From 97665937d54380b4f8df0e7e6cfb6a13175cc05b Mon Sep 17 00:00:00 2001 From: Himanshu Date: Tue, 3 Feb 2026 21:43:18 +0530 Subject: [PATCH] feat: integrate esbuild for bundling providers and update dependencies --- build-bundled.js | 528 ++++++++++++---------------------------------- package-lock.json | 485 ++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 3 files changed, 620 insertions(+), 394 deletions(-) diff --git a/build-bundled.js b/build-bundled.js index cb67bf3..5dcb9e8 100644 --- a/build-bundled.js +++ b/build-bundled.js @@ -1,432 +1,172 @@ +const esbuild = require("esbuild"); const fs = require("fs"); const path = require("path"); -const { execSync } = require("child_process"); const { minify } = require("terser"); -// Build configuration -const PROVIDERS_DIR = "./providers"; -const DIST_DIR = "./dist"; -const TEMP_DIR = "./temp-build"; +const SKIP_MINIFY = process.env.SKIP_MINIFY === "true"; -// Colors for console output -const colors = { - reset: "\x1b[0m", - bright: "\x1b[1m", - green: "\x1b[32m", - red: "\x1b[31m", - yellow: "\x1b[33m", - blue: "\x1b[34m", - magenta: "\x1b[35m", - cyan: "\x1b[36m", -}; +// Find all provider directories +const providersDir = path.join(__dirname, "providers"); +const providerDirs = fs + .readdirSync(providersDir, { withFileTypes: true }) + .filter( + (dirent) => + dirent.isDirectory() && !dirent.name.startsWith(".") && dirent.name !== "extractors", + ) + .map((dirent) => dirent.name); -const log = { - info: (msg) => console.log(`${colors.blue}ℹ${colors.reset} ${msg}`), - success: (msg) => console.log(`${colors.green}✅${colors.reset} ${msg}`), - error: (msg) => console.log(`${colors.red}❌${colors.reset} ${msg}`), - warning: (msg) => console.log(`${colors.yellow}⚠️${colors.reset} ${msg}`), - build: (msg) => console.log(`${colors.magenta}🔨${colors.reset} ${msg}`), - file: (msg) => console.log(`${colors.cyan}📄${colors.reset} ${msg}`), -}; +console.log(`Found ${providerDirs.length} providers to build`); -/** - * Bundled provider builder - creates self-contained JS files without imports - */ -class BundledProviderBuilder { - constructor() { - this.startTime = Date.now(); - this.providers = []; +async function buildProvider(providerName) { + const providerPath = path.join(providersDir, providerName); + const distPath = path.join(__dirname, "dist", providerName); + + // Create dist directory + if (!fs.existsSync(distPath)) { + fs.mkdirSync(distPath, { recursive: true }); } - /** - * Clean the dist and temp directories - */ - cleanDirs() { - if (fs.existsSync(DIST_DIR)) { - fs.rmSync(DIST_DIR, { recursive: true, force: true }); + const modules = ["catalog", "posts", "meta", "stream", "episodes"]; + const results = []; + + for (const moduleName of modules) { + const modulePath = path.join(providerPath, `${moduleName}.ts`); + + if (!fs.existsSync(modulePath)) { + continue; } - fs.mkdirSync(DIST_DIR, { recursive: true }); - - if (fs.existsSync(TEMP_DIR)) { - fs.rmSync(TEMP_DIR, { recursive: true, force: true }); - } - fs.mkdirSync(TEMP_DIR, { recursive: true }); - } - - /** - * Discover all provider directories (excluding extractors and utility files) - */ - discoverProviders() { - const items = fs.readdirSync(PROVIDERS_DIR, { withFileTypes: true }); - const excludeDirs = ["extractors", "extractors copy"]; - - this.providers = items - .filter((item) => item.isDirectory()) - .filter((item) => !item.name.startsWith(".")) - .filter((item) => !excludeDirs.includes(item.name)) - .map((item) => item.name); - - log.info( - `Found ${this.providers.length} providers: ${this.providers.join(", ")}`, - ); - } - - /** - * Compile TypeScript to JavaScript first - */ - compileTypeScript() { - log.build("Compiling TypeScript files..."); try { - execSync("npx tsc", { - stdio: "pipe", - encoding: "utf8", + // Use esbuild to bundle the module + const result = await esbuild.build({ + entryPoints: [modulePath], + bundle: true, + platform: "node", + format: "cjs", + target: "es2015", + write: false, + external: [], // Bundle everything + minify: false, // We'll minify separately if needed + keepNames: true, + treeShaking: true, + outfile: `${moduleName}.js`, }); - return true; - } catch (error) { - log.error("TypeScript compilation failed:"); - if (error.stdout) console.log(error.stdout); - if (error.stderr) console.log(error.stderr); - return false; - } - } - /** - * Bundle each provider module to be self-contained - * This inlines all imports from extractors into the provider files - */ - bundleProviders() { - log.build("Bundling provider modules..."); + let code = result.outputFiles[0].text; - for (const provider of this.providers) { - const providerDistDir = path.join(DIST_DIR, provider); - - if (!fs.existsSync(providerDistDir)) { - continue; - } - - const files = [ - "stream.js", - "catalog.js", - "posts.js", - "meta.js", - "episodes.js", - ]; - - for (const file of files) { - const filePath = path.join(providerDistDir, file); - if (fs.existsSync(filePath)) { - this.bundleFile(filePath, provider); - } - } - } - } - - /** - * Bundle a single file by inlining all local imports - */ - bundleFile(filePath, provider) { - let content = fs.readFileSync(filePath, "utf8"); - - // Find all require statements - both destructuring and non-destructuring patterns - // Pattern 1: const { x, y } = require("path") - const destructuringRegex = - /(?:const|let|var)\s+\{([^}]+)\}\s*=\s*require\s*\(\s*["']([^"']+)["']\s*\);?/g; - // Pattern 2: const hubcloud_1 = require("path") - const simpleRequireRegex = - /(?:const|let|var)\s+(\w+)\s*=\s*require\s*\(\s*["']([^"']+)["']\s*\);?/g; - - const imports = []; - let match; - - while ((match = destructuringRegex.exec(content)) !== null) { - imports.push({ - full: match[0], - names: match[1], - varName: null, - path: match[2], - isDestructuring: true, - }); - } - - while ((match = simpleRequireRegex.exec(content)) !== null) { - // Skip if already matched by destructuring regex - if (imports.some((i) => i.full === match[0])) continue; - imports.push({ - full: match[0], - names: null, - varName: match[1], - path: match[2], - isDestructuring: false, - }); - } - - // Process each import - for (const imp of imports) { - // Skip external modules (axios, cheerio, etc.) - they come from context - if (!imp.path.startsWith(".") && !imp.path.startsWith("/")) { - // Remove the require statement for external modules - content = content.replace(imp.full, `// External: ${imp.path}`); - continue; - } - - // Resolve the import path - const importDir = path.dirname(filePath); - let resolvedPath = path.resolve(importDir, imp.path); - - // Add .js extension if needed - if (!resolvedPath.endsWith(".js")) { - resolvedPath += ".js"; - } - - if (fs.existsSync(resolvedPath)) { - // Read the imported file - let importedContent = fs.readFileSync(resolvedPath, "utf8"); - - // Remove exports.X = X pattern and just keep the functions - importedContent = importedContent.replace( - /exports\.\w+\s*=\s*\w+;?/g, - "", + // Post-process the code for React Native compatibility + // Remove require statements for built-in modules that aren't available + code = code.replace(/require\(['"]node:.*?['"]\)/g, "{}"); + + // Fix CommonJS exports for React Native's ProviderManager execution context + // The ProviderManager only has `exports` object, not `module` + + // Extract what's being exported by looking at the __export call + // Pattern: __export(xxx_exports, { funcName: () => funcName, ... }); + const exportMatch = code.match(/__export\((\w+),\s*\{([^}]+)\}\);/); + + if (exportMatch) { + const exportsVar = exportMatch[1]; + const exportsContent = exportMatch[2]; + + // Parse the export entries like "funcName: () => funcName" + const exportEntries = exportsContent + .split(',') + .map(entry => { + const match = entry.trim().match(/(\w+):\s*\(\)\s*=>\s*(\w+)/); + return match ? match[1] : null; + }) + .filter(Boolean); + + // Replace module.exports pattern + code = code.replace( + /module\.exports\s*=\s*__toCommonJS\((\w+)\);/g, + '' ); - - // Remove Object.defineProperty exports - importedContent = importedContent.replace( - /Object\.defineProperty\(exports,\s*"__esModule"[^;]+;/g, - "", + + // Add direct exports assignments at the end + const directExports = exportEntries + .map(name => `exports.${name} = ${name};`) + .join('\n'); + + // Add the exports before the final comment + code = code.replace( + /\/\/ Annotate the CommonJS export names for ESM import in node:/, + `${directExports}\n// Annotate the CommonJS export names for ESM import in node:` ); - - // Remove require statements from imported file too (they use context) - importedContent = importedContent.replace( - /(?:const|let|var)\s+\{[^}]+\}\s*=\s*require\s*\(\s*["'][^"']+["']\s*\);?/g, - "", - ); - importedContent = importedContent.replace( - /(?:const|let|var)\s+\w+\s*=\s*require\s*\(\s*["'][^"']+["']\s*\);?/g, - "", - ); - - // Clean up the content - importedContent = importedContent.replace(/"use strict";?/g, ""); - - // Check if this is an extractor file - if ( - imp.path.includes("extractor") || - resolvedPath.includes("extractor") - ) { - // Insert the extractor function at the top of the file - content = content.replace( - imp.full, - `// Inlined from: ${imp.path}\n${importedContent.trim()}`, - ); - - // For non-destructuring imports, we need to replace function calls - // TypeScript outputs: (0, hubcloud_1.hubcloudExtractor)(...) - // We need to replace with just: hubcloudExtractor(...) - if (!imp.isDestructuring && imp.varName) { - // Find the exported function name - look for exports.funcName or function funcNameExtractor - // The exports pattern looks like: exports.hubcloudExtractor = hubcloudExtractor; - const exportsMatch = importedContent.match( - /exports\.(\w+Extractor)\s*=/, - ); - // Also try matching the function definition directly - const funcDefMatch = importedContent.match( - /function\s+(\w+Extractor)\s*\(/, - ); - const funcName = exportsMatch?.[1] || funcDefMatch?.[1]; - - if (funcName) { - // Replace (0, varName.funcName) or (0,varName.funcName) with just funcName - const callPattern = new RegExp( - `\\(0,\\s*${imp.varName}\\.${funcName}\\)`, - "g", - ); - content = content.replace(callPattern, funcName); - // Also replace varName.funcName (without the (0, ) wrapper) - const simpleCallPattern = new RegExp( - `${imp.varName}\\.${funcName}`, - "g", - ); - content = content.replace(simpleCallPattern, funcName); - } - } - } else if (imp.path.includes("types")) { - // Types are not needed at runtime, just remove the import - content = content.replace(imp.full, `// Types removed: ${imp.path}`); - } else { - // Other local imports - inline them - content = content.replace( - imp.full, - `// Inlined from: ${imp.path}\n${importedContent.trim()}`, - ); - } - } else { - // File doesn't exist, comment out the import - content = content.replace(imp.full, `// Not found: ${imp.path}`); } - } - - // Clean up the content - content = content.replace(/"use strict";?/g, ""); - content = content.replace( - /Object\.defineProperty\(exports,\s*"__esModule"[^;]+;/g, - "", - ); - - // Write the bundled file - fs.writeFileSync(filePath, content); - } - - /** - * Minify all JavaScript files - */ - async minifyFiles() { - const keepConsole = process.env.KEEP_CONSOLE === "true"; - log.build( - `Minifying JavaScript files... ${ - keepConsole ? "(keeping console logs)" : "(removing console logs)" - }`, - ); - - const minifyFile = async (filePath) => { - try { - const code = fs.readFileSync(filePath, "utf8"); - const result = await minify(code, { + + // Also handle the "0 && (module.exports = {...})" pattern at the end + code = code.replace(/0\s*&&\s*\(module\.exports\s*=\s*\{[^}]*\}\);?/g, ""); + + // Minify if not skipped + if (!SKIP_MINIFY) { + const minified = await minify(code, { compress: { - drop_console: !keepConsole, - drop_debugger: true, - pure_funcs: keepConsole - ? ["console.debug"] - : [ - "console.debug", - "console.log", - "console.info", - "console.warn", - ], + drop_console: false, + passes: 2, + }, + mangle: { + keep_fnames: false, }, - mangle: false, format: { comments: false, }, }); - if (result.code) { - fs.writeFileSync(filePath, result.code); - return true; - } - return false; - } catch (error) { - log.error(`Error minifying ${filePath}: ${error.message}`); - return false; - } - }; - - const findJsFiles = (dir) => { - const files = []; - if (!fs.existsSync(dir)) return files; - - const items = fs.readdirSync(dir, { withFileTypes: true }); - for (const item of items) { - const fullPath = path.join(dir, item.name); - if (item.isDirectory()) { - files.push(...findJsFiles(fullPath)); - } else if (item.isFile() && item.name.endsWith(".js")) { - files.push(fullPath); + if (minified.code) { + code = minified.code; } } - return files; - }; - const jsFiles = findJsFiles(DIST_DIR); - let minifiedCount = 0; - let totalSizeBefore = 0; - let totalSizeAfter = 0; + // Write the output + const outputPath = path.join(distPath, `${moduleName}.js`); + fs.writeFileSync(outputPath, code); - for (const filePath of jsFiles) { - const statsBefore = fs.statSync(filePath); - totalSizeBefore += statsBefore.size; + results.push({ + moduleName, + size: code.length, + }); - const success = await minifyFile(filePath); - if (success) { - const statsAfter = fs.statSync(filePath); - totalSizeAfter += statsAfter.size; - minifiedCount++; - } - } - - const compressionRatio = - totalSizeBefore > 0 - ? ( - ((totalSizeBefore - totalSizeAfter) / totalSizeBefore) * - 100 - ).toFixed(1) - : 0; - - log.success( - `Minified ${minifiedCount}/${jsFiles.length} files. ` + - `Size reduced by ${compressionRatio}% (${totalSizeBefore} → ${totalSizeAfter} bytes)`, - ); - } - - /** - * Clean up temp directory - */ - cleanup() { - if (fs.existsSync(TEMP_DIR)) { - fs.rmSync(TEMP_DIR, { recursive: true, force: true }); + console.log( + `✓ ${providerName}/${moduleName}.js (${(code.length / 1024).toFixed(1)}kb)`, + ); + } catch (error) { + console.error(`✗ Error building ${providerName}/${moduleName}:`, error.message); } } - /** - * Build everything - */ - async build() { - const isWatchMode = process.env.NODE_ENV === "development"; - - if (isWatchMode) { - console.log( - `\n${colors.cyan}🔄 Auto-build triggered${colors.reset} ${new Date().toLocaleTimeString()}`, - ); - } else { - console.log( - `\n${colors.bright}🚀 Starting bundled provider build...${colors.reset}\n`, - ); - } - - this.cleanDirs(); - this.discoverProviders(); - - const compiled = this.compileTypeScript(); - if (!compiled) { - log.error("Build failed due to compilation errors"); - process.exit(1); - } - - this.bundleProviders(); - - if (!process.env.SKIP_MINIFY) { - await this.minifyFiles(); - } else { - log.info("Skipping minification (SKIP_MINIFY=true)"); - } - - this.cleanup(); - - const buildTime = Date.now() - this.startTime; - log.success(`Build completed in ${buildTime}ms`); - - if (isWatchMode) { - console.log(`${colors.green}👀 Watching for changes...${colors.reset}\n`); - } else { - console.log( - `${colors.bright}✨ Build completed successfully!${colors.reset}\n`, - ); - } - } + return { providerName, modules: results }; } -// Run the build -const builder = new BundledProviderBuilder(); -builder.build().catch((error) => { +async function buildAll() { + const startTime = Date.now(); + console.log(`Building providers${SKIP_MINIFY ? " (without minification)" : ""}...\n`); + + // Clear dist directory + const distDir = path.join(__dirname, "dist"); + if (fs.existsSync(distDir)) { + fs.rmSync(distDir, { recursive: true, force: true }); + } + fs.mkdirSync(distDir, { recursive: true }); + + // Build all providers + const results = await Promise.all(providerDirs.map(buildProvider)); + + const totalModules = results.reduce((sum, r) => sum + r.modules.length, 0); + const totalSize = results.reduce( + (sum, r) => sum + r.modules.reduce((s, m) => s + m.size, 0), + 0, + ); + + const endTime = Date.now(); + console.log( + `\n✓ Built ${totalModules} modules from ${providerDirs.length} providers in ${((endTime - startTime) / 1000).toFixed(2)}s`, + ); + console.log(` Total size: ${(totalSize / 1024).toFixed(1)}kb`); +} + +buildAll().catch((error) => { console.error("Build failed:", error); process.exit(1); }); diff --git a/package-lock.json b/package-lock.json index bdf6767..8bc9ea0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "concurrently": "^8.2.2", "cors": "^2.8.5", "cross-env": "^7.0.3", + "esbuild": "^0.27.2", "express": "^4.21.2", "nodemon": "^3.1.10", "terser": "^5.43.1", @@ -37,6 +38,448 @@ "node": ">=6.9.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@isaacs/balanced-match": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", @@ -1024,6 +1467,48 @@ "node": ">= 0.4" } }, + "node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", diff --git a/package.json b/package.json index d42910e..d807b9e 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "concurrently": "^8.2.2", "cors": "^2.8.5", "cross-env": "^7.0.3", + "esbuild": "^0.27.2", "express": "^4.21.2", "nodemon": "^3.1.10", "terser": "^5.43.1",