@smushytaco/custompatch
Version:
Tool for patching buggy NPM packages instead of forking them
1 lines • 16.9 kB
Source Map (JSON)
{"version":3,"file":"patch-utilities.mjs","sources":["../src/patch-utilities.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'pathe';\nimport {\n createTwoFilesPatch,\n parsePatch,\n reversePatch,\n applyPatch\n} from 'diff';\nimport pc from 'picocolors';\nimport { PackageConfig } from './types.js';\nimport {\n ensureDirectoryExists,\n pathNormalize,\n readFileContent\n} from './file-utilities.js';\nimport {\n programOptions,\n currentDirectory,\n temporaryDirectory,\n patchDirectory\n} from './variables.js';\n\nexport function createPatch(\n packageName: string,\n pathname: string,\n patch: fs.WriteStream\n): void {\n const newFile = path.join(\n currentDirectory,\n 'node_modules',\n packageName,\n pathname\n );\n const oldFile = path.join(temporaryDirectory, packageName, pathname);\n const oldString = fs.existsSync(oldFile) ? readFileContent(oldFile) : '';\n const newString = readFileContent(newFile);\n if (pathname === 'package.json' && !programOptions.all) return; // Skip \"package.json\"\n if (oldString !== newString) {\n patch.write(\n createTwoFilesPatch(\n oldFile.replace(temporaryDirectory, ''),\n newFile.replace(path.join(currentDirectory, 'node_modules'), ''),\n oldString,\n newString\n )\n );\n }\n}\n\nexport function makePatchName(packageName: string, version: string): string {\n return `${packageName.replaceAll('/', '+')}#${version}.patch`;\n}\n\nexport async function comparePackages(\n packageName: string,\n version: string\n): Promise<void> {\n const patchFile = makePatchName(packageName, version);\n\n // Ensure the patches directory exists\n ensureDirectoryExists(patchDirectory);\n\n const stream = fs.createWriteStream(path.join(patchDirectory, patchFile));\n stream.on('error', (error) => {\n console.error(\n `${pc.redBright('ERROR:')} Failed to write to patch file - ${error.message}`\n );\n });\n\n stream.cork();\n scanFiles(packageName, '', stream);\n stream.uncork();\n\n // Handle 'drain' event if necessary\n if (stream.write('')) {\n stream.end();\n } else {\n stream.once('drain', () => {\n stream.end();\n });\n }\n\n console.log(`Successfully created ${pc.greenBright(patchFile)}`);\n}\n\nexport function scanFiles(\n packageName: string,\n source: string,\n patch: fs.WriteStream\n): void {\n const baseDirectory = path.join(\n currentDirectory,\n 'node_modules',\n packageName\n );\n const stack: string[] = [source];\n const visitedPaths = new Set<string>();\n while (stack.length > 0) {\n const currentSource = stack.pop();\n if (currentSource === undefined) continue;\n const directoryPath = path.join(baseDirectory, currentSource);\n let files: string[];\n try {\n files = fs.readdirSync(directoryPath);\n } catch (error) {\n console.error(\n `${pc.redBright('ERROR:')} Failed to read directory ${directoryPath} - ${error instanceof Error ? error.message : String(error)}`\n );\n continue;\n }\n\n for (const item of files) {\n if (item === 'node_modules') continue;\n\n const pathname = path.join(currentSource, item);\n const itemPath = path.join(baseDirectory, pathname);\n\n let stat: fs.Stats;\n try {\n stat = fs.lstatSync(itemPath);\n } catch (error) {\n console.error(\n `${pc.redBright('ERROR:')} Failed to get stats for ${itemPath} - ${error instanceof Error ? error.message : String(error)}`\n );\n continue;\n }\n\n if (stat.isSymbolicLink()) {\n // Skip symlinks to avoid cycles\n continue;\n }\n\n if (stat.isDirectory()) {\n // Prevent processing the same directory due to hard links or other reasons\n const realPath = fs.realpathSync(itemPath);\n if (visitedPaths.has(realPath)) {\n // Already visited this directory\n continue;\n }\n visitedPaths.add(realPath);\n stack.push(pathname);\n } else {\n createPatch(packageName, pathname, patch);\n }\n }\n }\n}\n\nexport async function readPatch(\n packageName: string,\n version: string,\n reverse: boolean = false\n): Promise<void> {\n const thePackageName = packageName.replaceAll('+', path.sep);\n const config = getConfig(thePackageName);\n if (config) {\n const patchFile = makePatchName(packageName, version);\n const patchFilePath = path.join(patchDirectory, patchFile);\n if (!fs.existsSync(patchFilePath)) {\n console.warn(\n `${pc.yellowBright('WARNING:')} Patch file \"${patchFile}\" does not exist.`\n );\n return;\n }\n const patchContent = readFileContent(patchFilePath);\n\n const patches = parsePatch(patchContent);\n\n for (const patchItem of patches) {\n // Ensure that we have a valid file name\n const filePath = patchItem.newFileName ?? patchItem.oldFileName;\n if (!filePath) {\n console.error(\n `${pc.redBright('ERROR:')} Patch item has no file names for package ${packageName}`\n );\n continue; // Skip this patch item\n }\n\n const normalizedPath = pathNormalize(filePath);\n const fileName = path.join(\n currentDirectory,\n 'node_modules',\n normalizedPath\n );\n\n let fileContent = '';\n if (fs.existsSync(fileName)) {\n fileContent = readFileContent(fileName);\n } else {\n console.warn(\n `${pc.yellowBright('WARNING:')} File \"${fileName}\" does not exist - skipping.`\n );\n continue;\n }\n\n if (reverse) {\n // Reverse the patch\n const reversedPatchText = reversePatch(patchItem);\n const reversePatchedContent = applyPatch(\n fileContent,\n reversedPatchText\n );\n\n if (reversePatchedContent === false) {\n // Failed to reverse the patch\n // Attempt to apply the original patch to check if it's already reversed\n const patchedContent = applyPatch(fileContent, patchItem);\n\n if (patchedContent === false) {\n // Patch failed for other reasons\n console.warn(\n `${pc.yellowBright('WARNING:')} Failed to reverse patch for ${pc.redBright(fileName)}`\n );\n } else {\n // Patch is already reversed\n console.log(\n `Patch already reversed for ${pc.greenBright(fileName)}`\n );\n }\n } else {\n try {\n fs.writeFileSync(fileName, reversePatchedContent, 'utf8');\n console.log(`Reversed patch for ${pc.greenBright(fileName)}`);\n } catch (error) {\n console.error(\n `${pc.redBright('ERROR:')} Could not write the new content for file ${fileName} - ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n } else {\n // Apply the patch normally\n const patchedContent = applyPatch(fileContent, patchItem);\n\n if (patchedContent === false) {\n // Failed to apply patch normally\n // Try applying the reversed patch to check if already applied\n const reversedPatchText = reversePatch(patchItem);\n const reversePatchedContent = applyPatch(\n fileContent,\n reversedPatchText\n );\n\n if (reversePatchedContent === false) {\n // Patch failed for other reasons\n console.warn(\n `${pc.yellowBright('WARNING:')} Failed to apply patch to ${pc.redBright(fileName)}`\n );\n } else {\n // The patch was already applied\n console.log(`Patch already applied to ${pc.greenBright(fileName)}`);\n }\n } else {\n try {\n fs.writeFileSync(fileName, patchedContent, 'utf8');\n console.log(`Patched ${pc.greenBright(fileName)}`);\n } catch (error) {\n console.error(\n `${pc.redBright('ERROR:')} Could not write the new content for file ${fileName} - ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n }\n }\n } else {\n console.error(\n `${pc.redBright('ERROR:')} Could not get config for package ${packageName}`\n );\n }\n}\n\nexport function getConfig(packageName: string): PackageConfig | false {\n const folder = path.join(currentDirectory, 'node_modules', packageName);\n const configName = path.join(folder, 'package.json');\n if (!fs.existsSync(folder)) {\n console.error(\n `${pc.redBright('ERROR:')} Missing folder \"${pc.whiteBright(folder)}\"`\n );\n return false;\n }\n try {\n fs.accessSync(configName, fs.constants.R_OK);\n } catch {\n console.error(\n `${pc.redBright('ERROR:')} Cannot read \"${pc.whiteBright(configName)}\"`\n );\n return false;\n }\n const packageConfig = readFileContent(configName);\n\n let config: PackageConfig;\n try {\n config = JSON.parse(packageConfig);\n } catch (error) {\n console.error(\n `${pc.redBright('ERROR:')} Could not parse \"${pc.whiteBright('package.json')}\" - ${pc.redBright(error instanceof Error ? error.message : String(error))}`\n );\n return false;\n }\n return config;\n}\n"],"names":[],"mappings":";;;;;;;;;SAsBgB,WAAA,CACd,WAAA,EACA,QAAA,EACA,KAAA,EAAqB;AAErB,EAAA,MAAM,UAAU,IAAA,CAAK,IAAA,CACnB,gBAAA,EACA,cAAA,EACA,aACA,QAAQ,CAAA;AAEV,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,kBAAA,EAAoB,aAAa,QAAQ,CAAA;AACnE,EAAA,MAAM,YAAY,EAAA,CAAG,UAAA,CAAW,OAAO,CAAA,GAAI,eAAA,CAAgB,OAAO,CAAA,GAAI,EAAA;AACtE,EAAA,MAAM,SAAA,GAAY,gBAAgB,OAAO,CAAA;AACzC,EAAA,IAAI,QAAA,KAAa,cAAA,IAAkB,CAAC,cAAA,CAAe,GAAA;AAAK,IAAA;AACxD,EAAA,IAAI,cAAc,SAAA,EAAW;AAC3B,IAAA,KAAA,CAAM,MACJ,mBAAA,CACE,OAAA,CAAQ,QAAQ,kBAAA,EAAoB,EAAE,GACtC,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,IAAA,CAAK,kBAAkB,cAAc,CAAA,EAAG,EAAE,CAAA,EAC/D,SAAA,EACA,SAAS,CACV,CAAA;AAAA,EAEL;AACF;AAEM,SAAU,aAAA,CAAc,aAAqB,OAAA,EAAe;AAChE,EAAA,OAAO,GAAG,WAAA,CAAY,UAAA,CAAW,KAAK,GAAG,CAAC,IAAI,OAAO,CAAA,MAAA,CAAA;AACvD;AAEA,eAAsB,eAAA,CACpB,aACA,OAAA,EAAe;AAEf,EAAA,MAAM,SAAA,GAAY,aAAA,CAAc,WAAA,EAAa,OAAO,CAAA;AAGpD,EAAA,qBAAA,CAAsB,cAAc,CAAA;AAEpC,EAAA,MAAM,SAAS,EAAA,CAAG,iBAAA,CAAkB,KAAK,IAAA,CAAK,cAAA,EAAgB,SAAS,CAAC,CAAA;AACxE,EAAA,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,CAAC,KAAA,KAAS;AAC3B,IAAA,OAAA,CAAQ,KAAA,CACN,GAAG,EAAA,CAAG,SAAA,CAAU,QAAQ,CAAC,CAAA,iCAAA,EAAoC,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAAA,EAEhF,CAAC,CAAA;AAED,EAAA,MAAA,CAAO,IAAA,EAAI;AACX,EAAA,SAAA,CAAU,WAAA,EAAa,IAAI,MAAM,CAAA;AACjC,EAAA,MAAA,CAAO,MAAA,EAAM;AAGb,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,EAAE,CAAA,EAAG;AACpB,IAAA,MAAA,CAAO,GAAA,EAAG;AAAA,EACZ,CAAA,MAAO;AACL,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,MAAK;AACxB,MAAA,MAAA,CAAO,GAAA,EAAG;AAAA,IACZ,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,OAAA,CAAQ,IAAI,CAAA,qBAAA,EAAwB,EAAA,CAAG,WAAA,CAAY,SAAS,CAAC,CAAA,CAAE,CAAA;AACjE;SAEgB,SAAA,CACd,WAAA,EACA,MAAA,EACA,KAAA,EAAqB;AAErB,EAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,IAAA,CACzB,gBAAA,EACA,gBACA,WAAW,CAAA;AAEb,EAAA,MAAM,KAAA,GAAkB,CAAC,MAAM,CAAA;AAC/B,EAAA,MAAM,YAAA,uBAAmB,GAAA;AACzB,EAAA,OAAO,KAAA,CAAM,SAAS,CAAA,EAAG;AACvB,IAAA,MAAM,aAAA,GAAgB,MAAM,GAAA;AAC5B,IAAA,IAAI,aAAA,KAAkB,MAAA;AAAW,MAAA;AACjC,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,IAAA,CAAK,aAAA,EAAe,aAAa,CAAA;AAC5D,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACF,MAAA,KAAA,GAAQ,EAAA,CAAG,YAAY,aAAa,CAAA;AAAA,IACtC,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,MACN,CAAA,EAAG,EAAA,CAAG,SAAA,CAAU,QAAQ,CAAC,CAAA,0BAAA,EAA6B,aAAa,CAAA,GAAA,EAAM,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,CAAA;AAEnI,MAAA;AAAA,IACF;AAEA,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,IAAI,IAAA,KAAS,cAAA;AAAgB,QAAA;AAE7B,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,aAAA,EAAe,IAAI,CAAA;AAC9C,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,aAAA,EAAe,QAAQ,CAAA;AAElD,MAAA,IAAI,IAAA;AACJ,MAAA,IAAI;AACF,QAAA,IAAA,GAAO,EAAA,CAAG,UAAU,QAAQ,CAAA;AAAA,MAC9B,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,MACN,CAAA,EAAG,EAAA,CAAG,SAAA,CAAU,QAAQ,CAAC,CAAA,yBAAA,EAA4B,QAAQ,CAAA,GAAA,EAAM,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,CAAA;AAE7H,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,IAAA,CAAK,gBAAc,EAAI;AAEzB,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,IAAA,CAAK,aAAW,EAAI;AAEtB,QAAA,MAAM,QAAA,GAAW,EAAA,CAAG,YAAA,CAAa,QAAQ,CAAA;AACzC,QAAA,IAAI,YAAA,CAAa,GAAA,CAAI,QAAQ,CAAA,EAAG;AAE9B,UAAA;AAAA,QACF;AACA,QAAA,YAAA,CAAa,IAAI,QAAQ,CAAA;AACzB,QAAA,KAAA,CAAM,KAAK,QAAQ,CAAA;AAAA,MACrB,CAAA,MAAO;AACL,QAAA,WAAA,CAAY,WAAA,EAAa,UAAU,KAAK,CAAA;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,SAAA,CACpB,WAAA,EACA,OAAA,EACA,OAAA,GAAmB,KAAA,EAAK;AAExB,EAAA,MAAM,cAAA,GAAiB,WAAA,CAAY,UAAA,CAAW,GAAA,EAAK,KAAK,GAAG,CAAA;AAC3D,EAAA,MAAM,MAAA,GAAS,UAAU,cAAc,CAAA;AACvC,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAM,SAAA,GAAY,aAAA,CAAc,WAAA,EAAa,OAAO,CAAA;AACpD,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,SAAS,CAAA;AACzD,IAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,aAAa,CAAA,EAAG;AACjC,MAAA,OAAA,CAAQ,IAAA,CACN,GAAG,EAAA,CAAG,YAAA,CAAa,UAAU,CAAC,CAAA,aAAA,EAAgB,SAAS,CAAA,iBAAA,CAAmB,CAAA;AAE5E,MAAA;AAAA,IACF;AACA,IAAA,MAAM,YAAA,GAAe,gBAAgB,aAAa,CAAA;AAElD,IAAA,MAAM,OAAA,GAAU,WAAW,YAAY,CAAA;AAEvC,IAAA,KAAA,MAAW,aAAa,OAAA,EAAS;AAE/B,MAAA,MAAM,QAAA,GAAW,SAAA,CAAU,WAAA,IAAe,SAAA,CAAU,WAAA;AACpD,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,OAAA,CAAQ,KAAA,CACN,GAAG,EAAA,CAAG,SAAA,CAAU,QAAQ,CAAC,CAAA,0CAAA,EAA6C,WAAW,CAAA,CAAE,CAAA;AAErF,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,cAAA,GAAiB,cAAc,QAAQ,CAAA;AAC7C,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CACpB,gBAAA,EACA,gBACA,cAAc,CAAA;AAGhB,MAAA,IAAI,WAAA,GAAc,EAAA;AAClB,MAAA,IAAI,EAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC3B,QAAA,WAAA,GAAc,gBAAgB,QAAQ,CAAA;AAAA,MACxC,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,IAAA,CACN,GAAG,EAAA,CAAG,YAAA,CAAa,UAAU,CAAC,CAAA,OAAA,EAAU,QAAQ,CAAA,4BAAA,CAA8B,CAAA;AAEhF,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,OAAA,EAAS;AAEX,QAAA,MAAM,iBAAA,GAAoB,aAAa,SAAS,CAAA;AAChD,QAAA,MAAM,qBAAA,GAAwB,UAAA,CAC5B,WAAA,EACA,iBAAiB,CAAA;AAGnB,QAAA,IAAI,0BAA0B,KAAA,EAAO;AAGnC,UAAA,MAAM,cAAA,GAAiB,UAAA,CAAW,WAAA,EAAa,SAAS,CAAA;AAExD,UAAA,IAAI,mBAAmB,KAAA,EAAO;AAE5B,YAAA,OAAA,CAAQ,IAAA,CACN,CAAA,EAAG,EAAA,CAAG,YAAA,CAAa,UAAU,CAAC,CAAA,6BAAA,EAAgC,EAAA,CAAG,SAAA,CAAU,QAAQ,CAAC,CAAA,CAAE,CAAA;AAAA,UAE1F,CAAA,MAAO;AAEL,YAAA,OAAA,CAAQ,IACN,CAAA,2BAAA,EAA8B,EAAA,CAAG,WAAA,CAAY,QAAQ,CAAC,CAAA,CAAE,CAAA;AAAA,UAE5D;AAAA,QACF,CAAA,MAAO;AACL,UAAA,IAAI;AACF,YAAA,EAAA,CAAG,aAAA,CAAc,QAAA,EAAU,qBAAA,EAAuB,MAAM,CAAA;AACxD,YAAA,OAAA,CAAQ,IAAI,CAAA,mBAAA,EAAsB,EAAA,CAAG,WAAA,CAAY,QAAQ,CAAC,CAAA,CAAE,CAAA;AAAA,UAC9D,SAAS,KAAA,EAAO;AACd,YAAA,OAAA,CAAQ,MACN,CAAA,EAAG,EAAA,CAAG,SAAA,CAAU,QAAQ,CAAC,CAAA,0CAAA,EAA6C,QAAQ,CAAA,GAAA,EAC5E,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CACvD,CAAA,CAAE,CAAA;AAAA,UAEN;AAAA,QACF;AAAA,MACF,CAAA,MAAO;AAEL,QAAA,MAAM,cAAA,GAAiB,UAAA,CAAW,WAAA,EAAa,SAAS,CAAA;AAExD,QAAA,IAAI,mBAAmB,KAAA,EAAO;AAG5B,UAAA,MAAM,iBAAA,GAAoB,aAAa,SAAS,CAAA;AAChD,UAAA,MAAM,qBAAA,GAAwB,UAAA,CAC5B,WAAA,EACA,iBAAiB,CAAA;AAGnB,UAAA,IAAI,0BAA0B,KAAA,EAAO;AAEnC,YAAA,OAAA,CAAQ,IAAA,CACN,CAAA,EAAG,EAAA,CAAG,YAAA,CAAa,UAAU,CAAC,CAAA,0BAAA,EAA6B,EAAA,CAAG,SAAA,CAAU,QAAQ,CAAC,CAAA,CAAE,CAAA;AAAA,UAEvF,CAAA,MAAO;AAEL,YAAA,OAAA,CAAQ,IAAI,CAAA,yBAAA,EAA4B,EAAA,CAAG,WAAA,CAAY,QAAQ,CAAC,CAAA,CAAE,CAAA;AAAA,UACpE;AAAA,QACF,CAAA,MAAO;AACL,UAAA,IAAI;AACF,YAAA,EAAA,CAAG,aAAA,CAAc,QAAA,EAAU,cAAA,EAAgB,MAAM,CAAA;AACjD,YAAA,OAAA,CAAQ,IAAI,CAAA,QAAA,EAAW,EAAA,CAAG,WAAA,CAAY,QAAQ,CAAC,CAAA,CAAE,CAAA;AAAA,UACnD,SAAS,KAAA,EAAO;AACd,YAAA,OAAA,CAAQ,MACN,CAAA,EAAG,EAAA,CAAG,SAAA,CAAU,QAAQ,CAAC,CAAA,0CAAA,EAA6C,QAAQ,CAAA,GAAA,EAC5E,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CACvD,CAAA,CAAE,CAAA;AAAA,UAEN;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAA,MAAO;AACL,IAAA,OAAA,CAAQ,KAAA,CACN,GAAG,EAAA,CAAG,SAAA,CAAU,QAAQ,CAAC,CAAA,kCAAA,EAAqC,WAAW,CAAA,CAAE,CAAA;AAAA,EAE/E;AACF;AAEM,SAAU,UAAU,WAAA,EAAmB;AAC3C,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,IAAA,CAAK,gBAAA,EAAkB,gBAAgB,WAAW,CAAA;AACtE,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,cAAc,CAAA;AACnD,EAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,MAAM,CAAA,EAAG;AAC1B,IAAA,OAAA,CAAQ,KAAA,CACN,CAAA,EAAG,EAAA,CAAG,SAAA,CAAU,QAAQ,CAAC,CAAA,iBAAA,EAAoB,EAAA,CAAG,WAAA,CAAY,MAAM,CAAC,CAAA,CAAA,CAAG,CAAA;AAExE,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,IAAI;AACF,IAAA,EAAA,CAAG,UAAA,CAAW,UAAA,EAAY,EAAA,CAAG,SAAA,CAAU,IAAI,CAAA;AAAA,EAC7C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAA,CAAQ,KAAA,CACN,CAAA,EAAG,EAAA,CAAG,SAAA,CAAU,QAAQ,CAAC,CAAA,cAAA,EAAiB,EAAA,CAAG,WAAA,CAAY,UAAU,CAAC,CAAA,CAAA,CAAG,CAAA;AAEzE,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,aAAA,GAAgB,gBAAgB,UAAU,CAAA;AAEhD,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,aAAa,CAAA;AAAA,EACnC,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CACN,GAAG,EAAA,CAAG,SAAA,CAAU,QAAQ,CAAC,CAAA,kBAAA,EAAqB,EAAA,CAAG,WAAA,CAAY,cAAc,CAAC,OAAO,EAAA,CAAG,SAAA,CAAU,iBAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,MAAA,CAAO,KAAK,CAAC,CAAC,CAAA,CAAE,CAAA;AAE3J,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAA;AACT;;;;"}