UNPKG

tusktsk

Version:

TuskTsk - The Freedom Configuration Language. Query databases, use any syntax, never bow to any king!

1,755 lines (1,465 loc) 148 kB
/** * TuskLang Enhanced for JavaScript - The Freedom Parser * ===================================================== * "We don't bow to any king" - Support ALL syntax styles * * Features: * - Multiple grouping: [], {}, <> * - $global vs section-local variables * - Cross-file communication * - Database queries (with adapters) * - All @ operators * - Maximum flexibility */ class TuskLangEnhanced { constructor() { this.globalVariables = {}; this.sectionVariables = {}; this.currentSection = null; this.parsedData = {}; this.crossFileCache = {}; this.databaseAdapter = null; this.cache = new Map(); } /** * Set database adapter for @query operations */ setDatabaseAdapter(adapter) { this.databaseAdapter = adapter; } /** * Parse TuskLang content */ parse(content) { const lines = content.split('\n'); const result = {}; let position = 0; while (position < lines.length) { const line = lines[position].trim(); // Skip empty lines and comments if (!line || line.startsWith('#') || line.startsWith('//')) { position++; continue; } // Remove optional semicolon const cleanLine = line.replace(/;$/, ''); // Check for section declarations [] if (/^\[([a-zA-Z_]\w*)\]$/.test(cleanLine)) { const match = cleanLine.match(/^\[([a-zA-Z_]\w*)\]$/); this.currentSection = match[1]; result[this.currentSection] = {}; this.sectionVariables[this.currentSection] = {}; position++; continue; } // Check for angle bracket objects > if (/^([a-zA-Z_]\w*)\s*>$/.test(cleanLine)) { const match = cleanLine.match(/^([a-zA-Z_]\w*)\s*>$/); const obj = this.parseAngleBracketObject(lines, position, match[1]); if (this.currentSection) { result[this.currentSection][obj.key] = obj.value; } else { result[obj.key] = obj.value; } position = obj.newPosition; continue; } // Check for curly brace objects { if (/^([a-zA-Z_]\w*)\s*\{/.test(cleanLine)) { const match = cleanLine.match(/^([a-zA-Z_]\w*)\s*\{/); const obj = this.parseCurlyBraceObject(lines, position, match[1]); if (this.currentSection) { result[this.currentSection][obj.key] = obj.value; } else { result[obj.key] = obj.value; } position = obj.newPosition; continue; } // Parse key-value pairs if (/^([$]?[a-zA-Z_][\w-]*)\s*[:=]\s*(.+)$/.test(cleanLine)) { const match = cleanLine.match(/^([$]?[a-zA-Z_][\w-]*)\s*[:=]\s*(.+)$/); const key = match[1]; const value = this.parseValue(match[2].trim()); // Store in result if (this.currentSection) { result[this.currentSection][key] = value; // Store section-local variable if not global if (!key.startsWith('$')) { this.sectionVariables[this.currentSection][key] = value; } } else { result[key] = value; } // Store global variables if (key.startsWith('$')) { this.globalVariables[key.substring(1)] = value; } this.parsedData[key] = value; } position++; } return this.resolveReferences(result); } /** * Parse angle bracket object */ parseAngleBracketObject(lines, startPos, key) { let position = startPos + 1; const obj = {}; while (position < lines.length) { const line = lines[position].trim(); // End of angle bracket object if (line === '<') { return { key, value: obj, newPosition: position + 1 }; } // Skip empty lines and comments if (!line || line.startsWith('#')) { position++; continue; } // Remove optional semicolon const cleanLine = line.replace(/;$/, ''); // Parse nested content if (/^([$]?[a-zA-Z_][\w-]*)\s*[:=]\s*(.+)$/.test(cleanLine)) { const match = cleanLine.match(/^([$]?[a-zA-Z_][\w-]*)\s*[:=]\s*(.+)$/); obj[match[1]] = this.parseValue(match[2].trim()); } else if (/^([a-zA-Z_]\w*)\s*>$/.test(cleanLine)) { const match = cleanLine.match(/^([a-zA-Z_]\w*)\s*>$/); const nested = this.parseAngleBracketObject(lines, position, match[1]); obj[nested.key] = nested.value; position = nested.newPosition - 1; } else if (/^([a-zA-Z_]\w*)\s*\{/.test(cleanLine)) { const match = cleanLine.match(/^([a-zA-Z_]\w*)\s*\{/); const nested = this.parseCurlyBraceObject(lines, position, match[1]); obj[nested.key] = nested.value; position = nested.newPosition - 1; } position++; } return { key, value: obj, newPosition: position }; } /** * Parse curly brace object */ parseCurlyBraceObject(lines, startPos, key) { let position = startPos; const obj = {}; // Check if opening brace is on same line const firstLine = lines[position].trim(); const sameLine = firstLine.includes('{'); if (sameLine) { position++; } while (position < lines.length) { const line = lines[position].trim(); // End of object if (line === '}' || line.startsWith('}')) { return { key, value: obj, newPosition: position + 1 }; } // Skip empty lines and comments if (!line || line.startsWith('#')) { position++; continue; } // Remove optional semicolon const cleanLine = line.replace(/;$/, ''); // Parse nested content if (/^([$]?[a-zA-Z_][\w-]*)\s*[:=]\s*(.+)$/.test(cleanLine)) { const match = cleanLine.match(/^([$]?[a-zA-Z_][\w-]*)\s*[:=]\s*(.+)$/); obj[match[1]] = this.parseValue(match[2].trim()); } position++; } return { key, value: obj, newPosition: position }; } /** * Parse values with all enhancements */ parseValue(value) { // Basic types if (value === 'true') return true; if (value === 'false') return false; if (value === 'null') return null; // Numbers if (/^-?\d+(\.\d+)?$/.test(value)) { return value.includes('.') ? parseFloat(value) : parseInt(value); } // $variable references (global) if (/^\$([a-zA-Z_]\w*)$/.test(value)) { const match = value.match(/^\$([a-zA-Z_]\w*)$/); return this.globalVariables[match[1]] || null; } // Section-local variable references if (/^[a-zA-Z_]\w*$/.test(value) && this.currentSection && this.sectionVariables[this.currentSection]?.[value] !== undefined) { return this.sectionVariables[this.currentSection][value]; } // Cross-file references: @file.tsk.get('key') if (/^@([\w-]+)\.tsk\.get\(["']([^"']+)["']\)$/.test(value)) { const match = value.match(/^@([\w-]+)\.tsk\.get\(["']([^"']+)["']\)$/); return this.crossFileGet(match[1], match[2]); } // Cross-file set: @file.tsk.set('key', value) if (/^@([\w-]+)\.tsk\.set\(["']([^"']+)["'],\s*(.+)\)$/.test(value)) { const match = value.match(/^@([\w-]+)\.tsk\.set\(["']([^"']+)["'],\s*(.+)\)$/); return this.crossFileSet(match[1], match[2], this.parseValue(match[3])); } // @date function if (/^@date\(["']([^"']+)["']\)$/.test(value)) { const match = value.match(/^@date\(["']([^"']+)["']\)$/); return this.formatDate(match[1]); } // Ranges: 8888-9999 if (/^(\d+)-(\d+)$/.test(value)) { const match = value.match(/^(\d+)-(\d+)$/); return { min: parseInt(match[1]), max: parseInt(match[2]), type: 'range' }; } // @ operators if (/^@(\w+)\((.+)\)$/.test(value)) { const match = value.match(/^@(\w+)\((.+)\)$/); return this.executeOperator(match[1], match[2]); } // Arrays if (value.startsWith('[') && value.endsWith(']')) { try { return JSON.parse(value); } catch { // Simple array parsing const content = value.slice(1, -1); return content.split(',').map(item => this.parseValue(item.trim())); } } // Inline objects if (value.startsWith('{') && value.endsWith('}')) { try { return JSON.parse(value); } catch { // Simple object parsing const obj = {}; const content = value.slice(1, -1); const pairs = content.split(','); pairs.forEach(pair => { const [k, v] = pair.split(':').map(s => s.trim()); if (k && v) { obj[k.replace(/["']/g, '')] = this.parseValue(v); } }); return obj; } } // String values (remove quotes) if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) { return value.slice(1, -1); } // String concatenation if (value.includes(' + ')) { const parts = value.split(' + ').map(part => { const parsed = this.parseValue(part.trim()); return parsed !== null ? String(parsed) : ''; }); return parts.join(''); } // Conditional/ternary if (value.includes(' ? ') && value.includes(' : ')) { const [condition, rest] = value.split(' ? '); const [trueVal, falseVal] = rest.split(' : '); const condResult = this.evaluateCondition(condition.trim()); return condResult ? this.parseValue(trueVal.trim()) : this.parseValue(falseVal.trim()); } // Environment variables if (/^@env\(["']([^"']+)["'](?:,\s*(.+))?\)$/.test(value)) { const match = value.match(/^@env\(["']([^"']+)["'](?:,\s*(.+))?\)$/); const envVar = match[1]; const defaultVal = match[2] ? this.parseValue(match[2]) : null; return process.env[envVar] || defaultVal; } return value; } /** * Execute @ operators */ async executeOperator(operator, params) { switch (operator) { case 'variable': return this.executeVariableOperator(params); case 'query': return this.executeQuery(params); case 'cache': return this.executeCacheOperator(params); case 'learn': return this.executeLearnOperator(params); case 'optimize': return this.executeOptimizeOperator(params); case 'metrics': return this.executeMetricsOperator(params); case 'feature': return this.executeFeatureOperator(params); case 'if': return this.executeIfOperator(params); case 'switch': return this.executeSwitchOperator(params); case 'for': return this.executeForOperator(params); case 'while': return this.executeWhileOperator(params); case 'each': return this.executeEachOperator(params); case 'filter': return this.executeFilterOperator(params); case 'string': return this.executeStringOperator(params); case 'regex': return this.executeRegexOperator(params); case 'hash': return this.executeHashOperator(params); case 'base64': return this.executeBase64Operator(params); case 'xml': return this.executeXmlOperator(params); case 'yaml': return this.executeYamlOperator(params); case 'csv': return this.executeCsvOperator(params); case 'template': return this.executeTemplateOperator(params); case 'encrypt': return this.executeEncryptOperator(params); case 'decrypt': return this.executeDecryptOperator(params); case 'jwt': return this.executeJwtOperator(params); case 'email': return this.executeEmailOperator(params); case 'sms': return this.executeSmsOperator(params); case 'webhook': return this.executeWebhookOperator(params); case 'websocket': return this.executeWebSocketOperator(params); case 'graphql': return this.executeGraphQLOperator(params); case 'grpc': return this.executeGrpcOperator(params); case 'sse': return this.executeSseOperator(params); case 'nats': return this.executeNatsOperator(params); case 'amqp': return this.executeAmqpOperator(params); case 'kafka': return this.executeKafkaOperator(params); case 'etcd': return this.executeEtcdOperator(params); case 'elasticsearch': return this.executeElasticsearchOperator(params); case 'prometheus': return this.executePrometheusOperator(params); case 'jaeger': return this.executeJaegerOperator(params); case 'zipkin': return this.executeZipkinOperator(params); case 'grafana': return this.executeGrafanaOperator(params); case 'istio': return this.executeIstioOperator(params); case 'consul': return this.executeConsulOperator(params); case 'vault': return this.executeVaultOperator(params); case 'temporal': return this.executeTemporalOperator(params); case 'mongodb': return this.executeMongoDbOperator(params); case 'redis': return this.executeRedisOperator(params); case 'postgresql': return this.executePostgreSqlOperator(params); case 'mysql': return this.executeMySqlOperator(params); case 'influxdb': return this.executeInfluxDbOperator(params); case 'oauth': return this.executeOAuthOperator(params); case 'saml': return this.executeSamlOperator(params); case 'ldap': return this.executeLdapOperator(params); case 'kubernetes': return this.executeKubernetesOperator(params); case 'docker': return this.executeDockerOperator(params); case 'aws': return this.executeAwsOperator(params); case 'azure': return this.executeAzureOperator(params); case 'gcp': return this.executeGcpOperator(params); case 'terraform': return this.executeTerraformOperator(params); case 'ansible': return this.executeAnsibleOperator(params); case 'puppet': return this.executePuppetOperator(params); case 'chef': return this.executeChefOperator(params); case 'jenkins': return this.executeJenkinsOperator(params); case 'github': return this.executeGitHubOperator(params); case 'gitlab': return this.executeGitLabOperator(params); case 'logs': return this.executeLogsOperator(params); case 'alerts': return this.executeAlertsOperator(params); case 'health': return this.executeHealthOperator(params); case 'status': return this.executeStatusOperator(params); case 'uptime': return this.executeUptimeOperator(params); case 'slack': return this.executeSlackOperator(params); case 'teams': return this.executeTeamsOperator(params); case 'discord': return this.executeDiscordOperator(params); case 'rbac': return this.executeRbacOperator(params); case 'audit': return this.executeAuditOperator(params); case 'compliance': return this.executeComplianceOperator(params); case 'governance': return this.executeGovernanceOperator(params); case 'policy': return this.executePolicyOperator(params); case 'workflow': return this.executeWorkflowOperator(params); case 'ai': return this.executeAiOperator(params); case 'blockchain': return this.executeBlockchainOperator(params); case 'iot': return this.executeIoTOperator(params); case 'edge': return this.executeEdgeOperator(params); case 'quantum': return this.executeQuantumOperator(params); case 'neural': return this.executeNeuralOperator(params); case 'date': return this.executeDateOperator(params); case 'file': return this.executeFileOperator(params); case 'json': return this.executeJsonOperator(params); case 'env': // Already handled in parseValue return `@${operator}(${params})`; default: // Unknown operator return `@${operator}(${params})`; } } /** * Execute database query */ async executeQuery(params) { try { // Parse query parameters const match = params.match(/^["']([^"']+)["'](?:,\s*(.+))?$/); if (!match) { throw new Error('Invalid @query syntax. Expected: "sql", args'); } const sql = match[1]; const args = match[2] ? this.parseQueryArgs(match[2]) : []; // Real database implementation using SQLite3 as default const sqlite3 = require('sqlite3').verbose(); const path = require('path'); // Use configured database or default to memory const dbPath = process.env.DB_PATH || ':memory:'; const db = new sqlite3.Database(dbPath); return new Promise((resolve, reject) => { if (sql.trim().toLowerCase().startsWith('select')) { // SELECT query db.all(sql, args, (err, rows) => { if (err) { resolve({ success: false, error: err.message, data: [] }); } else { resolve({ success: true, data: rows, count: rows.length }); } }); } else { // INSERT, UPDATE, DELETE query db.run(sql, args, function(err) { if (err) { resolve({ success: false, error: err.message }); } else { resolve({ success: true, changes: this.changes, lastID: this.lastID }); } }); } }); } catch (error) { console.error('Query error:', error); return { success: false, error: error.message, data: [] }; } } /** * Cache operator */ executeCacheOperator(params) { const match = params.match(/^["']([^"']+)["'],\s*(.+)$/); if (!match) return null; const ttl = match[1]; const value = this.parseValue(match[2]); const key = JSON.stringify({ operator: 'cache', params, value }); // Check cache const cached = this.cache.get(key); if (cached && cached.expires > Date.now()) { return cached.value; } // Store in cache const ttlMs = this.parseTTL(ttl); this.cache.set(key, { value, expires: Date.now() + ttlMs }); return value; } /** * Learn operator (placeholder) */ executeLearnOperator(params) { const match = params.match(/^["']([^"']+)["'],\s*(.+)$/); if (!match) return null; const key = match[1]; const defaultValue = this.parseValue(match[2]); // In a real implementation, this would use ML return defaultValue; } /** * Optimize operator (placeholder) */ executeOptimizeOperator(params) { const match = params.match(/^["']([^"']+)["'],\s*(.+)$/); if (!match) return null; const param = match[1]; const initialValue = this.parseValue(match[2]); // In a real implementation, this would auto-tune return initialValue; } /** * Metrics operator (placeholder) */ executeMetricsOperator(params) { const match = params.match(/^["']([^"']+)["'](?:,\s*(.+))?$/); if (!match) return 0; const metric = match[1]; const value = match[2] ? this.parseValue(match[2]) : null; // In a real implementation, this would track metrics return value || 0; } /** * Feature flag operator */ executeFeatureOperator(params) { const feature = params.replace(/["']/g, ''); // In a real implementation, check feature flags return false; } /** * If operator - conditional expressions */ executeIfOperator(params) { try { // Parse condition and values: "condition ? trueValue : falseValue" const match = params.match(/^(.+)\s*\?\s*(.+)\s*:\s*(.+)$/); if (!match) { throw new Error('Invalid @if syntax. Expected: condition ? trueValue : falseValue'); } const condition = match[1].trim(); const trueValue = match[2].trim(); const falseValue = match[3].trim(); const result = this.evaluateCondition(condition); return result ? this.parseValue(trueValue) : this.parseValue(falseValue); } catch (error) { console.error('@if operator error:', error); return null; } } /** * Switch operator - switch statements */ executeSwitchOperator(params) { try { // Parse switch expression and cases: "expression { case1: value1, case2: value2, default: defaultValue }" const match = params.match(/^(.+)\s*\{([^}]+)\}$/); if (!match) { throw new Error('Invalid @switch syntax. Expected: expression { case1: value1, case2: value2, default: defaultValue }'); } const expression = this.parseValue(match[1].trim()); const casesStr = match[2].trim(); // Parse cases const cases = {}; const casePairs = casesStr.split(',').map(pair => pair.trim()); for (const pair of casePairs) { const [key, value] = pair.split(':').map(s => s.trim()); if (key && value) { const cleanKey = key.replace(/["']/g, ''); cases[cleanKey] = this.parseValue(value); } } // Find matching case or default if (cases[expression] !== undefined) { return cases[expression]; } return cases['default'] || null; } catch (error) { console.error('@switch operator error:', error); return null; } } /** * For operator - for loops */ executeForOperator(params) { try { // Parse for loop: "start, end, step, expression" const parts = params.split(',').map(p => p.trim()); if (parts.length < 3) { throw new Error('Invalid @for syntax. Expected: start, end, step, expression'); } const start = parseInt(this.parseValue(parts[0])); const end = parseInt(this.parseValue(parts[1])); const step = parseInt(this.parseValue(parts[2])); const expression = parts[3] || 'i'; const results = []; for (let i = start; i <= end; i += step) { // Set loop variable in global scope this.globalVariables[expression] = i; results.push(i); } return results; } catch (error) { console.error('@for operator error:', error); return []; } } /** * While operator - while loops */ executeWhileOperator(params) { try { // Parse while loop: "condition, expression, maxIterations" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @while syntax. Expected: condition, expression, maxIterations'); } const condition = parts[0]; const expression = parts[1]; const maxIterations = parts[2] ? parseInt(this.parseValue(parts[2])) : 1000; const results = []; let iterations = 0; while (this.evaluateCondition(condition) && iterations < maxIterations) { const result = this.parseValue(expression); results.push(result); iterations++; } return results; } catch (error) { console.error('@while operator error:', error); return []; } } /** * Each operator - array iteration */ executeEachOperator(params) { try { // Parse each: "array, expression" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @each syntax. Expected: array, expression'); } const array = this.parseValue(parts[0]); const expression = parts[1]; if (!Array.isArray(array)) { throw new Error('@each requires an array as first parameter'); } const results = []; for (let i = 0; i < array.length; i++) { // Set iteration variables this.globalVariables['item'] = array[i]; this.globalVariables['index'] = i; this.globalVariables['key'] = i; const result = this.parseValue(expression); results.push(result); } return results; } catch (error) { console.error('@each operator error:', error); return []; } } /** * Filter operator - array filtering */ executeFilterOperator(params) { try { // Parse filter: "array, condition" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @filter syntax. Expected: array, condition'); } const array = this.parseValue(parts[0]); const condition = parts[1]; if (!Array.isArray(array)) { throw new Error('@filter requires an array as first parameter'); } const results = []; for (let i = 0; i < array.length; i++) { // Set iteration variables this.globalVariables['item'] = array[i]; this.globalVariables['index'] = i; this.globalVariables['key'] = i; if (this.evaluateCondition(condition)) { results.push(array[i]); } } return results; } catch (error) { console.error('@filter operator error:', error); return []; } } /** * String operator - string manipulation */ executeStringOperator(params) { try { // Parse string operations: "operation, value, ...args" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @string syntax. Expected: operation, value, ...args'); } const operation = parts[0].replace(/["']/g, ''); const value = this.parseValue(parts[1]); const args = parts.slice(2).map(arg => this.parseValue(arg)); switch (operation) { case 'length': return String(value).length; case 'upper': return String(value).toUpperCase(); case 'lower': return String(value).toLowerCase(); case 'trim': return String(value).trim(); case 'substring': const start = args[0] || 0; const end = args[1]; return String(value).substring(start, end); case 'replace': const search = args[0]; const replace = args[1]; return String(value).replace(new RegExp(search, 'g'), replace); case 'split': const delimiter = args[0] || ','; return String(value).split(delimiter); case 'join': const separator = args[0] || ''; return Array.isArray(value) ? value.join(separator) : value; default: throw new Error(`Unknown string operation: ${operation}`); } } catch (error) { console.error('@string operator error:', error); return ''; } } /** * Regex operator - regular expressions */ executeRegexOperator(params) { try { // Parse regex operations: "operation, pattern, value, ...args" const parts = params.split(',').map(p => p.trim()); if (parts.length < 3) { throw new Error('Invalid @regex syntax. Expected: operation, pattern, value, ...args'); } const operation = parts[0].replace(/["']/g, ''); const pattern = parts[1].replace(/["']/g, ''); const value = this.parseValue(parts[2]); const args = parts.slice(3).map(arg => this.parseValue(arg)); const regex = new RegExp(pattern, args[0] || ''); switch (operation) { case 'test': return regex.test(String(value)); case 'match': return String(value).match(regex); case 'replace': const replacement = args[1] || ''; return String(value).replace(regex, replacement); case 'split': return String(value).split(regex); default: throw new Error(`Unknown regex operation: ${operation}`); } } catch (error) { console.error('@regex operator error:', error); return null; } } /** * Hash operator - hashing functions */ executeHashOperator(params) { try { // Parse hash operations: "algorithm, value" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @hash syntax. Expected: algorithm, value'); } const algorithm = parts[0].replace(/["']/g, ''); const value = this.parseValue(parts[1]); // Simple hash implementation (in production, use crypto library) switch (algorithm) { case 'md5': return this.simpleHash(String(value), 'md5'); case 'sha1': return this.simpleHash(String(value), 'sha1'); case 'sha256': return this.simpleHash(String(value), 'sha256'); default: throw new Error(`Unknown hash algorithm: ${algorithm}`); } } catch (error) { console.error('@hash operator error:', error); return ''; } } /** * Simple hash implementation */ simpleHash(str, algorithm) { let hash = 0; for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; // Convert to 32-bit integer } return Math.abs(hash).toString(16); } /** * Base64 operator - base64 encoding/decoding */ executeBase64Operator(params) { try { // Parse base64 operations: "operation, value" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @base64 syntax. Expected: operation, value'); } const operation = parts[0].replace(/["']/g, ''); const value = this.parseValue(parts[1]); switch (operation) { case 'encode': return Buffer.from(String(value)).toString('base64'); case 'decode': return Buffer.from(String(value), 'base64').toString('utf8'); default: throw new Error(`Unknown base64 operation: ${operation}`); } } catch (error) { console.error('@base64 operator error:', error); return ''; } } /** * XML operator - XML parsing */ executeXmlOperator(params) { try { // Parse XML operations: "operation, value, ...args" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @xml syntax. Expected: operation, value, ...args'); } const operation = parts[0].replace(/["']/g, ''); const value = this.parseValue(parts[1]); switch (operation) { case 'parse': // Simple XML parsing (in production, use proper XML parser) return this.simpleXmlParse(String(value)); case 'stringify': return this.simpleXmlStringify(value); default: throw new Error(`Unknown XML operation: ${operation}`); } } catch (error) { console.error('@xml operator error:', error); return null; } } /** * Simple XML parsing */ simpleXmlParse(xml) { // Very basic XML parsing - in production use a proper XML parser const result = {}; const tagRegex = /<(\w+)[^>]*>(.*?)<\/\1>/g; let match; while ((match = tagRegex.exec(xml)) !== null) { result[match[1]] = match[2]; } return result; } /** * Simple XML stringification */ simpleXmlStringify(obj) { if (typeof obj !== 'object') { return `<value>${obj}</value>`; } let xml = ''; for (const [key, value] of Object.entries(obj)) { xml += `<${key}>${value}</${key}>`; } return xml; } /** * YAML operator - YAML parsing */ executeYamlOperator(params) { try { // Parse YAML operations: "operation, value" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @yaml syntax. Expected: operation, value'); } const operation = parts[0].replace(/["']/g, ''); const value = this.parseValue(parts[1]); switch (operation) { case 'parse': // Simple YAML parsing (in production, use proper YAML parser) return this.simpleYamlParse(String(value)); case 'stringify': return this.simpleYamlStringify(value); default: throw new Error(`Unknown YAML operation: ${operation}`); } } catch (error) { console.error('@yaml operator error:', error); return null; } } /** * Simple YAML parsing */ simpleYamlParse(yaml) { // Very basic YAML parsing - in production use a proper YAML parser const result = {}; const lines = yaml.split('\n'); for (const line of lines) { const match = line.match(/^(\w+):\s*(.+)$/); if (match) { result[match[1]] = match[2].trim(); } } return result; } /** * Simple YAML stringification */ simpleYamlStringify(obj) { if (typeof obj !== 'object') { return String(obj); } let yaml = ''; for (const [key, value] of Object.entries(obj)) { yaml += `${key}: ${value}\n`; } return yaml.trim(); } /** * CSV operator - CSV processing */ executeCsvOperator(params) { try { // Parse CSV operations: "operation, value, ...args" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @csv syntax. Expected: operation, value, ...args'); } const operation = parts[0].replace(/["']/g, ''); const value = this.parseValue(parts[1]); const args = parts.slice(2).map(arg => this.parseValue(arg)); switch (operation) { case 'parse': const delimiter = args[0] || ','; return this.parseCsv(String(value), delimiter); case 'stringify': const separator = args[0] || ','; return this.stringifyCsv(value, separator); default: throw new Error(`Unknown CSV operation: ${operation}`); } } catch (error) { console.error('@csv operator error:', error); return null; } } /** * Parse CSV string */ parseCsv(csv, delimiter = ',') { const lines = csv.split('\n'); const result = []; for (const line of lines) { if (line.trim()) { const fields = line.split(delimiter).map(field => field.trim()); result.push(fields); } } return result; } /** * Stringify to CSV */ stringifyCsv(data, delimiter = ',') { if (!Array.isArray(data)) { return String(data); } return data.map(row => { if (Array.isArray(row)) { return row.join(delimiter); } return String(row); }).join('\n'); } /** * Template operator - template engine */ executeTemplateOperator(params) { try { // Parse template operations: "template, data" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @template syntax. Expected: template, data'); } const template = this.parseValue(parts[0]); const data = this.parseValue(parts[1]); return this.renderTemplate(String(template), data); } catch (error) { console.error('@template operator error:', error); return ''; } } /** * Render template with data */ renderTemplate(template, data) { let result = template; if (typeof data === 'object') { for (const [key, value] of Object.entries(data)) { const placeholder = new RegExp(`\\{\\{${key}\\}\\}`, 'g'); result = result.replace(placeholder, String(value)); } } return result; } /** * Encrypt operator - data encryption */ executeEncryptOperator(params) { try { // Parse encrypt operations: "algorithm, value, key" const parts = params.split(',').map(p => p.trim()); if (parts.length < 3) { throw new Error('Invalid @encrypt syntax. Expected: algorithm, value, key'); } const algorithm = parts[0].replace(/["']/g, ''); const value = this.parseValue(parts[1]); const key = this.parseValue(parts[2]); // Simple encryption (in production, use proper crypto library) return this.simpleEncrypt(String(value), String(key), algorithm); } catch (error) { console.error('@encrypt operator error:', error); return ''; } } /** * Simple encryption implementation */ simpleEncrypt(text, key, algorithm) { // Very basic encryption - in production use proper crypto let result = ''; for (let i = 0; i < text.length; i++) { const charCode = text.charCodeAt(i) ^ key.charCodeAt(i % key.length); result += String.fromCharCode(charCode); } return Buffer.from(result).toString('base64'); } /** * Decrypt operator - data decryption */ executeDecryptOperator(params) { try { // Parse decrypt operations: "algorithm, value, key" const parts = params.split(',').map(p => p.trim()); if (parts.length < 3) { throw new Error('Invalid @decrypt syntax. Expected: algorithm, value, key'); } const algorithm = parts[0].replace(/["']/g, ''); const value = this.parseValue(parts[1]); const key = this.parseValue(parts[2]); // Simple decryption (in production, use proper crypto library) return this.simpleDecrypt(String(value), String(key), algorithm); } catch (error) { console.error('@decrypt operator error:', error); return ''; } } /** * Simple decryption implementation */ simpleDecrypt(encryptedText, key, algorithm) { // Very basic decryption - in production use proper crypto const decoded = Buffer.from(encryptedText, 'base64').toString(); let result = ''; for (let i = 0; i < decoded.length; i++) { const charCode = decoded.charCodeAt(i) ^ key.charCodeAt(i % key.length); result += String.fromCharCode(charCode); } return result; } /** * JWT operator - JWT tokens */ executeJwtOperator(params) { try { // Parse JWT operations: "operation, value, ...args" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @jwt syntax. Expected: operation, value, ...args'); } const operation = parts[0].replace(/["']/g, ''); const value = this.parseValue(parts[1]); const args = parts.slice(2).map(arg => this.parseValue(arg)); switch (operation) { case 'encode': const secret = args[0] || 'default-secret'; return this.simpleJwtEncode(value, secret); case 'decode': return this.simpleJwtDecode(String(value)); case 'verify': const verifySecret = args[0] || 'default-secret'; return this.simpleJwtVerify(String(value), verifySecret); default: throw new Error(`Unknown JWT operation: ${operation}`); } } catch (error) { console.error('@jwt operator error:', error); return null; } } /** * Simple JWT encoding */ simpleJwtEncode(payload, secret) { const header = { alg: 'HS256', typ: 'JWT' }; const encodedHeader = Buffer.from(JSON.stringify(header)).toString('base64'); const encodedPayload = Buffer.from(JSON.stringify(payload)).toString('base64'); const signature = this.simpleHash(encodedHeader + '.' + encodedPayload + secret, 'sha256'); return `${encodedHeader}.${encodedPayload}.${signature}`; } /** * Simple JWT decoding */ simpleJwtDecode(token) { const parts = token.split('.'); if (parts.length !== 3) { throw new Error('Invalid JWT token format'); } try { return JSON.parse(Buffer.from(parts[1], 'base64').toString()); } catch { throw new Error('Invalid JWT payload'); } } /** * Simple JWT verification */ simpleJwtVerify(token, secret) { try { const parts = token.split('.'); if (parts.length !== 3) { return false; } const expectedSignature = this.simpleHash(parts[0] + '.' + parts[1] + secret, 'sha256'); return parts[2] === expectedSignature; } catch { return false; } } /** * Email operator - email sending */ async executeEmailOperator(params) { try { // Parse email operations: "to, subject, body, ...options" const parts = params.split(',').map(p => p.trim()); if (parts.length < 3) { throw new Error('Invalid @email syntax. Expected: to, subject, body, ...options'); } const to = this.parseValue(parts[0]); const subject = this.parseValue(parts[1]); const body = this.parseValue(parts[2]); // Real email implementation using Node.js built-in modules const nodemailer = require('nodemailer'); // Create transporter (in production, use real SMTP settings) const transporter = nodemailer.createTransporter({ host: process.env.SMTP_HOST || 'localhost', port: process.env.SMTP_PORT || 587, secure: false, auth: { user: process.env.SMTP_USER || 'user@example.com', pass: process.env.SMTP_PASS || 'password' } }); // Send email const mailOptions = { from: process.env.SMTP_FROM || 'noreply@example.com', to: to, subject: subject, text: body, html: body }; const result = await transporter.sendMail(mailOptions); return { success: true, messageId: result.messageId, response: result.response }; } catch (error) { console.error('@email operator error:', error); return { success: false, error: error.message }; } } /** * SMS operator - SMS messaging */ async executeSmsOperator(params) { try { // Parse SMS operations: "to, message, ...options" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @sms syntax. Expected: to, message, ...options'); } const to = this.parseValue(parts[0]); const message = this.parseValue(parts[1]); // Real SMS implementation using Twilio API const twilio = require('twilio'); const accountSid = process.env.TWILIO_ACCOUNT_SID || 'your_account_sid'; const authToken = process.env.TWILIO_AUTH_TOKEN || 'your_auth_token'; const fromNumber = process.env.TWILIO_FROM_NUMBER || '+1234567890'; const client = twilio(accountSid, authToken); const result = await client.messages.create({ body: message, from: fromNumber, to: to }); return { success: true, messageId: result.sid, status: result.status, price: result.price }; } catch (error) { console.error('@sms operator error:', error); return { success: false, error: error.message }; } } /** * Webhook operator - webhook handling */ executeWebhookOperator(params) { try { // Parse webhook operations: "url, method, data, ...options" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @webhook syntax. Expected: url, method, data, ...options'); } const url = this.parseValue(parts[0]); const method = parts[1] ? this.parseValue(parts[1]) : 'POST'; const data = parts[2] ? this.parseValue(parts[2]) : {}; // Real HTTP request implementation const https = require('https'); const http = require('http'); const urlObj = new URL(url); const postData = JSON.stringify(data); const options = { hostname: urlObj.hostname, port: urlObj.port || (urlObj.protocol === 'https:' ? 443 : 80), path: urlObj.pathname + urlObj.search, method: method, headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData), 'User-Agent': 'TuskLang/1.0' } }; return new Promise((resolve, reject) => { const req = (urlObj.protocol === 'https:' ? https : http).request(options, (res) => { let responseData = ''; res.on('data', (chunk) => { responseData += chunk; }); res.on('end', () => { resolve({ success: res.statusCode >= 200 && res.statusCode < 300, statusCode: res.statusCode, headers: res.headers, data: responseData }); }); }); req.on('error', (error) => { resolve({ success: false, error: error.message }); }); req.write(postData); req.end(); }); } catch (error) { console.error('@webhook operator error:', error); return { success: false, error: error.message }; } } /** * WebSocket operator - WebSocket connections */ async executeWebSocketOperator(params) { try { // Parse WebSocket operations: "url, message, ...options" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @websocket syntax. Expected: url, message, ...options'); } const url = this.parseValue(parts[0]); const message = this.parseValue(parts[1]); const options = parts[2] ? this.parseValue(parts[2]) : {}; // Dynamic import for WebSocket const WebSocket = await import('ws').then(m => m.default); return new Promise((resolve) => { const ws = new WebSocket(url, options); ws.on('open', () => { ws.send(message); resolve({ success: true, connected: true, sent: true }); }); ws.on('message', (data) => { resolve({ success: true, connected: true, received: data.toString() }); ws.close(); }); ws.on('error', (error) => { resolve({ success: false, error: error.message }); }); ws.on('close', () => { resolve({ success: true, connected: false, closed: true }); }); // Timeout after 10 seconds setTimeout(() => { ws.close(); resolve({ success: false, error: 'Connection timeout' }); }, 10000); }); } catch (error) { console.error('@websocket operator error:', error); return { success: false, error: error.message }; } } /** * GraphQL operator - GraphQL client */ async executeGraphQLOperator(params) { try { // Parse GraphQL operations: "url, query, variables, ...options" const parts = params.split(',').map(p => p.trim()); if (parts.length < 2) { throw new Error('Invalid @graphql syntax. Expected: url, query, variables, ...options'); } const url = this.parseValue(parts[0]); const query = this.parseValue(parts[1]); const variables = parts[2] ? this.parseValue(parts[2]) : {}; const options = parts[3] ? this.parseValue(parts[3]) : {}; const https = require('https'); const http = require('http'); const postData = JSON.stringify({ query: query, variables: variables, ...options }); const urlObj = new URL(url); const isHttps = urlObj.protocol === 'https:'; const client = isHttps ? https : http; const requestOptions = { hostname: urlObj.hostname, port: urlObj.port || (isHttps ? 443 : 80), path: urlObj.pathname + urlObj.search, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData), ...options.headers } }; return new Promise((resolve) => { const req = client.request(requestOptions, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { try { const result = JSON.parse(data); resolve({ success: true, data: result }); } catch (error) { resolve({ success: false, error: 'Invalid JSON response' }); } }); }); req.on('error', (error) => { resolve({ success: false, error: error.message }); }); req.write(postData); req.end(); }); } catch (error) { console.error('@graphql operator error:', error); return { success: false, error: error.message }; } } /** * gRPC operator - gRPC communication */ executeGrpcOperator(params) { try { // Parse gRPC operations: "url, method, data, ...options" const parts = params.split(',').map(p => p.trim()); if (parts.length < 3) { throw new Error('Invalid @grpc syntax. Expected: url, method, data, ...options'); } const url = this.pa