highcharts-export-server
Version:
**Note:** If you use the public Export Server at [https://export.highcharts.com](https://export.highcharts.com) you should read our [Terms of use and Fair Usage Policy](https://www.highcharts.com/docs/export-module/privacy-disclaimer-export). Note that a
1 lines • 66.2 kB
JavaScript
import"colors";import{existsSync as e,mkdirSync as t,appendFile as r,readFileSync as o,promises as i,writeFileSync as s}from"fs";import n,{dirname as a,join as l,resolve as c,sep as p,posix as h}from"path";import{HttpsProxyAgent as u}from"https-proxy-agent";import d from"prompts";import g from"dotenv";import{z as m}from"zod";import{createRequire as f}from"module";import{fileURLToPath as v}from"url";import y from"http";import b from"https";import{Pool as w}from"tarn";import{v4 as E}from"uuid";import T from"puppeteer";import{JSDOM as S}from"jsdom";import R from"dompurify";import x from"cors";import _ from"express";import O from"multer";import L from"express-rate-limit";const k={core:["highcharts","highcharts-more","highcharts-3d"],modules:["stock","map","gantt","exporting","parallel-coordinates","accessibility","boost-canvas","boost","data","data-tools","draggable-points","static-scale","broken-axis","heatmap","tilemap","tiledwebmap","timeline","treemap","treegraph","item-series","drilldown","histogram-bellcurve","bullet","funnel","funnel3d","geoheatmap","pyramid3d","networkgraph","pareto","pattern-fill","pictorial","price-indicator","sankey","arc-diagram","dependency-wheel","series-label","series-on-point","solid-gauge","sonification","streamgraph","sunburst","variable-pie","variwide","vector","venn","windbarb","wordcloud","xrange","no-data-to-display","drag-panes","debugger","dumbbell","lollipop","cylinder","organization","dotplot","marker-clusters","hollowcandlestick","heikinashi","flowmap","export-data","navigator","textpath"],indicators:["indicators-all"],custom:["https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.min.js","https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.45/moment-timezone-with-data.min.js"]},I={puppeteer:{args:{value:["--allow-running-insecure-content","--ash-no-nudges","--autoplay-policy=user-gesture-required","--block-new-web-contents","--disable-accelerated-2d-canvas","--disable-background-networking","--disable-background-timer-throttling","--disable-backgrounding-occluded-windows","--disable-breakpad","--disable-checker-imaging","--disable-client-side-phishing-detection","--disable-component-extensions-with-background-pages","--disable-component-update","--disable-default-apps","--disable-dev-shm-usage","--disable-domain-reliability","--disable-extensions","--disable-features=CalculateNativeWinOcclusion,InterestFeedContentSuggestions,WebOTP","--disable-hang-monitor","--disable-ipc-flooding-protection","--disable-logging","--disable-notifications","--disable-offer-store-unmasked-wallet-cards","--disable-popup-blocking","--disable-print-preview","--disable-prompt-on-repost","--disable-renderer-backgrounding","--disable-search-engine-choice-screen","--disable-session-crashed-bubble","--disable-setuid-sandbox","--disable-site-isolation-trials","--disable-speech-api","--disable-sync","--enable-unsafe-webgpu","--hide-crash-restore-bubble","--hide-scrollbars","--metrics-recording-only","--mute-audio","--no-default-browser-check","--no-first-run","--no-pings","--pipe","--no-startup-window","--password-store=basic","--process-per-tab","--use-mock-keychain"],type:"string[]",description:"Arguments array to send to Puppeteer."},tempDir:{value:"./tmp/",type:"string",envLink:"PUPPETEER_TEMP_DIR",description:"The directory for Puppeteer to store temporary files."}},highcharts:{version:{value:"latest",type:"string",envLink:"HIGHCHARTS_VERSION",description:"The Highcharts version to be used."},cdnURL:{value:"https://code.highcharts.com/",type:"string",envLink:"HIGHCHARTS_CDN_URL",description:"The CDN URL for Highcharts scripts to be used."},useNpm:{value:!1,type:"boolean",envLink:"HIGHCHARTS_USE_NPM",description:"Flag to use Highcharts scripts from NPM package"},coreScripts:{value:k.core,type:"string[]",envLink:"HIGHCHARTS_CORE_SCRIPTS",description:"The core Highcharts scripts to fetch."},moduleScripts:{value:k.modules,type:"string[]",envLink:"HIGHCHARTS_MODULE_SCRIPTS",description:"The modules of Highcharts to fetch."},indicatorScripts:{value:k.indicators,type:"string[]",envLink:"HIGHCHARTS_INDICATOR_SCRIPTS",description:"The indicators of Highcharts to fetch."},customScripts:{value:k.custom,type:"string[]",description:"Additional custom scripts or dependencies to fetch."},forceFetch:{value:!1,type:"boolean",envLink:"HIGHCHARTS_FORCE_FETCH",description:"The flag to determine whether to refetch all scripts after each server rerun."},cachePath:{value:".cache",type:"string",envLink:"HIGHCHARTS_CACHE_PATH",description:"The path to the cache directory. It is used to store the Highcharts scripts and custom scripts."}},export:{infile:{value:!1,type:"string",description:"The input file should include a name and a type (json or svg). It must be correctly formatted as a JSON or SVG file."},instr:{value:!1,type:"string",description:"Input, provided in the form of a stringified JSON or SVG file, will override the --infile option."},options:{value:!1,type:"string",description:"An alias for the --instr option."},outfile:{value:!1,type:"string",description:"The output filename along with a type (jpeg, png, pdf, or svg). This will ignore the --type flag."},type:{value:"png",type:"string",envLink:"EXPORT_TYPE",description:"The file export format. It can be jpeg, png, pdf, or svg."},constr:{value:"chart",type:"string",envLink:"EXPORT_CONSTR",description:"The constructor to use. Can be chart, stockChart, mapChart, or ganttChart."},defaultHeight:{value:400,type:"number",envLink:"EXPORT_DEFAULT_HEIGHT",description:"the default height of the exported chart. Used when no value is set."},defaultWidth:{value:600,type:"number",envLink:"EXPORT_DEFAULT_WIDTH",description:"The default width of the exported chart. Used when no value is set."},defaultScale:{value:1,type:"number",envLink:"EXPORT_DEFAULT_SCALE",description:"The default scale of the exported chart. Used when no value is set."},height:{value:!1,type:"number",description:"The height of the exported chart, overriding the option in the chart settings."},width:{value:!1,type:"number",description:"The width of the exported chart, overriding the option in the chart settings."},scale:{value:!1,type:"number",description:"The scale of the exported chart, overriding the option in the chart settings. Ranges between 0.1 and 5.0."},globalOptions:{value:!1,type:"string",description:"Either a stringified JSON or a filename containing options to be passed into the Highcharts.setOptions."},themeOptions:{value:!1,type:"string",description:"Either a stringified JSON or a filename containing theme options to be passed into the Highcharts.setOptions."},batch:{value:!1,type:"string",description:'Initiates a batch job with a string containing input/output pairs: "in=out;in=out;...".'},rasterizationTimeout:{value:1500,type:"number",envLink:"EXPORT_RASTERIZATION_TIMEOUT",description:"The duration in milliseconds to wait for rendering a webpage."}},customLogic:{allowCodeExecution:{value:!1,type:"boolean",envLink:"CUSTOM_LOGIC_ALLOW_CODE_EXECUTION",description:"Controls whether the execution of arbitrary code is allowed during the exporting process."},allowFileResources:{value:!1,type:"boolean",envLink:"CUSTOM_LOGIC_ALLOW_FILE_RESOURCES",description:"Controls the ability to inject resources from the filesystem. This setting has no effect when running as a server."},customCode:{value:!1,type:"string",description:"Custom code to execute before chart initialization. It can be a function, code wrapped within a function, or a filename with the .js extension."},callback:{value:!1,type:"string",description:"JavaScript code to run during construction. It can be a function or a filename with the .js extension."},resources:{value:!1,type:"string",description:"Additional resource in the form of a stringified JSON, which may contain files, js, and css sections."},loadConfig:{value:!1,type:"string",legacyName:"fromFile",description:"A file containing a pre-defined configuration to use."},createConfig:{value:!1,type:"string",description:"Enables setting options through a prompt and saving them in a provided config file."}},server:{maxUploadSize:{value:3,type:"number",envLink:"SERVER_MAX_UPLOAD_SIZE",description:"The maximum upload size, in MB, for the server."},enable:{value:!1,type:"boolean",envLink:"SERVER_ENABLE",cliName:"enableServer",description:"When set to true, the server starts on the local IP address 0.0.0.0."},host:{value:"0.0.0.0",type:"string",envLink:"SERVER_HOST",description:"The hostname of the server. Additionally, it starts a server on the provided hostname."},port:{value:7801,type:"number",envLink:"SERVER_PORT",description:"The server port when enabled."},benchmarking:{value:!1,type:"boolean",envLink:"SERVER_BENCHMARKING",cliName:"serverBenchmarking",description:"Indicates whether to display the duration, in milliseconds, of specific actions that occur on the server while serving a request."},proxy:{host:{value:!1,type:"string",envLink:"SERVER_PROXY_HOST",cliName:"proxyHost",description:"The host of the proxy server to use, if it exists."},port:{value:8080,type:"number",envLink:"SERVER_PROXY_PORT",cliName:"proxyPort",description:"The port of the proxy server to use, if it exists."},username:{value:!1,type:"string",envLink:"SERVER_PROXY_USERNAME",cliName:"proxyUsername",description:"The username for the proxy server, if it exists."},password:{value:!1,type:"string",envLink:"SERVER_PROXY_PASSWORD",cliName:"proxyPassword",description:"The password for the proxy server, if it exists."},timeout:{value:5e3,type:"number",envLink:"SERVER_PROXY_TIMEOUT",cliName:"proxyTimeout",description:"The timeout for the proxy server to use, if it exists."}},rateLimiting:{enable:{value:!1,type:"boolean",envLink:"SERVER_RATE_LIMITING_ENABLE",cliName:"enableRateLimiting",description:"Enables rate limiting for the server."},maxRequests:{value:10,type:"number",envLink:"SERVER_RATE_LIMITING_MAX_REQUESTS",legacyName:"rateLimit",description:"The maximum number of requests allowed in one minute."},window:{value:1,type:"number",envLink:"SERVER_RATE_LIMITING_WINDOW",description:"The time window, in minutes, for the rate limiting."},delay:{value:0,type:"number",envLink:"SERVER_RATE_LIMITING_DELAY",description:"The delay duration for each successive request before reaching the maximum limit."},trustProxy:{value:!1,type:"boolean",envLink:"SERVER_RATE_LIMITING_TRUST_PROXY",description:"Set this to true if the server is behind a load balancer."},skipKey:{value:!1,type:"string",envLink:"SERVER_RATE_LIMITING_SKIP_KEY",description:"Allows bypassing the rate limiter and should be provided with the skipToken argument."},skipToken:{value:!1,type:"string",envLink:"SERVER_RATE_LIMITING_SKIP_TOKEN",description:"Allows bypassing the rate limiter and should be provided with the skipKey argument."}},ssl:{enable:{value:!1,type:"boolean",envLink:"SERVER_SSL_ENABLE",cliName:"enableSsl",description:"Enables or disables the SSL protocol."},force:{value:!1,type:"boolean",envLink:"SERVER_SSL_FORCE",cliName:"sslForce",legacyName:"sslOnly",description:"When set to true, the server is forced to serve only over HTTPS."},port:{value:443,type:"number",envLink:"SERVER_SSL_PORT",cliName:"sslPort",description:"The port on which to run the SSL server."},certPath:{value:!1,type:"string",envLink:"SERVER_SSL_CERT_PATH",legacyName:"sslPath",description:"The path to the SSL certificate/key file."}}},pool:{minWorkers:{value:4,type:"number",envLink:"POOL_MIN_WORKERS",description:"The number of minimum and initial pool workers to spawn."},maxWorkers:{value:8,type:"number",envLink:"POOL_MAX_WORKERS",legacyName:"workers",description:"The number of maximum pool workers to spawn."},workLimit:{value:40,type:"number",envLink:"POOL_WORK_LIMIT",description:"The number of work pieces that can be performed before restarting the worker process."},acquireTimeout:{value:5e3,type:"number",envLink:"POOL_ACQUIRE_TIMEOUT",description:"The duration, in milliseconds, to wait for acquiring a resource."},createTimeout:{value:5e3,type:"number",envLink:"POOL_CREATE_TIMEOUT",description:"The duration, in milliseconds, to wait for creating a resource."},destroyTimeout:{value:5e3,type:"number",envLink:"POOL_DESTROY_TIMEOUT",description:"The duration, in milliseconds, to wait for destroying a resource."},idleTimeout:{value:3e4,type:"number",envLink:"POOL_IDLE_TIMEOUT",description:"The duration, in milliseconds, after which an idle resource is destroyed."},createRetryInterval:{value:200,type:"number",envLink:"POOL_CREATE_RETRY_INTERVAL",description:"The duration, in milliseconds, to wait before retrying the create process in case of a failure."},reaperInterval:{value:1e3,type:"number",envLink:"POOL_REAPER_INTERVAL",description:"The duration, in milliseconds, after which the check for idle resources to destroy is triggered."},benchmarking:{value:!1,type:"boolean",envLink:"POOL_BENCHMARKING",cliName:"poolBenchmarking",description:"Indicate whether to show statistics for the pool of resources or not."}},logging:{level:{value:4,type:"number",envLink:"LOGGING_LEVEL",cliName:"logLevel",description:"The logging level to be used."},file:{value:"highcharts-export-server.log",type:"string",envLink:"LOGGING_FILE",cliName:"logFile",description:"The name of a log file. The `logToFile` and `logDest` options also need to be set to enable file logging."},dest:{value:"log/",type:"string",envLink:"LOGGING_DEST",cliName:"logDest",description:"The path to store log files. The `logToFile` option also needs to be set to enable file logging."},toConsole:{value:!0,type:"boolean",envLink:"LOGGING_TO_CONSOLE",cliName:"logToConsole",description:"Enables or disables showing logs in the console."},toFile:{value:!0,type:"boolean",envLink:"LOGGING_TO_FILE",cliName:"logToFile",description:"Enables or disables creation of the log directory and saving the log into a .log file."}},ui:{enable:{value:!1,type:"boolean",envLink:"UI_ENABLE",cliName:"enableUi",description:"Enables or disables the user interface (UI) for the export server."},route:{value:"/",type:"string",envLink:"UI_ROUTE",cliName:"uiRoute",description:"The endpoint route to which the user interface (UI) should be attached."}},other:{nodeEnv:{value:"production",type:"string",envLink:"OTHER_NODE_ENV",description:"The type of Node.js environment."},listenToProcessExits:{value:!0,type:"boolean",envLink:"OTHER_LISTEN_TO_PROCESS_EXITS",description:"Decides whether or not to attach process.exit handlers."},noLogo:{value:!1,type:"boolean",envLink:"OTHER_NO_LOGO",description:"Skip printing the logo on a startup. Will be replaced by a simple text."},hardResetPage:{value:!1,type:"boolean",envLink:"OTHER_HARD_RESET_PAGE",description:"Decides if the page content should be reset entirely."},browserShellMode:{value:!0,type:"boolean",envLink:"OTHER_BROWSER_SHELL_MODE",description:"Decides if the browser runs in the shell mode."}},debug:{enable:{value:!1,type:"boolean",envLink:"DEBUG_ENABLE",cliName:"enableDebug",description:"Enables or disables debug mode for the underlying browser."},headless:{value:!0,type:"boolean",envLink:"DEBUG_HEADLESS",description:"Controls the mode in which the browser is launched when in the debug mode."},devtools:{value:!1,type:"boolean",envLink:"DEBUG_DEVTOOLS",description:"Decides whether to enable DevTools when the browser is in a headful state."},listenToConsole:{value:!1,type:"boolean",envLink:"DEBUG_LISTEN_TO_CONSOLE",description:"Decides whether to enable a listener for console messages sent from the browser."},dumpio:{value:!1,type:"boolean",envLink:"DEBUG_DUMPIO",description:"Redirects browser process stdout and stderr to process.stdout and process.stderr."},slowMo:{value:0,type:"number",envLink:"DEBUG_SLOW_MO",description:"Slows down Puppeteer operations by the specified number of milliseconds."},debuggingPort:{value:9222,type:"number",envLink:"DEBUG_DEBUGGING_PORT",description:"Specifies the debugging port."}}},N={puppeteer:[{type:"list",name:"args",message:"Puppeteer arguments",initial:I.puppeteer.args.value.join(","),separator:","}],highcharts:[{type:"text",name:"version",message:"Highcharts version",initial:I.highcharts.version.value},{type:"text",name:"cdnURL",message:"The URL of CDN",initial:I.highcharts.cdnURL.value},{type:"toggle",name:"useNpm",message:"Flag to use Highcharts scripts from NPM package",initial:I.highcharts.useNpm.value},{type:"multiselect",name:"coreScripts",message:"Available core scripts",instructions:"Space: Select specific, A: Select all, Enter: Confirm.",choices:I.highcharts.coreScripts.value},{type:"multiselect",name:"moduleScripts",message:"Available module scripts",instructions:"Space: Select specific, A: Select all, Enter: Confirm.",choices:I.highcharts.moduleScripts.value},{type:"multiselect",name:"indicatorScripts",message:"Available indicator scripts",instructions:"Space: Select specific, A: Select all, Enter: Confirm.",choices:I.highcharts.indicatorScripts.value},{type:"list",name:"customScripts",message:"Custom scripts",initial:I.highcharts.customScripts.value.join(","),separator:","},{type:"toggle",name:"forceFetch",message:"Force re-fetch the scripts",initial:I.highcharts.forceFetch.value},{type:"text",name:"cachePath",message:"The path to the cache directory",initial:I.highcharts.cachePath.value}],export:[{type:"select",name:"type",message:"The default export file type",hint:`Default: ${I.export.type.value}`,initial:0,choices:["png","jpeg","pdf","svg"]},{type:"select",name:"constr",message:"The default constructor for Highcharts",hint:`Default: ${I.export.constr.value}`,initial:0,choices:["chart","stockChart","mapChart","ganttChart"]},{type:"number",name:"defaultHeight",message:"The default fallback height of the exported chart",initial:I.export.defaultHeight.value},{type:"number",name:"defaultWidth",message:"The default fallback width of the exported chart",initial:I.export.defaultWidth.value},{type:"number",name:"defaultScale",message:"The default fallback scale of the exported chart",initial:I.export.defaultScale.value,min:.1,max:5},{type:"number",name:"rasterizationTimeout",message:"The rendering webpage timeout in milliseconds",initial:I.export.rasterizationTimeout.value}],customLogic:[{type:"toggle",name:"allowCodeExecution",message:"Enable execution of custom code",initial:I.customLogic.allowCodeExecution.value},{type:"toggle",name:"allowFileResources",message:"Enable file resources",initial:I.customLogic.allowFileResources.value}],server:[{type:"toggle",name:"enable",message:"Starts the server on 0.0.0.0",initial:I.server.enable.value},{type:"text",name:"host",message:"Server hostname",initial:I.server.host.value},{type:"number",name:"port",message:"Server port",initial:I.server.port.value},{type:"toggle",name:"benchmarking",message:"Enable server benchmarking",initial:I.server.benchmarking.value},{type:"text",name:"proxy.host",message:"The host of the proxy server to use",initial:I.server.proxy.host.value},{type:"number",name:"proxy.port",message:"The port of the proxy server to use",initial:I.server.proxy.port.value},{type:"number",name:"proxy.timeout",message:"The timeout for the proxy server to use",initial:I.server.proxy.timeout.value},{type:"toggle",name:"rateLimiting.enable",message:"Enable rate limiting",initial:I.server.rateLimiting.enable.value},{type:"number",name:"rateLimiting.maxRequests",message:"The maximum requests allowed per minute",initial:I.server.rateLimiting.maxRequests.value},{type:"number",name:"rateLimiting.window",message:"The rate-limiting time window in minutes",initial:I.server.rateLimiting.window.value},{type:"number",name:"rateLimiting.delay",message:"The delay for each successive request before reaching the maximum",initial:I.server.rateLimiting.delay.value},{type:"toggle",name:"rateLimiting.trustProxy",message:"Set to true if behind a load balancer",initial:I.server.rateLimiting.trustProxy.value},{type:"text",name:"rateLimiting.skipKey",message:"Allows bypassing the rate limiter when provided with the skipToken argument",initial:I.server.rateLimiting.skipKey.value},{type:"text",name:"rateLimiting.skipToken",message:"Allows bypassing the rate limiter when provided with the skipKey argument",initial:I.server.rateLimiting.skipToken.value},{type:"toggle",name:"ssl.enable",message:"Enable SSL protocol",initial:I.server.ssl.enable.value},{type:"toggle",name:"ssl.force",message:"Force serving only over HTTPS",initial:I.server.ssl.force.value},{type:"number",name:"ssl.port",message:"SSL server port",initial:I.server.ssl.port.value},{type:"text",name:"ssl.certPath",message:"The path to find the SSL certificate/key",initial:I.server.ssl.certPath.value}],pool:[{type:"number",name:"minWorkers",message:"The initial number of workers to spawn",initial:I.pool.minWorkers.value},{type:"number",name:"maxWorkers",message:"The maximum number of workers to spawn",initial:I.pool.maxWorkers.value},{type:"number",name:"workLimit",message:"The pieces of work that can be performed before restarting a Puppeteer process",initial:I.pool.workLimit.value},{type:"number",name:"acquireTimeout",message:"The number of milliseconds to wait for acquiring a resource",initial:I.pool.acquireTimeout.value},{type:"number",name:"createTimeout",message:"The number of milliseconds to wait for creating a resource",initial:I.pool.createTimeout.value},{type:"number",name:"destroyTimeout",message:"The number of milliseconds to wait for destroying a resource",initial:I.pool.destroyTimeout.value},{type:"number",name:"idleTimeout",message:"The number of milliseconds after an idle resource is destroyed",initial:I.pool.idleTimeout.value},{type:"number",name:"createRetryInterval",message:"The retry interval in milliseconds after a create process fails",initial:I.pool.createRetryInterval.value},{type:"number",name:"reaperInterval",message:"The reaper interval in milliseconds after triggering the check for idle resources to destroy",initial:I.pool.reaperInterval.value},{type:"toggle",name:"benchmarking",message:"Enable benchmarking for a resource pool",initial:I.pool.benchmarking.value}],logging:[{type:"number",name:"level",message:"The log level (0: silent, 1: error, 2: warning, 3: notice, 4: verbose, 5: benchmark)",initial:I.logging.level.value,round:0,min:0,max:5},{type:"text",name:"file",message:"A log file name. Set with --toFile and --logDest to enable file logging",initial:I.logging.file.value},{type:"text",name:"dest",message:"The path to a log file when the file logging is enabled",initial:I.logging.dest.value},{type:"toggle",name:"toConsole",message:"Enable logging to the console",initial:I.logging.toConsole.value},{type:"toggle",name:"toFile",message:"Enables logging to a file",initial:I.logging.toFile.value}],ui:[{type:"toggle",name:"enable",message:"Enable UI for the export server",initial:I.ui.enable.value},{type:"text",name:"route",message:"A route to attach the UI",initial:I.ui.route.value}],other:[{type:"text",name:"nodeEnv",message:"The type of Node.js environment",initial:I.other.nodeEnv.value},{type:"toggle",name:"listenToProcessExits",message:"Set to false to skip attaching process.exit handlers",initial:I.other.listenToProcessExits.value},{type:"toggle",name:"noLogo",message:"Skip printing the logo on startup. Replaced by simple text",initial:I.other.noLogo.value},{type:"toggle",name:"hardResetPage",message:"Decides if the page content should be reset entirely",initial:I.other.hardResetPage.value},{type:"toggle",name:"browserShellMode",message:"Decides if the browser runs in the shell mode",initial:I.other.browserShellMode.value}],debug:[{type:"toggle",name:"enable",message:"Enables debug mode for the browser instance",initial:I.debug.enable.value},{type:"toggle",name:"headless",message:"The mode setting for the browser",initial:I.debug.headless.value},{type:"toggle",name:"devtools",message:"The DevTools for the headful browser",initial:I.debug.devtools.value},{type:"toggle",name:"listenToConsole",message:"The event listener for console messages from the browser",initial:I.debug.listenToConsole.value},{type:"toggle",name:"dumpio",message:"Redirects the browser stdout and stderr to NodeJS process",initial:I.debug.dumpio.value},{type:"number",name:"slowMo",message:"Puppeteer operations slow down in milliseconds",initial:I.debug.slowMo.value},{type:"number",name:"debuggingPort",message:"The port number for debugging",initial:I.debug.debuggingPort.value}]},C=["options","globalOptions","themeOptions","resources","payload"],A={},P=(e,t="")=>{Object.keys(e).forEach((r=>{if(!["puppeteer","highcharts"].includes(r)){const o=e[r];void 0===o.value?P(o,`${t}.${r}`):(A[o.cliName||r]=`${t}.${r}`.substring(1),void 0!==o.legacyName&&(A[o.legacyName]=`${t}.${r}`.substring(1)))}}))};P(I),g.config();const H=e=>m.string().transform((t=>t.split(",").map((e=>e.trim())).filter((t=>e.includes(t))))).transform((e=>e.length?e:void 0)),$=()=>m.enum(["true","false",""]).transform((e=>""!==e?"true"===e:void 0)),D=e=>m.enum([...e,""]).transform((e=>""!==e?e:void 0)),G=()=>m.string().trim().refine((e=>!["false","undefined","null","NaN"].includes(e)||""===e),(e=>({message:`The string contains forbidden values, received '${e}'`}))).transform((e=>""!==e?e:void 0)),U=()=>m.string().trim().refine((e=>/^(\.\/|\.\.\/|\/|[a-zA-Z]:\\|[a-zA-Z]:\/)?((?:[\w-]+)[\\/]?)+$/.test(e)),{},{message:"The string is an invalid path directory string."}),M=()=>m.string().trim().refine((e=>""===e||!isNaN(parseFloat(e))&&parseFloat(e)>0),(e=>({message:`The value must be numeric and positive, received '${e}'`}))).transform((e=>""!==e?parseFloat(e):void 0)),j=()=>m.string().trim().refine((e=>""===e||!isNaN(parseFloat(e))&&parseFloat(e)>=0),(e=>({message:`The value must be numeric and non-negative, received '${e}'`}))).transform((e=>""!==e?parseFloat(e):void 0)),F=m.object({PUPPETEER_TEMP_DIR:U(),HIGHCHARTS_VERSION:m.string().trim().refine((e=>/^(latest|\d+(\.\d+){0,2})$/.test(e)||""===e),(e=>({message:`HIGHCHARTS_VERSION must be 'latest', a major version, or in the form XX.YY.ZZ, received '${e}'`}))).transform((e=>""!==e?e:void 0)),HIGHCHARTS_CDN_URL:m.string().trim().refine((e=>e.startsWith("https://")||e.startsWith("http://")||""===e),(e=>({message:`Invalid value for HIGHCHARTS_CDN_URL. It should start with http:// or https://, received '${e}'`}))).transform((e=>""!==e?e:void 0)),HIGHCHARTS_USE_NPM:$(),HIGHCHARTS_CORE_SCRIPTS:H(k.core),HIGHCHARTS_MODULE_SCRIPTS:H(k.modules),HIGHCHARTS_INDICATOR_SCRIPTS:H(k.indicators),HIGHCHARTS_FORCE_FETCH:$(),HIGHCHARTS_CACHE_PATH:G(),HIGHCHARTS_ADMIN_TOKEN:G(),EXPORT_TYPE:D(["jpeg","png","pdf","svg"]),EXPORT_CONSTR:D(["chart","stockChart","mapChart","ganttChart"]),EXPORT_DEFAULT_HEIGHT:M(),EXPORT_DEFAULT_WIDTH:M(),EXPORT_DEFAULT_SCALE:M(),EXPORT_RASTERIZATION_TIMEOUT:j(),CUSTOM_LOGIC_ALLOW_CODE_EXECUTION:$(),CUSTOM_LOGIC_ALLOW_FILE_RESOURCES:$(),SERVER_ENABLE:$(),SERVER_HOST:G(),SERVER_PORT:M(),SERVER_MAX_UPLOAD_SIZE:M(),SERVER_BENCHMARKING:$(),SERVER_PROXY_HOST:G(),SERVER_PROXY_PORT:M(),SERVER_PROXY_USERNAME:G(),SERVER_PROXY_PASSWORD:G(),SERVER_PROXY_TIMEOUT:j(),SERVER_RATE_LIMITING_ENABLE:$(),SERVER_RATE_LIMITING_MAX_REQUESTS:j(),SERVER_RATE_LIMITING_WINDOW:j(),SERVER_RATE_LIMITING_DELAY:j(),SERVER_RATE_LIMITING_TRUST_PROXY:$(),SERVER_RATE_LIMITING_SKIP_KEY:G(),SERVER_RATE_LIMITING_SKIP_TOKEN:G(),SERVER_SSL_ENABLE:$(),SERVER_SSL_FORCE:$(),SERVER_SSL_PORT:M(),SERVER_SSL_CERT_PATH:G(),POOL_MIN_WORKERS:j(),POOL_MAX_WORKERS:j(),POOL_WORK_LIMIT:M(),POOL_ACQUIRE_TIMEOUT:j(),POOL_CREATE_TIMEOUT:j(),POOL_DESTROY_TIMEOUT:j(),POOL_IDLE_TIMEOUT:j(),POOL_CREATE_RETRY_INTERVAL:j(),POOL_REAPER_INTERVAL:j(),POOL_BENCHMARKING:$(),LOGGING_LEVEL:m.string().trim().refine((e=>""===e||!isNaN(parseFloat(e))&&parseFloat(e)>=0&&parseFloat(e)<=5),(e=>({message:`Invalid value for LOGGING_LEVEL. We only accept values from 0 to 5 as logging levels, received '${e}'`}))).transform((e=>""!==e?parseFloat(e):void 0)),LOGGING_FILE:G(),LOGGING_DEST:G(),LOGGING_TO_CONSOLE:$(),LOGGING_TO_FILE:$(),UI_ENABLE:$(),UI_ROUTE:G(),OTHER_NODE_ENV:D(["development","production","test"]),OTHER_LISTEN_TO_PROCESS_EXITS:$(),OTHER_NO_LOGO:$(),OTHER_HARD_RESET_PAGE:$(),OTHER_BROWSER_SHELL_MODE:$(),OTHER_ALLOW_XLINK:$(),DEBUG_ENABLE:$(),DEBUG_HEADLESS:$(),DEBUG_DEVTOOLS:$(),DEBUG_LISTEN_TO_CONSOLE:$(),DEBUG_DUMPIO:$(),DEBUG_SLOW_MO:j(),DEBUG_DEBUGGING_PORT:M()}).partial().parse(process.env),W=["red","yellow","blue","gray","green"];let V={toConsole:!0,toFile:!1,pathCreated:!1,levelsDesc:[{title:"error",color:W[0]},{title:"warning",color:W[1]},{title:"notice",color:W[2]},{title:"verbose",color:W[3]},{title:"benchmark",color:W[4]}],listeners:[]};const q=(o,i)=>{V.pathCreated||(!e(V.dest)&&t(V.dest),V.pathCreated=!0),r(`${V.dest}${V.file}`,[i].concat(o).join(" ")+"\n",(e=>{e&&(console.log(`[logger] Unable to write to log file: ${e}`),V.toFile=!1)}))},B=(...e)=>{const[t,...r]=e,{levelsDesc:o,level:i}=V;if(5!==t&&(0===t||t>i||i>o.length))return;const s=`${(new Date).toString().split("(")[0].trim()} [${o[t-1].title}] -`;V.listeners.forEach((e=>{e(s,r.join(" "))})),V.toConsole&&console.log.apply(void 0,[s.toString()[V.levelsDesc[t-1].color]].concat(r)),V.toFile&&q(r,s)},X=(e,t,r)=>{const o=r||t.message,{level:i,levelsDesc:s}=V;if(0===e||e>i||i>s.length)return;const n=`${(new Date).toString().split("(")[0].trim()} [${s[e-1].title}] -`,a=t.message!==t.stackMessage||void 0===t.stackMessage?t.stack:t.stack.split("\n").slice(1).join("\n"),l=[o,"\n",a];V.toConsole&&console.log.apply(void 0,[n.toString()[V.levelsDesc[e-1].color]].concat([o[W[e-1]],"\n",a])),V.listeners.forEach((e=>{e(n,l.join(" "))})),V.toFile&&q(l,n)},K=e=>{e>=0&&e<=V.levelsDesc.length&&(V.level=e)},z=(e,t)=>{if(V={...V,dest:e||V.dest,file:t||V.file,toFile:!0},0===V.dest.length)return B(1,"[logger] File logging initialization: no path supplied.");V.dest.endsWith("/")||(V.dest+="/")},J=a(f(import.meta.url).resolve("highcharts/package.json")),Y=v(new URL("../.",import.meta.url)),Z=(e,t)=>{const r=["png","jpeg","pdf","svg"];if(t){const o=t.split(".").pop();"jpg"===o?e="jpeg":r.includes(o)&&e!==o&&(e=o)}return{"image/png":"png","image/jpeg":"jpeg","application/pdf":"pdf","image/svg+xml":"svg"}[e]||r.find((t=>t===e))||"png"},Q=(e=!1,t)=>{const r=["js","css","files"];let i=e,s=!1;if(t&&e.endsWith(".json"))try{i=ee(o(e,"utf8"))}catch(e){return X(2,e,"[cli] No resources found.")}else i=ee(e),i&&!t&&delete i.files;for(const e in i)r.includes(e)?s||(s=!0):delete i[e];return s?(i.files&&(i.files=i.files.map((e=>e.trim())),(!i.files||i.files.length<=0)&&delete i.files),i):B(3,"[cli] No resources found.")};function ee(e,t){try{const r=JSON.parse("string"!=typeof e?JSON.stringify(e):e);return"string"!=typeof r&&t?JSON.stringify(r):r}catch{return!1}}const te=e=>{if(null===e||"object"!=typeof e)return e;const t=Array.isArray(e)?[]:{};for(const r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=te(e[r]));return t},re=(e,t)=>JSON.stringify(e,((e,r)=>("string"==typeof r&&((r=r.trim()).startsWith("function(")||r.startsWith("function ("))&&r.endsWith("}")&&(r=t?`EXP_FUN${(r+"").replaceAll(/\n|\t|\r/g," ")}EXP_FUN`:void 0),"function"==typeof r?`EXP_FUN${(r+"").replaceAll(/\n|\t|\r/g," ")}EXP_FUN`:r))).replaceAll(/"EXP_FUN|EXP_FUN"/g,"");function oe(){console.log("\nUsage of CLI arguments:".bold,"\n------",`\nFor more detailed information, visit the readme at: ${"https://github.com/highcharts/node-export-server#readme".bold.yellow}.`);const e=t=>{for(const[r,o]of Object.entries(t))if(Object.prototype.hasOwnProperty.call(o,"value")){let e=` --${o.cliName||r} ${("<"+o.type+">").green} `;if(e.length<48)for(let t=e.length;t<48;t++)e+=".";console.log(e,o.description,`[Default: ${o.value.toString().bold}]`.blue)}else e(o)};Object.keys(I).forEach((t=>{["puppeteer","highcharts"].includes(t)||(console.log(`\n${t.toUpperCase()}`.red),e(I[t]))})),console.log("\n")}const ie=e=>!["false","undefined","null","NaN","0",""].includes(e)&&!!e,se=(e,t)=>{if(e&&"string"==typeof e)return(e=e.trim()).endsWith(".js")?!!t&&se(o(e,"utf8")):e.startsWith("function()")||e.startsWith("function ()")||e.startsWith("()=>")||e.startsWith("() =>")?`(${e})()`:e.replace(/;$/,"")},ne=()=>{const e=process.hrtime.bigint();return()=>Number(process.hrtime.bigint()-e)/1e6};let ae={};const le=()=>ae,ce=(e,t,r=[])=>{const o=te(e);for(const[e,s]of Object.entries(t))o[e]="object"!=typeof(i=s)||Array.isArray(i)||null===i||r.includes(e)||void 0===o[e]?void 0!==s?s:o[e]:ce(o[e],s,r);var i;return o};function pe(e,t={},r=""){Object.keys(e).forEach((o=>{const i=e[o],s=t&&t[o];void 0===i.value?pe(i,s,`${r}.${o}`):(void 0!==s&&(i.value=s),i.envLink in F&&void 0!==F[i.envLink]&&(i.value=F[i.envLink]))}))}function he(e){let t={};for(const[r,o]of Object.entries(e))t[r]=Object.prototype.hasOwnProperty.call(o,"value")?o.value:he(o);return t}function ue(e,t,r){for(;t.length>1;){const o=t.shift();return Object.prototype.hasOwnProperty.call(e,o)||(e[o]={}),e[o]=ue(Object.assign({},e[o]),t,r),e}return e[t[0]]=r,e}async function de(e,t={}){return new Promise(((r,o)=>{const i=(e=>e.startsWith("https")?b:y)(e);i.get(e,Object.assign({headers:{"User-Agent":"highcharts/export",Referer:"highcharts.export"}},t||{}),(e=>{let t="";e.on("data",(e=>{t+=e})),e.on("end",(()=>{t||o("Nothing was fetched from the URL."),e.text=t,r(e)}))})).on("error",(e=>{o(e)}))}))}class ge extends Error{constructor(e){super(),this.message=e,this.stackMessage=e}setError(e){return this.error=e,e.name&&(this.name=e.name),e.statusCode&&(this.statusCode=e.statusCode),e.stack&&(this.stackMessage=e.message,this.stack=e.stack),this}}const me={cdnURL:"https://code.highcharts.com/",activeManifest:{},sources:"",hcVersion:""},fe=e=>e.sources.substring(0,e.sources.indexOf("*/")).replace("/*","").replace("*/","").replace(/\n/g,"").trim(),ve=e=>e.replace(/\\/g,"/").split("/").pop().replace(/\.js$/i,""),ye=async(e,t,r,i=!1,s=!1)=>{let n;if(e.endsWith(".js")||(e=`${e}.js`),i)try{B(4,`[cache] Fetching script from NPM - ${l("node_modules","highcharts",e)}`);const t=c(J,e);if(!t.startsWith(c(J)+p))throw new ge(`[cache] Invalid script path detected for '${e}'. Directory traversal attempt or bad version input.`,403);return n=o(t,"utf8"),r&&n&&(r[ve(e)]=1),n}catch{}else if(B(4,`[cache] Fetching script from CDN - ${e}`),n=await de(e,t),200===n.statusCode&&"string"==typeof n.text)return r&&(r[ve(e)]=1),n.text;if(s)throw new ge(`[cache] Could not fetch the mandatory ${e}. The script might not exist in the requested version.`,404);return B(2,`[cache] Could not fetch the ${e}. The script might not exist in the requested version.`),""},be=async(e,t,r)=>{try{const o={};return me.sources=await(async(e,t,r)=>{const o=e.version,i="latest"!==o&&o?`${o}/`:"",s=e.cdnURL||me.cdnURL;B(3,`[cache] Updating cache version to Highcharts: ${i||"latest"}.`);const n=e.useNpm;let a;const{host:c,port:p,username:h,password:d}=t;if(c&&p)try{a=new u({host:c,port:p,...h&&d?{username:h,password:d}:{}})}catch(e){throw new ge("[cache] Could not create a Proxy Agent.").setError(e)}const g=a?{agent:a,timeout:F.SERVER_PROXY_TIMEOUT}:{};return(await Promise.all([...e.coreScripts.map((e=>ye(n&&e||`${s}${i}${e}`,g,r,n,!0))),...e.moduleScripts.map((e=>ye(n&&l("modules",e)||("map"===e?`${s}maps/${i}modules/${e}`:`${s}${i}modules/${e}`),g,r,n))),...e.indicatorScripts.map((e=>ye(n&&l("indicators",e)||`${s}stock/${i}indicators/${e}`,g,r,n))),...e.customScripts.map((e=>ye(`${e}`,g)))])).join(";\n")})(e,t,o),me.hcVersion=fe(me),s(r,me.sources),o}catch(e){throw new ge("[cache] Unable to update the local Highcharts cache.").setError(e)}},we=async r=>{const{highcharts:i,server:n}=r,a=l(Y,i.cachePath);let c;const p=l(a,"manifest.json"),h=l(a,"sources.js");if(!e(a)&&t(a),!e(p)||i.forceFetch)B(3,"[cache] Fetching and caching Highcharts dependencies."),c=await be(i,n.proxy,h);else{let e=!1;const t=JSON.parse(o(p));if(t.modules&&Array.isArray(t.modules)){const e={};t.modules.forEach((t=>e[t]=1)),t.modules=e}const{coreScripts:r,moduleScripts:s,indicatorScripts:a}=i,l=r.length+s.length+a.length;t.version!==i.version?(B(2,"[cache] A Highcharts version mismatch in the cache, need to re-fetch."),e=!0):Object.keys(t.modules||{}).length!==l?(B(2,"[cache] The cache and the requested modules do not match, need to re-fetch."),e=!0):e=(s||[]).some((e=>{if(!t.modules[e])return B(2,`[cache] The ${e} is missing in the cache, need to re-fetch.`),!0})),e?c=await be(i,n.proxy,h):(B(3,"[cache] Dependency cache is up to date, proceeding."),me.sources=o(h,"utf8"),c=t.modules,me.hcVersion=fe(me))}await(async(e,t)=>{const r={version:e.version,modules:t||{}};me.activeManifest=r,B(3,"[cache] Writing a new manifest.");try{s(l(Y,e.cachePath,"manifest.json"),JSON.stringify(r),"utf8")}catch(e){throw new ge("[cache] Error writing the cache manifest.").setError(e)}})(i,c)},Ee=()=>l(Y,le().highcharts.cachePath),Te=()=>me.hcVersion;function Se(){Highcharts.animObject=function(){return{duration:0}}}async function Re(e,t,r){window._displayErrors=r;const{getOptions:o,merge:i,setOptions:s,wrap:n}=Highcharts;Highcharts.setOptionsObj=i(!1,{},o());const a={animation:!1};t.export.strInj&&(a.height=e.chart.height,a.width=e.chart.width),window.isRenderComplete=!1,n(Highcharts.Chart.prototype,"init",(function(e,t,r){((t=i(t,{exporting:{enabled:!1},plotOptions:{series:{label:{enabled:!1}}},tooltip:{}})).series||[]).forEach((function(e){e.animation=!1})),window.onHighchartsRender||(window.onHighchartsRender=Highcharts.addEvent(this,"render",(()=>{window.isRenderComplete=!0}))),e.apply(this,[t,r])})),n(Highcharts.Series.prototype,"init",(function(e,t,r){e.apply(this,[t,r])}));const l=t.export.strInj?new Function(`return ${t.export.strInj}`)():e;t.customLogic.customCode&&new Function("options",t.customLogic.customCode)(l);const c=i(!1,JSON.parse(t.export.themeOptions),l,{chart:a}),p=t.customLogic.callback?new Function(`return ${t.customLogic.callback}`)():void 0,h=JSON.parse(t.export.globalOptions);h&&s(h);let u=t.export.constr||"chart";u=void 0!==Highcharts[u]?u:"chart",Highcharts[u]("container",c,p);const d=o();for(const e in d)"function"!=typeof d[e]&&delete d[e];s(Highcharts.setOptionsObj),Highcharts.setOptionsObj={}}const xe=o(Y+"/templates/template.html","utf8");let _e;async function Oe(){if(!_e)return!1;const e=await _e.newPage();return await e.setCacheEnabled(!1),await ke(e),function(e){const{debug:t}=le();t.enable&&t.listenToConsole&&e.on("console",(e=>{console.log(`[debug] ${e.text()}`)}));e.on("pageerror",(async t=>{e.isClosed()||await e.$eval("#container",((e,t)=>{window._displayErrors&&(e.innerHTML=t)}),`<h1>Chart input data error: </h1>${t.toString()}`)}))}(e),e}async function Le(e,t){try{for(const e of t)await e.dispose();await e.evaluate((()=>{if("undefined"!=typeof Highcharts){const e=Highcharts.charts;if(Array.isArray(e)&&e.length)for(const t of e)t&&t.destroy(),Highcharts.charts.shift()}const[...e]=document.getElementsByTagName("script"),[,...t]=document.getElementsByTagName("style"),[...r]=document.getElementsByTagName("link");for(const o of[...e,...t,...r])o.remove()}))}catch(e){X(2,e,"[browser] Could not clear page's resources.")}}async function ke(e){await e.setContent(xe,{waitUntil:"domcontentloaded"}),await e.addScriptTag({path:`${Ee()}/sources.js`}),await e.evaluate(Se)}const Ie=async(e,t,r,o)=>{r.export.instr=null,r.export.infile=null;const i=Buffer.byteLength(r.export?.strInj?r.export?.strInj:JSON.stringify(t),"utf-8");if(B(4,`[export] The current total size of data passed to a page is around ${(i/1048576).toFixed(2)} MB`),i>=104857600)throw new ge("[export] The data passed to a page exceeded 100MB.");return e.evaluate(Re,t,r,o)};var Ne=async(e,t,r)=>{let i=[];try{B(4,"[export] Determining export path.");const s=r.export,a=s?.options?.chart?.displayErrors&&me.activeManifest.modules.debugger;let l;if(t.indexOf&&(t.indexOf("<svg")>=0||t.indexOf("<?xml")>=0)){if(B(4,"[export] Treating as SVG."),"svg"===s.type)return t;l=!0,await e.setContent((e=>`\n<!DOCTYPE html>\n<html lang='en-US'>\n <head>\n <meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n <title>Highcharts Export</title>\n </head>\n <style>\n \n\nhtml, body {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\n#table-div, #sliders, #datatable, #controls, .ld-row {\n display: none;\n height: 0;\n}\n\n#chart-container {\n box-sizing: border-box;\n margin: 0;\n overflow: auto;\n font-size: 0;\n}\n\n#chart-container > figure, div {\n margin-top: 0 !important;\n margin-bottom: 0 !important;\n}\n\n\n </style>\n <body>\n <div id="chart-container">\n ${e}\n </div>\n </body>\n</html>\n\n`)(t),{waitUntil:"domcontentloaded"})}else B(4,"[export] Treating as config."),s.strInj?await Ie(e,{chart:{height:s.height,width:s.width}},r,a):(t.chart.height=s.height,t.chart.width=s.width,await Ie(e,t,r,a));i=await async function(e,t){const r=[],i=t.customLogic.resources;if(i){const s=[];if(i.js&&s.push({content:i.js}),i.files)for(const e of i.files){const t=!e.startsWith("http");s.push(t?{content:o(e,"utf8")}:{url:e})}for(const t of s)try{r.push(await e.addScriptTag(t))}catch(e){X(2,e,"[export] The JS resource cannot be loaded.")}s.length=0;const a=[];if(i.css){let o=i.css.match(/@import\s*([^;]*);/g);if(o)for(let e of o)e&&(e=e.replace("url(","").replace("@import","").replace(/"/g,"").replace(/'/g,"").replace(/;/,"").replace(/\)/g,"").trim(),e.startsWith("http")?a.push({url:e}):t.customLogic.allowFileResources&&a.push({path:n.join(Y,e)}));a.push({content:i.css.replace(/@import\s*([^;]*);/g,"")||" "});for(const t of a)try{r.push(await e.addStyleTag(t))}catch(e){X(2,e,"[export] The CSS resource cannot be loaded.")}a.length=0}}return r}(e,r);const c=l?await e.evaluate((e=>{const t=document.querySelector("#chart-container svg:first-of-type"),r=t.height.baseVal.value*e,o=t.width.baseVal.value*e;return document.body.style.zoom=e,document.body.style.margin="0px",{chartHeight:r,chartWidth:o}}),parseFloat(s.scale)):await e.evaluate((()=>{const{chartHeight:e,chartWidth:t}=window.Highcharts.charts[0];return document.body.style.zoom=1,{chartHeight:e,chartWidth:t}})),p=Math.abs(Math.ceil(c.chartHeight||s.height)),h=Math.abs(Math.ceil(c.chartWidth||s.width)),{x:u,y:d}=await(e=>e.$eval("#chart-container",(e=>{const{x:t,y:r,width:o,height:i}=e.getBoundingClientRect();return{x:t,y:r,width:o,height:Math.trunc(i>1?i:500)}})))(e);let g;if(await e.setViewport({height:p,width:h,deviceScaleFactor:l?1:parseFloat(s.scale)}),"svg"===s.type)g=await(e=>e.$eval("#container svg:first-of-type",(e=>e.outerHTML)))(e);else if(["png","jpeg"].includes(s.type))g=await((e,t,r,o,i)=>Promise.race([e.screenshot({type:t,encoding:r,clip:o,captureBeyondViewport:!0,fullPage:!1,optimizeForSpeed:!0,..."png"!==t?{quality:80}:{},omitBackground:"png"==t}),new Promise(((e,t)=>setTimeout((()=>t(new ge("Rasterization timeout"))),i||1500)))]))(e,s.type,"base64",{width:h,height:p,x:u,y:d},s.rasterizationTimeout);else{if("pdf"!==s.type)throw new ge(`[export] Unsupported output format ${s.type}.`);g=await(async(e,t,r,o,i)=>(await e.emulateMediaType("screen"),e.pdf({height:t+1,width:r,encoding:o,timeout:i||1500})))(e,p,h,"base64",s.rasterizationTimeout)}return await Le(e,i),g}catch(t){return await Le(e,i),t}};let Ce=!1;const Ae={performedExports:0,exportAttempts:0,exportFromSvgAttempts:0,timeSpent:0,droppedExports:0,spentAverage:0};let Pe={};const He={create:async()=>{let e=!1;const t=E(),r=(new Date).getTime();try{if(e=await Oe(),!e||e.isClosed())throw new ge("The page is invalid or closed.");B(3,`[pool] Successfully created a worker ${t} - took ${(new Date).getTime()-r} ms.`)}catch(e){throw new ge("Error encountered when creating a new page.").setError(e)}return{id:t,page:e,workCount:Math.round(Math.random()*(Pe.workLimit/2))}},validate:async e=>!(!e.page||e.page?.isClosed())&&(!(Pe.workLimit&&++e.workCount>Pe.workLimit)||(B(3,`[pool] Worker failed validation: exceeded work limit (limit is ${Pe.workLimit}).`),!1)),destroy:async e=>{B(3,`[pool] Destroying pool entry ${e.id}.`),e.page&&!e.page.isClosed()&&await e.page.close()}},$e=async e=>{if(Pe=e&&e.pool?{...e.pool}:{},await async function(e){const{puppeteer:t,debug:r,other:o}=le(),{enable:i,...s}=r,n={headless:!o.browserShellMode||"shell",userDataDir:t.tempDir||"./tmp/",args:e,handleSIGINT:!1,handleSIGTERM:!1,handleSIGHUP:!1,waitForInitialPage:!1,defaultViewport:null,...i&&s};if(!_e){const e=25;let t=0;const r=async()=>{try{B(3,`[browser] Attempting to get a browser instance (try ${++t}).`),_e=await T.launch(n)}catch(o){if(X(2,o,`[browser] Failed to launch a browser instance - retrying (attempt ${t}/${e}).`),!(t<25))throw o;B(3,`[browser] Retry to open a browser (attempt ${t}/${e}).`),await new Promise((e=>setTimeout(e,4e3))),await r()}};try{await r(),"shell"===n.headless&&B(3,"[browser] Launched browser in shell mode."),i&&B(3,"[browser] Launched browser in debug mode.")}catch(e){throw new ge("[browser] Maximum retries to open a browser instance reached.").setError(e)}if(!_e)throw new ge("[browser] Cannot find a browser to open.")}return _e}(e.puppeteerArgs),B(3,`[pool] Initializing pool with workers: min ${Pe.minWorkers}, max ${Pe.maxWorkers}.`),Ce)return B(4,"[pool] Already initialized, please kill it before creating a new one.");parseInt(Pe.minWorkers)>parseInt(Pe.maxWorkers)&&(Pe.minWorkers=Pe.maxWorkers);try{Ce=new w({...He,min:parseInt(Pe.minWorkers),max:parseInt(Pe.maxWorkers),acquireTimeoutMillis:Pe.acquireTimeout,createTimeoutMillis:Pe.createTimeout,destroyTimeoutMillis:Pe.destroyTimeout,idleTimeoutMillis:Pe.idleTimeout,createRetryIntervalMillis:Pe.createRetryInterval,reapIntervalMillis:Pe.reaperInterval,propagateCreateError:!1}),Ce.on("release",(async e=>{const t=await async function(e,t=!1){try{if(e&&!e.isClosed())return t?(await e.goto("about:blank",{waitUntil:"domcontentloaded"}),await ke(e)):await e.evaluate((()=>{document.body.innerHTML='<div id="chart-container"><div id="container"></div></div>'})),!0}catch(e){X(2,e,"[browser] Could not clear the content of the page.")}return!1}(e.page,!1);B(4,`[pool] Releasing a worker with ID ${e.id}. Clear page status: ${t}.`)})),Ce.on("destroySuccess",((e,t)=>{B(4,`[pool] Destroyed a worker with ID ${t.id}.`),t.page=null}));const e=[];for(let t=0;t<Pe.minWorkers;t++)try{const t=await Ce.acquire().promise;e.push(t)}catch(e){X(2,e,"[pool] Could not create an initial resource.")}e.forEach((e=>{Ce.release(e)})),B(3,"[pool] The pool is ready"+(e.length?` with ${e.length} initial resources waiting.`:"."))}catch(e){throw new ge("[pool] Could not create the pool of workers.").setError(e)}};async function De(){if(B(3,"[pool] Killing pool with all workers and closing browser."),Ce){for(const e of Ce.used)Ce.release(e.resource);Ce.destroyed||(await Ce.destroy(),B(4,"[browser] Destroyed the pool of resources."))}await async function(){_e?.connected&&await _e.close(),B(4,"[browser] Closed the browser.")}()}const Ge=async(e,t)=>{let r;try{if(B(4,"[pool] Work received, starting to process."),++Ae.exportAttempts,Pe.benchmarking&&Me(),!Ce)throw new ge("Work received, but pool has not been started.");const o=ne();try{B(4,"[pool] Acquiring a worker handle."),r=await Ce.acquire().promise,t.server.benchmarking&&B(5,t.payload?.requestId?`[benchmark] Request with ID ${t.payload?.requestId} -`:"[benchmark]",`Acquired a worker handle: ${o()}ms.`)}catch(e){throw new ge((t.payload?.requestId?`For request with ID ${t.payload?.requestId} - `:"")+`Error encountered when acquiring an available entry: ${o()}ms.`).setError(e)}if(B(4,"[pool] Acquired a worker handle."),!r.page)throw new ge("Resolved worker page is invalid: the pool setup is wonky.");let i=(new Date).getTime();B(4,`[pool] Starting work on pool entry with ID ${r.id}.`);const s=ne(),n=await Ne(r.page,e,t);if(n instanceof Error)throw"Rasterization timeout"===n.message&&(r.workCount=Pe.workLimit+1,r.page=null),"TimeoutError"===n.name||"Rasterization timeout"===n.message?new ge("Rasterization timeout: your chart may be too complex or large, and failed to render within the allotted time.").setError(n):new ge((t.payload?.requestId?`For request with ID ${t.payload?.requestId} - `:"")+`Error encountered during export: ${s()}ms.`).setError(n);t.server.benchmarking&&B(5,t.payload?.requestId?`[benchmark] Request with ID ${t.payload?.requestId} -`:"[benchmark]",`Exported a chart sucessfully: ${s()}ms.`),Ce.release(r);const a=(new Date).getTime()-i;return Ae.timeSpent+=a,Ae.spentAverage=Ae.timeSpent/++Ae.performedExports,B(4,`[pool] Work completed in ${a} ms.`),{result:n,options:t}}catch(e){throw++Ae.droppedExports,r&&Ce.release(r),new ge(`[pool] In pool.postWork: ${e.message}`).setError(e)}},Ue=()=>({min:Ce.min,max:Ce.max,all:Ce.numFree()+Ce.numUsed(),available:Ce.numFree(),used:Ce.numUsed(),pending:Ce.numPendingAcquires()});function Me(){const{min:e,max:t,all:r,available:o,used:i,pending:s}=Ue();B(5,`[pool] The minimum number of resources allowed by pool: ${e}.`),B(5,`[pool] The maximum number of resources allowed by pool: ${t}.`),B(5,`[pool] The number of all created resources: ${r}.`),B(5,`[pool] The number of available resources: ${o}.`),B(5,`[pool] The number of acquired resources: ${i}.`),B(5,`[pool] The number of resources waiting to be acquired: ${s}.`)}var je=Ue,Fe=()=>Ae;let We=!1;const Ve=async(e,t)=>{B(4,"[chart] Starting the exporting process.");const r=((e,t={})=>{let r={};return e.svg?(r=te(t),r.export.type=e.type||e.export.type,r.export.scale=e.scale||e.export.scale,r.export.outfile=e.outfile||e.export.outfile,r.payload={svg:e.svg}):r=ce(t,e,C),r.export.outfile=r.export?.outfile||`chart.${r.export?.type||"png"}`,r})(e,le()),i=r.export;if(r.payload?.svg&&""!==r.payload.svg)try{B(4,"[chart] Attempting to export from a SVG input.");const e=Ke(function(e){const t=[];F.OTHER_ALLOW_XLINK||t.push("xlink:href");const r=new S("").window;return R(r).sanitize(e,{ADD_TAGS:["foreignObject"],FORBID_ATTR:t,HTML_INTEGRATION_POINTS:{foreignobject:!0}})}(r.payload.svg),r,t);return++Ae.exportFromSvgAttempts,e}catch(e){return t(new ge("[chart] Error loading SVG input.").setError(e))}if(i.infile&&i.infile.length)try{return B(4,"[chart] Attempting to exp