   - - - {"files":{"node_modules":{"files":{"@electron-toolkit":{"files":{"preload":{"files":{"LICENSE":{"size":1074,"integrity":{"algorithm":"SHA256","hash":"14e3f2932ddf62cc5ee8f65f24a74b223a31f164709ca19a731b39ce60874d32","blockSize":4194304,"blocks":["14e3f2932ddf62cc5ee8f65f24a74b223a31f164709ca19a731b39ce60874d32"]},"offset":"0"},"dist":{"files":{"index.cjs":{"size":3178,"integrity":{"algorithm":"SHA256","hash":"a591a7f58d26674a10f2d404874a7b01d9ebc617419c21b74773a6c77912c067","blockSize":4194304,"blocks":["a591a7f58d26674a10f2d404874a7b01d9ebc617419c21b74773a6c77912c067"]},"offset":"1074"},"index.mjs":{"size":3010,"integrity":{"algorithm":"SHA256","hash":"507f0422595d6b1f762094282ae9a88113fef8cc6957401f6d57babcaf56ba44","blockSize":4194304,"blocks":["507f0422595d6b1f762094282ae9a88113fef8cc6957401f6d57babcaf56ba44"]},"offset":"4252"}}},"package.json":{"size":755,"integrity":{"algorithm":"SHA256","hash":"efb1ca72e8cffff338d8e3699fed31168f31bb39513a7a764eee8d413516f406","blockSize":4194304,"blocks":["efb1ca72e8cffff338d8e3699fed31168f31bb39513a7a764eee8d413516f406"]},"offset":"7262"}}},"utils":{"files":{"LICENSE":{"size":1074,"integrity":{"algorithm":"SHA256","hash":"14e3f2932ddf62cc5ee8f65f24a74b223a31f164709ca19a731b39ce60874d32","blockSize":4194304,"blocks":["14e3f2932ddf62cc5ee8f65f24a74b223a31f164709ca19a731b39ce60874d32"]},"offset":"8017"},"dist":{"files":{"index.cjs":{"size":3021,"integrity":{"algorithm":"SHA256","hash":"78da76a5b907949af248fa24acf9bc358a7010a6d800fbee8be1836a7a99bbbb","blockSize":4194304,"blocks":["78da76a5b907949af248fa24acf9bc358a7010a6d800fbee8be1836a7a99bbbb"]},"offset":"9091"},"index.d.cts":{"size":2373,"integrity":{"algorithm":"SHA256","hash":"194779039dc8a41af2eefa2ff740594be9cf44333870346c20602031ad73f168","blockSize":4194304,"blocks":["194779039dc8a41af2eefa2ff740594be9cf44333870346c20602031ad73f168"]},"offset":"12112"},"index.d.mts":{"size":2373,"integrity":{"algorithm":"SHA256","hash":"194779039dc8a41af2eefa2ff740594be9cf44333870346c20602031ad73f168","blockSize":4194304,"blocks":["194779039dc8a41af2eefa2ff740594be9cf44333870346c20602031ad73f168"]},"offset":"14485"},"index.mjs":{"size":2907,"integrity":{"algorithm":"SHA256","hash":"adf3a06d74a13390fce0580af9d00098e76b54fe7b92602203b8996692b06219","blockSize":4194304,"blocks":["adf3a06d74a13390fce0580af9d00098e76b54fe7b92602203b8996692b06219"]},"offset":"16858"}}},"package.json":{"size":744,"integrity":{"algorithm":"SHA256","hash":"9c372ef467b830858f446428a3350170a8467d3ca8a4a31f20006c548a17ddf5","blockSize":4194304,"blocks":["9c372ef467b830858f446428a3350170a8467d3ca8a4a31f20006c548a17ddf5"]},"offset":"19765"}}}}},"argparse":{"files":{"LICENSE":{"size":12775,"integrity":{"algorithm":"SHA256","hash":"de4d1f2d2ad5ad0cfd1657a106476b31cb5db5ef9d1ff842b237c0c81f0c8a23","blockSize":4194304,"blocks":["de4d1f2d2ad5ad0cfd1657a106476b31cb5db5ef9d1ff842b237c0c81f0c8a23"]},"offset":"20509"},"argparse.js":{"size":129714,"integrity":{"algorithm":"SHA256","hash":"2e73e7a3167ba840dbcf41feeafc3544a3e2b39220b5e997133c519861febf16","blockSize":4194304,"blocks":["2e73e7a3167ba840dbcf41feeafc3544a3e2b39220b5e997133c519861febf16"]},"offset":"33284"},"lib":{"files":{"sub.js":{"size":2252,"integrity":{"algorithm":"SHA256","hash":"2bc4ef9e87c47f1a4e0cfcb3706d886e0d73edce88149e300d2364066f396ed6","blockSize":4194304,"blocks":["2bc4ef9e87c47f1a4e0cfcb3706d886e0d73edce88149e300d2364066f396ed6"]},"offset":"162998"},"textwrap.js":{"size":17391,"integrity":{"algorithm":"SHA256","hash":"2550466c9a0425fa583a70e25bb93e190fe09b61f7de4861ea8ec54b7b899db0","blockSize":4194304,"blocks":["2550466c9a0425fa583a70e25bb93e190fe09b61f7de4861ea8ec54b7b899db0"]},"offset":"165250"}}},"package.json":{"size":448,"integrity":{"algorithm":"SHA256","hash":"800e809f5cdb0a7dec1834e1d2c0a165b1b63c2d6d7b2a97034b8c668de24a8f","blockSize":4194304,"blocks":["800e809f5cdb0a7dec1834e1d2c0a165b1b63c2d6d7b2a97034b8c668de24a8f"]},"offset":"182641"}}},"debug":{"files":{"LICENSE":{"size":1139,"integrity":{"algorithm":"SHA256","hash":"3a61c6c96caf5c1d9b623fb9b04c822b783dfcb78aa7e49c76a3f643e6ed7f95","blockSize":4194304,"blocks":["3a61c6c96caf5c1d9b623fb9b04c822b783dfcb78aa7e49c76a3f643e6ed7f95"]},"offset":"183089"},"package.json":{"size":910,"integrity":{"algorithm":"SHA256","hash":"85f3f142cda5b1a1ed18f4a5181a6c6b31b07a6d35da48dacc507586924c7ccd","blockSize":4194304,"blocks":["85f3f142cda5b1a1ed18f4a5181a6c6b31b07a6d35da48dacc507586924c7ccd"]},"offset":"184228"},"src":{"files":{"browser.js":{"size":6103,"integrity":{"algorithm":"SHA256","hash":"19920671f5902f64ad8ea11767fa50ea9d7a71ae0b7dff7ba5693c0075afc763","blockSize":4194304,"blocks":["19920671f5902f64ad8ea11767fa50ea9d7a71ae0b7dff7ba5693c0075afc763"]},"offset":"185138"},"common.js":{"size":6915,"integrity":{"algorithm":"SHA256","hash":"dbe83d2bb5837f3c4d7fe537b8004c585987270eceed5b06b8e078deb0ae214a","blockSize":4194304,"blocks":["dbe83d2bb5837f3c4d7fe537b8004c585987270eceed5b06b8e078deb0ae214a"]},"offset":"191241"},"index.js":{"size":314,"integrity":{"algorithm":"SHA256","hash":"aa127ff1752b7d9c7415c5c7bb6994d9aa722b81bcbcab4bd48316b013d23bf3","blockSize":4194304,"blocks":["aa127ff1752b7d9c7415c5c7bb6994d9aa722b81bcbcab4bd48316b013d23bf3"]},"offset":"198156"},"node.js":{"size":4728,"integrity":{"algorithm":"SHA256","hash":"d7b26d7c92f8ea7794b77ce11f3c11cd18c9084df7c357e3c7025344fa28aac6","blockSize":4194304,"blocks":["d7b26d7c92f8ea7794b77ce11f3c11cd18c9084df7c357e3c7025344fa28aac6"]},"offset":"198470"}}}}},"electron-log":{"files":{"LICENSE":{"size":1082,"integrity":{"algorithm":"SHA256","hash":"8a7030a9df0eac3ba1948991278d847d3e4c8dc4908a777b5868692c975ccfa8","blockSize":4194304,"blocks":["8a7030a9df0eac3ba1948991278d847d3e4c8dc4908a777b5868692c975ccfa8"]},"offset":"203198"},"main.js":{"size":75,"integrity":{"algorithm":"SHA256","hash":"fae41b809b95f890613ddda64561cd0fa4b3cc1de2c5aa2df753b31b02123365","blockSize":4194304,"blocks":["fae41b809b95f890613ddda64561cd0fa4b3cc1de2c5aa2df753b31b02123365"]},"offset":"204280"},"node.js":{"size":75,"integrity":{"algorithm":"SHA256","hash":"3fdad739e0f2096fef0196a841d4a5fd7b84a355a1e07247fe0ada59e3215bed","blockSize":4194304,"blocks":["3fdad739e0f2096fef0196a841d4a5fd7b84a355a1e07247fe0ada59e3215bed"]},"offset":"204355"},"package.json":{"size":1036,"integrity":{"algorithm":"SHA256","hash":"8ef6744fddf5ed3e81dad36ff7b370c111cc09d6257d46ee6a7b3c27f17979ff","blockSize":4194304,"blocks":["8ef6744fddf5ed3e81dad36ff7b370c111cc09d6257d46ee6a7b3c27f17979ff"]},"offset":"204430"},"preload.js":{"size":106,"integrity":{"algorithm":"SHA256","hash":"cfbc921386f62a953a6aa967b047b6aae1a6fd2268ea02f6fea6da164da34d30","blockSize":4194304,"blocks":["cfbc921386f62a953a6aa967b047b6aae1a6fd2268ea02f6fea6da164da34d30"]},"offset":"205466"},"renderer.js":{"size":87,"integrity":{"algorithm":"SHA256","hash":"5a21e4441e3894b7e786482d3c7ea770874a307d4673ba180fa9a6591bbb8cfa","blockSize":4194304,"blocks":["5a21e4441e3894b7e786482d3c7ea770874a307d4673ba180fa9a6591bbb8cfa"]},"offset":"205572"},"src":{"files":{"core":{"files":{"Buffering.js":{"size":613,"integrity":{"algorithm":"SHA256","hash":"1554b35c7baba7c1d91dee9458e66d5163be59bfc1f2c713589e379d7516983d","blockSize":4194304,"blocks":["1554b35c7baba7c1d91dee9458e66d5163be59bfc1f2c713589e379d7516983d"]},"offset":"205659"},"Logger.js":{"size":5471,"integrity":{"algorithm":"SHA256","hash":"2572098d75d2737989517b5d27bd37bf6eab1ca846271d69a96d625e60a64255","blockSize":4194304,"blocks":["2572098d75d2737989517b5d27bd37bf6eab1ca846271d69a96d625e60a64255"]},"offset":"206272"},"scope.js":{"size":854,"integrity":{"algorithm":"SHA256","hash":"5a57c42dd543207fd96056b101df00eb97f3f19dffffc17c826b9e2a026a0c04","blockSize":4194304,"blocks":["5a57c42dd543207fd96056b101df00eb97f3f19dffffc17c826b9e2a026a0c04"]},"offset":"211743"},"transforms":{"files":{"format.js":{"size":4094,"integrity":{"algorithm":"SHA256","hash":"2163c8bcaf2e74f8167b4bcb84dd2211d7451f558844721c7944ff884ff1b7f8","blockSize":4194304,"blocks":["2163c8bcaf2e74f8167b4bcb84dd2211d7451f558844721c7944ff884ff1b7f8"]},"offset":"212597"},"style.js":{"size":1520,"integrity":{"algorithm":"SHA256","hash":"d786b2dbb92743dfdc33bec9a12ce215b911aaef59f8d88d6bb282d4bd593b02","blockSize":4194304,"blocks":["d786b2dbb92743dfdc33bec9a12ce215b911aaef59f8d88d6bb282d4bd593b02"]},"offset":"216691"},"transform.js":{"size":372,"integrity":{"algorithm":"SHA256","hash":"d41edd15ea18c66efc749f05848357afecfa36b42f65167827f7e795578784d8","blockSize":4194304,"blocks":["d41edd15ea18c66efc749f05848357afecfa36b42f65167827f7e795578784d8"]},"offset":"218211"}}}}},"index.js":{"size":513,"integrity":{"algorithm":"SHA256","hash":"9554d4b13d8c2a36378d4853a8e1b28563f03fa3f610a692e755df04d64ba53f","blockSize":4194304,"blocks":["9554d4b13d8c2a36378d4853a8e1b28563f03fa3f610a692e755df04d64ba53f"]},"offset":"218583"},"main":{"files":{"ElectronExternalApi.js":{"size":4692,"integrity":{"algorithm":"SHA256","hash":"1b06b5416e5c874ed8fc6325794599a8bfa6bd524d3a2e266dea4e50faaaa1a7","blockSize":4194304,"blocks":["1b06b5416e5c874ed8fc6325794599a8bfa6bd524d3a2e266dea4e50faaaa1a7"]},"offset":"219096"},"index.js":{"size":1204,"integrity":{"algorithm":"SHA256","hash":"9232a0dd58735cf11489fb21b35506619faf723b7cb3a1bf699ee0965a929325","blockSize":4194304,"blocks":["9232a0dd58735cf11489fb21b35506619faf723b7cb3a1bf699ee0965a929325"]},"offset":"223788"},"initialize.js":{"size":2459,"integrity":{"algorithm":"SHA256","hash":"7d5e6c1d18bd56ef030f12008fdd688c2dc5f40949b9d6fa997caa739a6ed4bf","blockSize":4194304,"blocks":["7d5e6c1d18bd56ef030f12008fdd688c2dc5f40949b9d6fa997caa739a6ed4bf"]},"offset":"224992"}}},"node":{"files":{"ErrorHandler.js":{"size":3311,"integrity":{"algorithm":"SHA256","hash":"42052a03eda2f33163ea5f46d4d78dac799e801539ae474ab1b730a507a1b7ee","blockSize":4194304,"blocks":["42052a03eda2f33163ea5f46d4d78dac799e801539ae474ab1b730a507a1b7ee"]},"offset":"227451"},"EventLogger.js":{"size":5836,"integrity":{"algorithm":"SHA256","hash":"9f82f44f0dbc60c9ac2276699f1d6fda1a46c605dd28a8e8c32f2af186919e97","blockSize":4194304,"blocks":["9f82f44f0dbc60c9ac2276699f1d6fda1a46c605dd28a8e8c32f2af186919e97"]},"offset":"230762"},"NodeExternalApi.js":{"size":4951,"integrity":{"algorithm":"SHA256","hash":"9eb39da5689391cc7fc8a7779967db3186beab3bf241c1611774caf0c486089a","blockSize":4194304,"blocks":["9eb39da5689391cc7fc8a7779967db3186beab3bf241c1611774caf0c486089a"]},"offset":"236598"},"createDefaultLogger.js":{"size":1205,"integrity":{"algorithm":"SHA256","hash":"832b6e548db30fcf367b7ee5afff2dd7325a377af5ea9f00404cdc083ea54d96","blockSize":4194304,"blocks":["832b6e548db30fcf367b7ee5afff2dd7325a377af5ea9f00404cdc083ea54d96"]},"offset":"241549"},"index.js":{"size":290,"integrity":{"algorithm":"SHA256","hash":"a950d587bb76139ddfbcfa9d80f869e00e6d0299664758631d6977198cc5b2a6","blockSize":4194304,"blocks":["a950d587bb76139ddfbcfa9d80f869e00e6d0299664758631d6977198cc5b2a6"]},"offset":"242754"},"packageJson.js":{"size":2349,"integrity":{"algorithm":"SHA256","hash":"0c2a87c76002dedd9778d04a2e360d10009fc8561dc2d649e41f9196ffa8668e","blockSize":4194304,"blocks":["0c2a87c76002dedd9778d04a2e360d10009fc8561dc2d649e41f9196ffa8668e"]},"offset":"243044"},"transforms":{"files":{"object.js":{"size":2906,"integrity":{"algorithm":"SHA256","hash":"990e63a431feef1addad96aa8525fa4d0e797583244a04f527776869a0be6d4d","blockSize":4194304,"blocks":["990e63a431feef1addad96aa8525fa4d0e797583244a04f527776869a0be6d4d"]},"offset":"245393"}}},"transports":{"files":{"console.js":{"size":2517,"integrity":{"algorithm":"SHA256","hash":"1225cc6aa07c73f442c75b96c6df2990ac2b7a550d5430910056b114e1608272","blockSize":4194304,"blocks":["1225cc6aa07c73f442c75b96c6df2990ac2b7a550d5430910056b114e1608272"]},"offset":"248299"},"file":{"files":{"File.js":{"size":3299,"integrity":{"algorithm":"SHA256","hash":"c993861cbe264159b7d77cf6489ea875e1b248f4cdf95bb8a338fcb63b0b48a4","blockSize":4194304,"blocks":["c993861cbe264159b7d77cf6489ea875e1b248f4cdf95bb8a338fcb63b0b48a4"]},"offset":"250816"},"FileRegistry.js":{"size":1789,"integrity":{"algorithm":"SHA256","hash":"e3b6ab7aeb35b08072b3be580dcfb1c0ebbb8e892f2d412f2f22279e129f74a9","blockSize":4194304,"blocks":["e3b6ab7aeb35b08072b3be580dcfb1c0ebbb8e892f2d412f2f22279e129f74a9"]},"offset":"254115"},"NullFile.js":{"size":232,"integrity":{"algorithm":"SHA256","hash":"f59571c2745779b7ab0c1fb54f2e219964444adac1d1d03de8fbc9e633d78a32","blockSize":4194304,"blocks":["f59571c2745779b7ab0c1fb54f2e219964444adac1d1d03de8fbc9e633d78a32"]},"offset":"255904"},"index.js":{"size":4417,"integrity":{"algorithm":"SHA256","hash":"678db06d5434325ee12f208d6c4de5db12c7a99205812800af664d3993e9c1ec","blockSize":4194304,"blocks":["678db06d5434325ee12f208d6c4de5db12c7a99205812800af664d3993e9c1ec"]},"offset":"256136"}}},"ipc.js":{"size":808,"integrity":{"algorithm":"SHA256","hash":"e9c86603ad45226c86cfb77fd631b93c47df3f76c06312d684c23ac0931e447e","blockSize":4194304,"blocks":["e9c86603ad45226c86cfb77fd631b93c47df3f76c06312d684c23ac0931e447e"]},"offset":"260553"},"remote.js":{"size":2114,"integrity":{"algorithm":"SHA256","hash":"4d3d566a5cf821a80da7fc5a19748bd47128148f0a44709beb3164e3f95af705","blockSize":4194304,"blocks":["4d3d566a5cf821a80da7fc5a19748bd47128148f0a44709beb3164e3f95af705"]},"offset":"261361"}}}}},"renderer":{"files":{"electron-log-preload.js":{"size":2054,"integrity":{"algorithm":"SHA256","hash":"6e488d9b11ea738f05f51c2a22cc68c8add00ba5126f797f9192cc92ae899d13","blockSize":4194304,"blocks":["6e488d9b11ea738f05f51c2a22cc68c8add00ba5126f797f9192cc92ae899d13"]},"offset":"263475"},"index.js":{"size":2027,"integrity":{"algorithm":"SHA256","hash":"7207aa5cde3a7d0980dec28405364cb659eec0dc7c78e5e3f06df970b44cd3de","blockSize":4194304,"blocks":["7207aa5cde3a7d0980dec28405364cb659eec0dc7c78e5e3f06df970b44cd3de"]},"offset":"265529"},"lib":{"files":{"RendererErrorHandler.js":{"size":1998,"integrity":{"algorithm":"SHA256","hash":"5656699c9b819e572e3631f833e6b612e64648fefc43d2d7bc388932c58fa247","blockSize":4194304,"blocks":["5656699c9b819e572e3631f833e6b612e64648fefc43d2d7bc388932c58fa247"]},"offset":"267556"},"transports":{"files":{"console.js":{"size":2569,"integrity":{"algorithm":"SHA256","hash":"c6ced3b63c96dfd820fb942fc44cd6c223ed884d198618331ac03d7d2414f25d","blockSize":4194304,"blocks":["c6ced3b63c96dfd820fb942fc44cd6c223ed884d198618331ac03d7d2414f25d"]},"offset":"269554"},"ipc.js":{"size":2701,"integrity":{"algorithm":"SHA256","hash":"c9f48611211d81edfb9f18910626637f53bf42e666031c1342449cfc1f01ebe9","blockSize":4194304,"blocks":["c9f48611211d81edfb9f18910626637f53bf42e666031c1342449cfc1f01ebe9"]},"offset":"272123"}}}}}}}}}}},"electron-updater":{"files":{"LICENSE":{"size":1084,"integrity":{"algorithm":"SHA256","hash":"bed8d0ab3e6031817f775a641ff37313b0f5591bc8ba0ed79b978dafbd4231ce","blockSize":4194304,"blocks":["bed8d0ab3e6031817f775a641ff37313b0f5591bc8ba0ed79b978dafbd4231ce"]},"offset":"274824"},"out":{"files":{"AppAdapter.js":{"size":740,"integrity":{"algorithm":"SHA256","hash":"2fd4359fe091d7a42e2e2df8327e03aa52e202cbf593b11d9bc891cefd09caa8","blockSize":4194304,"blocks":["2fd4359fe091d7a42e2e2df8327e03aa52e202cbf593b11d9bc891cefd09caa8"]},"offset":"275908"},"AppAdapter.js.map":{"size":1814,"integrity":{"algorithm":"SHA256","hash":"8e3dbb32bcedad41e5b863d6a21eb2f858d84a82185b5006ac259b3a688c5529","blockSize":4194304,"blocks":["8e3dbb32bcedad41e5b863d6a21eb2f858d84a82185b5006ac259b3a688c5529"]},"offset":"276648"},"AppImageUpdater.js":{"size":5402,"integrity":{"algorithm":"SHA256","hash":"fa617d642f91407073b26a54a30a7dfc019845da458006841581dd725802344d","blockSize":4194304,"blocks":["fa617d642f91407073b26a54a30a7dfc019845da458006841581dd725802344d"]},"offset":"278462"},"AppImageUpdater.js.map":{"size":8831,"integrity":{"algorithm":"SHA256","hash":"ac62de127f9e40e28cf9bb7d3517377056df73884781b7a00cd201419c46621b","blockSize":4194304,"blocks":["ac62de127f9e40e28cf9bb7d3517377056df73884781b7a00cd201419c46621b"]},"offset":"283864"},"AppUpdater.js":{"size":29849,"integrity":{"algorithm":"SHA256","hash":"f33534f53e10b00b823bf6e044614fc4d6cf1c6c54d748215362a567b2f35d55","blockSize":4194304,"blocks":["f33534f53e10b00b823bf6e044614fc4d6cf1c6c54d748215362a567b2f35d55"]},"offset":"292695"},"AppUpdater.js.map":{"size":52226,"integrity":{"algorithm":"SHA256","hash":"7e71638e315dd0bd35b3c235a9eaedf3124152129b3ae6b98510ba92688efd65","blockSize":4194304,"blocks":["7e71638e315dd0bd35b3c235a9eaedf3124152129b3ae6b98510ba92688efd65"]},"offset":"322544"},"BaseUpdater.js":{"size":6118,"integrity":{"algorithm":"SHA256","hash":"6e0b8e6dd0a5380391758ebdf8b37991de236865359694a312600e2938be64cb","blockSize":4194304,"blocks":["6e0b8e6dd0a5380391758ebdf8b37991de236865359694a312600e2938be64cb"]},"offset":"374770"},"BaseUpdater.js.map":{"size":10883,"integrity":{"algorithm":"SHA256","hash":"8b7ea5834d5c20a6f2786166118482fd644c4e05031b4adff29d9db4212cc907","blockSize":4194304,"blocks":["8b7ea5834d5c20a6f2786166118482fd644c4e05031b4adff29d9db4212cc907"]},"offset":"380888"},"DebUpdater.js":{"size":2150,"integrity":{"algorithm":"SHA256","hash":"946aa65f85765c1eb6ee37c097da44e8a68f7780ab6d0d7305e8a8306aa2d7d4","blockSize":4194304,"blocks":["946aa65f85765c1eb6ee37c097da44e8a68f7780ab6d0d7305e8a8306aa2d7d4"]},"offset":"391771"},"DebUpdater.js.map":{"size":3862,"integrity":{"algorithm":"SHA256","hash":"fea9a0754cd700aad640cbca0ce03af236b7f475cb48fcd44eba7fe82e8f27ec","blockSize":4194304,"blocks":["fea9a0754cd700aad640cbca0ce03af236b7f475cb48fcd44eba7fe82e8f27ec"]},"offset":"393921"},"DownloadedUpdateHelper.js":{"size":6907,"integrity":{"algorithm":"SHA256","hash":"81d816fdfddf4711218f78c7625e22122b2159ec7c83209613dfb9e71a552e4d","blockSize":4194304,"blocks":["81d816fdfddf4711218f78c7625e22122b2159ec7c83209613dfb9e71a552e4d"]},"offset":"397783"},"DownloadedUpdateHelper.js.map":{"size":12251,"integrity":{"algorithm":"SHA256","hash":"cef2750982fd63ef843c4a274938682a1f8e2abd1eac794f1b612fdb496b1d00","blockSize":4194304,"blocks":["cef2750982fd63ef843c4a274938682a1f8e2abd1eac794f1b612fdb496b1d00"]},"offset":"404690"},"ElectronAppAdapter.js":{"size":1180,"integrity":{"algorithm":"SHA256","hash":"fa8fbf1de1c69924942aa3926878d391fba95007095836abe5f5b878506d4931","blockSize":4194304,"blocks":["fa8fbf1de1c69924942aa3926878d391fba95007095836abe5f5b878506d4931"]},"offset":"416941"},"ElectronAppAdapter.js.map":{"size":2289,"integrity":{"algorithm":"SHA256","hash":"f5b740ccc773315579ac1cc893db314f1bf589d4c499073755c625e8cdfa99a0","blockSize":4194304,"blocks":["f5b740ccc773315579ac1cc893db314f1bf589d4c499073755c625e8cdfa99a0"]},"offset":"418121"},"MacUpdater.js":{"size":12563,"integrity":{"algorithm":"SHA256","hash":"47a521a1698333b83d4308b38c4a7bacda5f2ca6b5a3627b45bed3f4ee2549c6","blockSize":4194304,"blocks":["47a521a1698333b83d4308b38c4a7bacda5f2ca6b5a3627b45bed3f4ee2549c6"]},"offset":"420410"},"MacUpdater.js.map":{"size":20681,"integrity":{"algorithm":"SHA256","hash":"ab43aea96ac27f9ad62b2389d2a8dd00efaaf4cd50dad0f97143a88fb864fa44","blockSize":4194304,"blocks":["ab43aea96ac27f9ad62b2389d2a8dd00efaaf4cd50dad0f97143a88fb864fa44"]},"offset":"432973"},"NsisUpdater.js":{"size":9414,"integrity":{"algorithm":"SHA256","hash":"aafa536ffd84880f8d32bef8dfecf3f592fed0b969e743397ad8c064b04922a5","blockSize":4194304,"blocks":["aafa536ffd84880f8d32bef8dfecf3f592fed0b969e743397ad8c064b04922a5"]},"offset":"453654"},"NsisUpdater.js.map":{"size":15022,"integrity":{"algorithm":"SHA256","hash":"003ba3291c267b0446229b5c4be2bff521468f10b091637d7ea0fd76f814a0d3","blockSize":4194304,"blocks":["003ba3291c267b0446229b5c4be2bff521468f10b091637d7ea0fd76f814a0d3"]},"offset":"463068"},"PacmanUpdater.js":{"size":2145,"integrity":{"algorithm":"SHA256","hash":"ead882f52c070621baf66ca6f1fff9e32a582107d195fa88e2ff91690e6881e7","blockSize":4194304,"blocks":["ead882f52c070621baf66ca6f1fff9e32a582107d195fa88e2ff91690e6881e7"]},"offset":"478090"},"PacmanUpdater.js.map":{"size":3803,"integrity":{"algorithm":"SHA256","hash":"e20f9645cb4aa45630bca74e7e46cbc622be3d19b2677b4c65fcc1b2f644d58a","blockSize":4194304,"blocks":["e20f9645cb4aa45630bca74e7e46cbc622be3d19b2677b4c65fcc1b2f644d58a"]},"offset":"480235"},"RpmUpdater.js":{"size":2470,"integrity":{"algorithm":"SHA256","hash":"7f9090b138acd70f5952b1426727a020673716d75e51687a0c8ee7ff4d27671a","blockSize":4194304,"blocks":["7f9090b138acd70f5952b1426727a020673716d75e51687a0c8ee7ff4d27671a"]},"offset":"484038"},"RpmUpdater.js.map":{"size":4406,"integrity":{"algorithm":"SHA256","hash":"cc780941edcf41757d417c87495cf4365a28f8e020d074103c8100e1d0332213","blockSize":4194304,"blocks":["cc780941edcf41757d417c87495cf4365a28f8e020d074103c8100e1d0332213"]},"offset":"486508"},"differentialDownloader":{"files":{"DataSplitter.js":{"size":7981,"integrity":{"algorithm":"SHA256","hash":"1e9719ec807a6e65e9501238e0569ff2c57b0b8eb3653752591a08cfbd0350e3","blockSize":4194304,"blocks":["1e9719ec807a6e65e9501238e0569ff2c57b0b8eb3653752591a08cfbd0350e3"]},"offset":"490914"},"DataSplitter.js.map":{"size":14197,"integrity":{"algorithm":"SHA256","hash":"0817663359a5a6daa235684203aefd5c915b0f3c46e32ab88f71616df6e70695","blockSize":4194304,"blocks":["0817663359a5a6daa235684203aefd5c915b0f3c46e32ab88f71616df6e70695"]},"offset":"498895"},"DifferentialDownloader.js":{"size":12607,"integrity":{"algorithm":"SHA256","hash":"4b0c55133763861163fac484a07d3091b6f917460338b4f21e398a5cd8012109","blockSize":4194304,"blocks":["4b0c55133763861163fac484a07d3091b6f917460338b4f21e398a5cd8012109"]},"offset":"513092"},"DifferentialDownloader.js.map":{"size":21465,"integrity":{"algorithm":"SHA256","hash":"ad64b36901677b514770bef76e30afb45ae0beada57d2b364ef06cdde2191a93","blockSize":4194304,"blocks":["ad64b36901677b514770bef76e30afb45ae0beada57d2b364ef06cdde2191a93"]},"offset":"525699"},"FileWithEmbeddedBlockMapDifferentialDownloader.js":{"size":1861,"integrity":{"algorithm":"SHA256","hash":"8f3c12c0d7e6e0284b9c9af068a0c6caa56f691997c763bb5850b8fa98c19650","blockSize":4194304,"blocks":["8f3c12c0d7e6e0284b9c9af068a0c6caa56f691997c763bb5850b8fa98c19650"]},"offset":"547164"},"FileWithEmbeddedBlockMapDifferentialDownloader.js.map":{"size":3213,"integrity":{"algorithm":"SHA256","hash":"f21cdffe96e592998d830c9cf3d62cb1c209cc5aa0697dbff1e5e7b3dc7156f4","blockSize":4194304,"blocks":["f21cdffe96e592998d830c9cf3d62cb1c209cc5aa0697dbff1e5e7b3dc7156f4"]},"offset":"549025"},"GenericDifferentialDownloader.js":{"size":524,"integrity":{"algorithm":"SHA256","hash":"62ca9a1d3ca12deca41ad902a24d8fec34ec150cdc194478d5b4fc987a66921b","blockSize":4194304,"blocks":["62ca9a1d3ca12deca41ad902a24d8fec34ec150cdc194478d5b4fc987a66921b"]},"offset":"552238"},"GenericDifferentialDownloader.js.map":{"size":709,"integrity":{"algorithm":"SHA256","hash":"37a09dab5af73258527d65396a02363f10df71c1d4c60555b4492ee5c847aada","blockSize":4194304,"blocks":["37a09dab5af73258527d65396a02363f10df71c1d4c60555b4492ee5c847aada"]},"offset":"552762"},"ProgressDifferentialDownloadCallbackTransform.js":{"size":3824,"integrity":{"algorithm":"SHA256","hash":"d4b62c2f8eec10bb8edcc0227cde609734ef344bd3e727a48cdb806ea3608ef4","blockSize":4194304,"blocks":["d4b62c2f8eec10bb8edcc0227cde609734ef344bd3e727a48cdb806ea3608ef4"]},"offset":"553471"},"ProgressDifferentialDownloadCallbackTransform.js.map":{"size":6590,"integrity":{"algorithm":"SHA256","hash":"c7d2540b01b43b9a8ffde20eecd5a20d0343265d95ce3dc8cb0a32ecfcb6b304","blockSize":4194304,"blocks":["c7d2540b01b43b9a8ffde20eecd5a20d0343265d95ce3dc8cb0a32ecfcb6b304"]},"offset":"557295"},"downloadPlanBuilder.js":{"size":5517,"integrity":{"algorithm":"SHA256","hash":"4ee0506c1431e86c6e693a5d118c2909f7638cc27000e3c7569cd43da08bfbf4","blockSize":4194304,"blocks":["4ee0506c1431e86c6e693a5d118c2909f7638cc27000e3c7569cd43da08bfbf4"]},"offset":"563885"},"downloadPlanBuilder.js.map":{"size":10248,"integrity":{"algorithm":"SHA256","hash":"f05e73a087686a5d06a1a2ce77f539ee1250653fd192949e3dd466b328fc4898","blockSize":4194304,"blocks":["f05e73a087686a5d06a1a2ce77f539ee1250653fd192949e3dd466b328fc4898"]},"offset":"569402"},"multipleRangeDownloader.js":{"size":4872,"integrity":{"algorithm":"SHA256","hash":"34232a0454e945eac3f749628e16a5fbed8d9001bec71c3967defba09fb89c9f","blockSize":4194304,"blocks":["34232a0454e945eac3f749628e16a5fbed8d9001bec71c3967defba09fb89c9f"]},"offset":"579650"},"multipleRangeDownloader.js.map":{"size":8881,"integrity":{"algorithm":"SHA256","hash":"54471e9a9a0c968396fbd16199b86dd9b638bc6eb0b5976f36b4a4de6ff812e2","blockSize":4194304,"blocks":["54471e9a9a0c968396fbd16199b86dd9b638bc6eb0b5976f36b4a4de6ff812e2"]},"offset":"584522"}}},"electronHttpExecutor.js":{"size":3258,"integrity":{"algorithm":"SHA256","hash":"907bc7f2c71c1f964fe83f71337a520073e753f3f35ea00076f5676aebaa6404","blockSize":4194304,"blocks":["907bc7f2c71c1f964fe83f71337a520073e753f3f35ea00076f5676aebaa6404"]},"offset":"593403"},"electronHttpExecutor.js.map":{"size":5547,"integrity":{"algorithm":"SHA256","hash":"3e6eafc704edaa106700ef5ce03e621a33c86a974e5499d3a3551a18e4851e8a","blockSize":4194304,"blocks":["3e6eafc704edaa106700ef5ce03e621a33c86a974e5499d3a3551a18e4851e8a"]},"offset":"596661"},"main.js":{"size":4643,"integrity":{"algorithm":"SHA256","hash":"577a4ec8ec6e1f62771c1ef5dacb09d507b3fc4cb1ccf44b02183bada0bdc7e9","blockSize":4194304,"blocks":["577a4ec8ec6e1f62771c1ef5dacb09d507b3fc4cb1ccf44b02183bada0bdc7e9"]},"offset":"602208"},"main.js.map":{"size":4664,"integrity":{"algorithm":"SHA256","hash":"5827cab243bd07f6b9f00336022d701f06beb0702f0b04c87deee3ba80da8bb1","blockSize":4194304,"blocks":["5827cab243bd07f6b9f00336022d701f06beb0702f0b04c87deee3ba80da8bb1"]},"offset":"606851"},"providerFactory.js":{"size":3189,"integrity":{"algorithm":"SHA256","hash":"2cd4d58d4afe521e10968e645107174e1c1c4b30b2135aac6c3aaffef4ecf6cb","blockSize":4194304,"blocks":["2cd4d58d4afe521e10968e645107174e1c1c4b30b2135aac6c3aaffef4ecf6cb"]},"offset":"611515"},"providerFactory.js.map":{"size":5173,"integrity":{"algorithm":"SHA256","hash":"4f5d44d7a18af8cd813c488b853384ce413919a71de19c3a253d26717d6b6218","blockSize":4194304,"blocks":["4f5d44d7a18af8cd813c488b853384ce413919a71de19c3a253d26717d6b6218"]},"offset":"614704"},"providers":{"files":{"BitbucketProvider.js":{"size":1969,"integrity":{"algorithm":"SHA256","hash":"d918e2d9a98797a36dfa777b380689282187dadf9c881e94b7e2073c8d325416","blockSize":4194304,"blocks":["d918e2d9a98797a36dfa777b380689282187dadf9c881e94b7e2073c8d325416"]},"offset":"619877"},"BitbucketProvider.js.map":{"size":3454,"integrity":{"algorithm":"SHA256","hash":"bf4e8f4f4efbf1c89aa4cb4979d10e4b329cffee9726a12795bb1c5cf324703a","blockSize":4194304,"blocks":["bf4e8f4f4efbf1c89aa4cb4979d10e4b329cffee9726a12795bb1c5cf324703a"]},"offset":"621846"},"GenericProvider.js":{"size":2252,"integrity":{"algorithm":"SHA256","hash":"c0d1f1aed62d7418e4d292118b3e079f9680914c554fe7604786b73771297d8a","blockSize":4194304,"blocks":["c0d1f1aed62d7418e4d292118b3e079f9680914c554fe7604786b73771297d8a"]},"offset":"625300"},"GenericProvider.js.map":{"size":3777,"integrity":{"algorithm":"SHA256","hash":"32687ae2a040a8a153135d9aced2afbffe42d1ad337ce8ca53f2e899a6900640","blockSize":4194304,"blocks":["32687ae2a040a8a153135d9aced2afbffe42d1ad337ce8ca53f2e899a6900640"]},"offset":"627552"},"GitHubProvider.js":{"size":9893,"integrity":{"algorithm":"SHA256","hash":"5a4f4eda45a8e3a10f304b413739e3ad774eb4bc7a01cc0cc5f792d0928ba267","blockSize":4194304,"blocks":["5a4f4eda45a8e3a10f304b413739e3ad774eb4bc7a01cc0cc5f792d0928ba267"]},"offset":"631329"},"GitHubProvider.js.map":{"size":16996,"integrity":{"algorithm":"SHA256","hash":"cbd02d3d648eb3067cddca24de4622ab2ef85ed7951128674be2201e940930b5","blockSize":4194304,"blocks":["cbd02d3d648eb3067cddca24de4622ab2ef85ed7951128674be2201e940930b5"]},"offset":"641222"},"KeygenProvider.js":{"size":2205,"integrity":{"algorithm":"SHA256","hash":"361cd9b7c29c6db9b94ac74947a6d4c7b48ac01a74c6b7950d9ff256ec783568","blockSize":4194304,"blocks":["361cd9b7c29c6db9b94ac74947a6d4c7b48ac01a74c6b7950d9ff256ec783568"]},"offset":"658218"},"KeygenProvider.js.map":{"size":3892,"integrity":{"algorithm":"SHA256","hash":"a5082b0cd3893d9e77fbbb62cdc8a2ffa3f701c9f65c3b7ab1279eea662b3bb5","blockSize":4194304,"blocks":["a5082b0cd3893d9e77fbbb62cdc8a2ffa3f701c9f65c3b7ab1279eea662b3bb5"]},"offset":"660423"},"PrivateGitHubProvider.js":{"size":4152,"integrity":{"algorithm":"SHA256","hash":"aadfd7068b4cef45e051c3068b107deba330a48d6b7a640f8a319ae56703bfad","blockSize":4194304,"blocks":["aadfd7068b4cef45e051c3068b107deba330a48d6b7a640f8a319ae56703bfad"]},"offset":"664315"},"PrivateGitHubProvider.js.map":{"size":7789,"integrity":{"algorithm":"SHA256","hash":"5e34535e67fb3177740fcc6b848e4929752b752021b10dfd14e9139e33dc7ff6","blockSize":4194304,"blocks":["5e34535e67fb3177740fcc6b848e4929752b752021b10dfd14e9139e33dc7ff6"]},"offset":"668467"},"Provider.js":{"size":5043,"integrity":{"algorithm":"SHA256","hash":"618bfd8924a488594083e6f6874d373f01a234ca0837e1aabb7710ae1944eee4","blockSize":4194304,"blocks":["618bfd8924a488594083e6f6874d373f01a234ca0837e1aabb7710ae1944eee4"]},"offset":"676256"},"Provider.js.map":{"size":10016,"integrity":{"algorithm":"SHA256","hash":"3b206ce108475ebaea3e6b46855c221d9bfdddab4a5b9c8bcf1ad3cd50df4aa5","blockSize":4194304,"blocks":["3b206ce108475ebaea3e6b46855c221d9bfdddab4a5b9c8bcf1ad3cd50df4aa5"]},"offset":"681299"}}},"types.js":{"size":1551,"integrity":{"algorithm":"SHA256","hash":"b92b36b9fd6ad4790a05d8ef0c1e65b875923ff098e5371a59076b20b17f2e3b","blockSize":4194304,"blocks":["b92b36b9fd6ad4790a05d8ef0c1e65b875923ff098e5371a59076b20b17f2e3b"]},"offset":"691315"},"types.js.map":{"size":3619,"integrity":{"algorithm":"SHA256","hash":"3f31519e9ef41568d2308ccb5a2a7c08e54bffcd43c7547610727235babd2b3e","blockSize":4194304,"blocks":["3f31519e9ef41568d2308ccb5a2a7c08e54bffcd43c7547610727235babd2b3e"]},"offset":"692866"},"util.js":{"size":1720,"integrity":{"algorithm":"SHA256","hash":"911c1ccd4a663d95ee44ea18e11e89b72c8c5255d31dbcc95c7af8b95e48482a","blockSize":4194304,"blocks":["911c1ccd4a663d95ee44ea18e11e89b72c8c5255d31dbcc95c7af8b95e48482a"]},"offset":"696485"},"util.js.map":{"size":2847,"integrity":{"algorithm":"SHA256","hash":"ab32b0289461ad969ae6a6620d853aedae969d9e88fa116363ff4ba069ffac85","blockSize":4194304,"blocks":["ab32b0289461ad969ae6a6620d853aedae969d9e88fa116363ff4ba069ffac85"]},"offset":"698205"},"windowsExecutableCodeSignatureVerifier.js":{"size":7435,"integrity":{"algorithm":"SHA256","hash":"5a488a2cb485d91ba6db7c5c832f133fe006dbd8e347169a02120114d643e222","blockSize":4194304,"blocks":["5a488a2cb485d91ba6db7c5c832f133fe006dbd8e347169a02120114d643e222"]},"offset":"701052"},"windowsExecutableCodeSignatureVerifier.js.map":{"size":11200,"integrity":{"algorithm":"SHA256","hash":"84250ef52a2cf6c833b558edda04a9fec0f02d75a5bbf8c1c5f71d7babe684a9","blockSize":4194304,"blocks":["84250ef52a2cf6c833b558edda04a9fec0f02d75a5bbf8c1c5f71d7babe684a9"]},"offset":"708487"}}},"package.json":{"size":1040,"integrity":{"algorithm":"SHA256","hash":"6f6633a142dbb92cea4099650112ac3d162dc841e6fd55c0cab2020bb5f51230","blockSize":4194304,"blocks":["6f6633a142dbb92cea4099650112ac3d162dc841e6fd55c0cab2020bb5f51230"]},"offset":"719687"},"node_modules":{"files":{"builder-util-runtime":{"files":{"LICENSE":{"size":1084,"integrity":{"algorithm":"SHA256","hash":"bed8d0ab3e6031817f775a641ff37313b0f5591bc8ba0ed79b978dafbd4231ce","blockSize":4194304,"blocks":["bed8d0ab3e6031817f775a641ff37313b0f5591bc8ba0ed79b978dafbd4231ce"]},"offset":"720727"},"out":{"files":{"CancellationToken.js":{"size":3199,"integrity":{"algorithm":"SHA256","hash":"054512fdee2fe810ef46d5ce7fdc2c39d3582ee8c3d463a4ee6c954bca8ec7d5","blockSize":4194304,"blocks":["054512fdee2fe810ef46d5ce7fdc2c39d3582ee8c3d463a4ee6c954bca8ec7d5"]},"offset":"721811"},"CancellationToken.js.map":{"size":5648,"integrity":{"algorithm":"SHA256","hash":"9fdf32eccac29b57c7703a23cd1201ca6a04c1b81b349900177ec1b948317c89","blockSize":4194304,"blocks":["9fdf32eccac29b57c7703a23cd1201ca6a04c1b81b349900177ec1b948317c89"]},"offset":"725010"},"MemoLazy.js":{"size":1504,"integrity":{"algorithm":"SHA256","hash":"f92e496315210399d4f58381b25ab4ca17f42991b4a50a0353c7e0acd92836a3","blockSize":4194304,"blocks":["f92e496315210399d4f58381b25ab4ca17f42991b4a50a0353c7e0acd92836a3"]},"offset":"730658"},"MemoLazy.js.map":{"size":2756,"integrity":{"algorithm":"SHA256","hash":"1603666315d0de55b5553b7223abfba2fdc113fc765f61c5e74d60ed4c3c7a9b","blockSize":4194304,"blocks":["1603666315d0de55b5553b7223abfba2fdc113fc765f61c5e74d60ed4c3c7a9b"]},"offset":"732162"},"ProgressCallbackTransform.js":{"size":1949,"integrity":{"algorithm":"SHA256","hash":"35503895f7e7dd4329b94dd69eb48674ac55d9d6646d0ea42eada5378d433d32","blockSize":4194304,"blocks":["35503895f7e7dd4329b94dd69eb48674ac55d9d6646d0ea42eada5378d433d32"]},"offset":"734918"},"ProgressCallbackTransform.js.map":{"size":3693,"integrity":{"algorithm":"SHA256","hash":"7e42abdec49293ecbd388e36213ccf743a0b12a018af5045dd23cd0ed495c7ff","blockSize":4194304,"blocks":["7e42abdec49293ecbd388e36213ccf743a0b12a018af5045dd23cd0ed495c7ff"]},"offset":"736867"},"blockMapApi.js":{"size":116,"integrity":{"algorithm":"SHA256","hash":"84e270ead20b81c2c527c7cea8c295819fd015c120f67fd686c29534e036c239","blockSize":4194304,"blocks":["84e270ead20b81c2c527c7cea8c295819fd015c120f67fd686c29534e036c239"]},"offset":"740560"},"blockMapApi.js.map":{"size":403,"integrity":{"algorithm":"SHA256","hash":"cbc5bfdd044fd2f70dd6edaf55449890497bdf67a05686e847da71ac96b94a33","blockSize":4194304,"blocks":["cbc5bfdd044fd2f70dd6edaf55449890497bdf67a05686e847da71ac96b94a33"]},"offset":"740676"},"error.js":{"size":255,"integrity":{"algorithm":"SHA256","hash":"820464dee13ae1ca3c40d6a0f35bd49cabb154af63f872e9ed3488a0b95cca49","blockSize":4194304,"blocks":["820464dee13ae1ca3c40d6a0f35bd49cabb154af63f872e9ed3488a0b95cca49"]},"offset":"741079"},"error.js.map":{"size":454,"integrity":{"algorithm":"SHA256","hash":"64580cca1bb760bd55809c02ee1b3789dd6bd3499bee30e82ed8986e3413ef95","blockSize":4194304,"blocks":["64580cca1bb760bd55809c02ee1b3789dd6bd3499bee30e82ed8986e3413ef95"]},"offset":"741334"},"httpExecutor.js":{"size":17426,"integrity":{"algorithm":"SHA256","hash":"78002d2339af1426a86945374c4ab9e6430cb107a4dc9b4a87e7ae017b37ecae","blockSize":4194304,"blocks":["78002d2339af1426a86945374c4ab9e6430cb107a4dc9b4a87e7ae017b37ecae"]},"offset":"741788"},"httpExecutor.js.map":{"size":33728,"integrity":{"algorithm":"SHA256","hash":"ceff7e299612d5ecdeb7d521e41f31efc5cba906fbaf3c48b58950f9dbe088a9","blockSize":4194304,"blocks":["ceff7e299612d5ecdeb7d521e41f31efc5cba906fbaf3c48b58950f9dbe088a9"]},"offset":"759214"},"index.js":{"size":4396,"integrity":{"algorithm":"SHA256","hash":"fb99da106ddb31c24972bbf11075ac7142cc7e0183adcd54768da63fd4134934","blockSize":4194304,"blocks":["fb99da106ddb31c24972bbf11075ac7142cc7e0183adcd54768da63fd4134934"]},"offset":"792942"},"index.js.map":{"size":2657,"integrity":{"algorithm":"SHA256","hash":"5afa84d10d80dbb09711ddcc6c419fbaa9708e0caa0a835d0cd0f7384f661837","blockSize":4194304,"blocks":["5afa84d10d80dbb09711ddcc6c419fbaa9708e0caa0a835d0cd0f7384f661837"]},"offset":"797338"},"publishOptions.js":{"size":2213,"integrity":{"algorithm":"SHA256","hash":"b6b7aec32a18090813844b709ef4e1d3d4c96742f1b282145a62ba8487c98ee4","blockSize":4194304,"blocks":["b6b7aec32a18090813844b709ef4e1d3d4c96742f1b282145a62ba8487c98ee4"]},"offset":"799995"},"publishOptions.js.map":{"size":14910,"integrity":{"algorithm":"SHA256","hash":"911ba0652004fdbf73d4406eeb63f53134975a0e431db5d87922634959c39660","blockSize":4194304,"blocks":["911ba0652004fdbf73d4406eeb63f53134975a0e431db5d87922634959c39660"]},"offset":"802208"},"retry.js":{"size":884,"integrity":{"algorithm":"SHA256","hash":"3d9f4919ea75103f62e81fcd96e7047bb615edb58c1c5d1c3892c01c0eccb18c","blockSize":4194304,"blocks":["3d9f4919ea75103f62e81fcd96e7047bb615edb58c1c5d1c3892c01c0eccb18c"]},"offset":"817118"},"retry.js.map":{"size":1468,"integrity":{"algorithm":"SHA256","hash":"ae2a495c96ca32b476f9e856ba0add35bebf6925166d7be2c94f84fc2ff4ebd8","blockSize":4194304,"blocks":["ae2a495c96ca32b476f9e856ba0add35bebf6925166d7be2c94f84fc2ff4ebd8"]},"offset":"818002"},"rfc2253Parser.js":{"size":2264,"integrity":{"algorithm":"SHA256","hash":"a8a6966c3bc3e6cc0df40128aa591747859257563f46f56b83d76148f8e170c4","blockSize":4194304,"blocks":["a8a6966c3bc3e6cc0df40128aa591747859257563f46f56b83d76148f8e170c4"]},"offset":"819470"},"rfc2253Parser.js.map":{"size":4168,"integrity":{"algorithm":"SHA256","hash":"8bcf678951773404906d4b9ceb1e6afead0c6db8a15c73b6f273f1f135b176b6","blockSize":4194304,"blocks":["8bcf678951773404906d4b9ceb1e6afead0c6db8a15c73b6f273f1f135b176b6"]},"offset":"821734"},"updateInfo.js":{"size":115,"integrity":{"algorithm":"SHA256","hash":"935693e55dcf8a1e0ad653bbee7d456594835fdee0b99c9f7559befe1387043a","blockSize":4194304,"blocks":["935693e55dcf8a1e0ad653bbee7d456594835fdee0b99c9f7559befe1387043a"]},"offset":"825902"},"updateInfo.js.map":{"size":2316,"integrity":{"algorithm":"SHA256","hash":"120aabe1a0e0af390b242d63084b4dcdafba31c8c4d1888780bba5fe49e98f99","blockSize":4194304,"blocks":["120aabe1a0e0af390b242d63084b4dcdafba31c8c4d1888780bba5fe49e98f99"]},"offset":"826017"},"uuid.js":{"size":6393,"integrity":{"algorithm":"SHA256","hash":"5a58134245d8e5ae587e995195d3ca33d9f9e273fc077d700e675f4c4005c029","blockSize":4194304,"blocks":["5a58134245d8e5ae587e995195d3ca33d9f9e273fc077d700e675f4c4005c029"]},"offset":"828333"},"uuid.js.map":{"size":12236,"integrity":{"algorithm":"SHA256","hash":"3f8dc910c8f65bcd60d13787829931ec270933c7009ee667c854a0911e84d338","blockSize":4194304,"blocks":["3f8dc910c8f65bcd60d13787829931ec270933c7009ee667c854a0911e84d338"]},"offset":"834726"},"xml.js":{"size":3549,"integrity":{"algorithm":"SHA256","hash":"8f637be20077f0634bf36cac8a464973a6e1530e51f4efcfaec0f2c64df6ceb0","blockSize":4194304,"blocks":["8f637be20077f0634bf36cac8a464973a6e1530e51f4efcfaec0f2c64df6ceb0"]},"offset":"846962"},"xml.js.map":{"size":6987,"integrity":{"algorithm":"SHA256","hash":"405331ede8c0bfb52033a9829b6ae9ca7f87c36b1c663c220309dad6fc8f0ca1","blockSize":4194304,"blocks":["405331ede8c0bfb52033a9829b6ae9ca7f87c36b1c663c220309dad6fc8f0ca1"]},"offset":"850511"}}},"package.json":{"size":630,"integrity":{"algorithm":"SHA256","hash":"bd4785fbfd1732f4a6405813e47a7a0cd9a824f0e98046c55c188d45310fe8d3","blockSize":4194304,"blocks":["bd4785fbfd1732f4a6405813e47a7a0cd9a824f0e98046c55c188d45310fe8d3"]},"offset":"857498"}}},"fs-extra":{"files":{"LICENSE":{"size":1084,"integrity":{"algorithm":"SHA256","hash":"1e76029602ae9b21cc4e612db2496d92febed882ba13ba745f8b3309e85f9d39","blockSize":4194304,"blocks":["1e76029602ae9b21cc4e612db2496d92febed882ba13ba745f8b3309e85f9d39"]},"offset":"858128"},"lib":{"files":{"copy":{"files":{"copy-sync.js":{"size":5776,"integrity":{"algorithm":"SHA256","hash":"a50856fe7fab3d1d22e8fbf5f32543d46342257cad5e31df8f2a7409fdf19c97","blockSize":4194304,"blocks":["a50856fe7fab3d1d22e8fbf5f32543d46342257cad5e31df8f2a7409fdf19c97"]},"offset":"859212"},"copy.js":{"size":7756,"integrity":{"algorithm":"SHA256","hash":"b1ef00cadd368ea903c9a86927e40636cd832d8fa64344637c96e0e223faf876","blockSize":4194304,"blocks":["b1ef00cadd368ea903c9a86927e40636cd832d8fa64344637c96e0e223faf876"]},"offset":"864988"},"index.js":{"size":147,"integrity":{"algorithm":"SHA256","hash":"f94ad0b8c5f5131a682be2d0427189c260e49fa748fb6f6bcc1f78678354e5d2","blockSize":4194304,"blocks":["f94ad0b8c5f5131a682be2d0427189c260e49fa748fb6f6bcc1f78678354e5d2"]},"offset":"872744"}}},"empty":{"files":{"index.js":{"size":747,"integrity":{"algorithm":"SHA256","hash":"1096edcb5ec0ed015b36914beff0826f6cd5d7ce2645ee9dee60c0b272e57856","blockSize":4194304,"blocks":["1096edcb5ec0ed015b36914beff0826f6cd5d7ce2645ee9dee60c0b272e57856"]},"offset":"872891"}}},"ensure":{"files":{"file.js":{"size":1709,"integrity":{"algorithm":"SHA256","hash":"a104ff42c9aefd0e34556b9df2e4b5c9cd15315b0b0f70b07938901428b3c608","blockSize":4194304,"blocks":["a104ff42c9aefd0e34556b9df2e4b5c9cd15315b0b0f70b07938901428b3c608"]},"offset":"873638"},"index.js":{"size":542,"integrity":{"algorithm":"SHA256","hash":"77ccb9b4d1eab607ce7ba8d3d5bed59b0cb9cc4748d02aa896a2413b71dbfe60","blockSize":4194304,"blocks":["77ccb9b4d1eab607ce7ba8d3d5bed59b0cb9cc4748d02aa896a2413b71dbfe60"]},"offset":"875347"},"link.js":{"size":1652,"integrity":{"algorithm":"SHA256","hash":"339ce737e858367c65f79c0960bc6d1d617638aae07d396ac8ae5c8670b500c3","blockSize":4194304,"blocks":["339ce737e858367c65f79c0960bc6d1d617638aae07d396ac8ae5c8670b500c3"]},"offset":"875889"},"symlink-paths.js":{"size":3374,"integrity":{"algorithm":"SHA256","hash":"5595b764059fb90ce4a13f5cdf43988da97e636521d3c599ce5260681d75bdfc","blockSize":4194304,"blocks":["5595b764059fb90ce4a13f5cdf43988da97e636521d3c599ce5260681d75bdfc"]},"offset":"877541"},"symlink-type.js":{"size":694,"integrity":{"algorithm":"SHA256","hash":"17abe9590176305dd04316b2ac5c972dcf54cea32d279f955fbcf25098743dc8","blockSize":4194304,"blocks":["17abe9590176305dd04316b2ac5c972dcf54cea32d279f955fbcf25098743dc8"]},"offset":"880915"},"symlink.js":{"size":2522,"integrity":{"algorithm":"SHA256","hash":"8b1fa73e5b5554380b710ccfbb4fe23764e53f0e5ce046689741310a82a19e21","blockSize":4194304,"blocks":["8b1fa73e5b5554380b710ccfbb4fe23764e53f0e5ce046689741310a82a19e21"]},"offset":"881609"}}},"fs":{"files":{"index.js":{"size":3373,"integrity":{"algorithm":"SHA256","hash":"620b6e703880fd6718c354c5359a5c37a2379054c037269dbcf7afd2503e4a6f","blockSize":4194304,"blocks":["620b6e703880fd6718c354c5359a5c37a2379054c037269dbcf7afd2503e4a6f"]},"offset":"884131"}}},"index.js":{"size":358,"integrity":{"algorithm":"SHA256","hash":"4967e903b3dc290f2b401b81bfcad8b2d94fd68c1bf4563df63ac082af0e1dae","blockSize":4194304,"blocks":["4967e903b3dc290f2b401b81bfcad8b2d94fd68c1bf4563df63ac082af0e1dae"]},"offset":"887504"},"json":{"files":{"index.js":{"size":508,"integrity":{"algorithm":"SHA256","hash":"c5ac6a8005308e5bb36619fed225c987872300d356fa95d0d56878029ebbdc45","blockSize":4194304,"blocks":["c5ac6a8005308e5bb36619fed225c987872300d356fa95d0d56878029ebbdc45"]},"offset":"887862"},"jsonfile.js":{"size":238,"integrity":{"algorithm":"SHA256","hash":"a986ad3c13166f3bf8f30b18140bfc8ea1754760ab3802aa7c8c3780d54f07ba","blockSize":4194304,"blocks":["a986ad3c13166f3bf8f30b18140bfc8ea1754760ab3802aa7c8c3780d54f07ba"]},"offset":"888370"},"output-json-sync.js":{"size":276,"integrity":{"algorithm":"SHA256","hash":"a68fde22ad1a194755de03e90861805248f883342e05bd685258e76a90e7a6ab","blockSize":4194304,"blocks":["a68fde22ad1a194755de03e90861805248f883342e05bd685258e76a90e7a6ab"]},"offset":"888608"},"output-json.js":{"size":277,"integrity":{"algorithm":"SHA256","hash":"b738aaf8ff9aae265b0512cb2554e1f8ce8605d21dc6230189a9be6980079fc8","blockSize":4194304,"blocks":["b738aaf8ff9aae265b0512cb2554e1f8ce8605d21dc6230189a9be6980079fc8"]},"offset":"888884"}}},"mkdirs":{"files":{"index.js":{"size":328,"integrity":{"algorithm":"SHA256","hash":"adcd576e2e3868b94adb1bad6d1e3cf2312ffdfa71e49a57fe6247e116e75ecf","blockSize":4194304,"blocks":["adcd576e2e3868b94adb1bad6d1e3cf2312ffdfa71e49a57fe6247e116e75ecf"]},"offset":"889161"},"make-dir.js":{"size":545,"integrity":{"algorithm":"SHA256","hash":"23c7ce8a3d6b39d1c7cf5d16ba6447c1690a6fdaa8c5f41e6b76526b7afe96f3","blockSize":4194304,"blocks":["23c7ce8a3d6b39d1c7cf5d16ba6447c1690a6fdaa8c5f41e6b76526b7afe96f3"]},"offset":"889489"},"utils.js":{"size":1655,"integrity":{"algorithm":"SHA256","hash":"5372a36f4b2c5023788c23dbc6639155cb016a1b111e8fc1d6bf97cbaf11b1f8","blockSize":4194304,"blocks":["5372a36f4b2c5023788c23dbc6639155cb016a1b111e8fc1d6bf97cbaf11b1f8"]},"offset":"890034"}}},"move":{"files":{"index.js":{"size":147,"integrity":{"algorithm":"SHA256","hash":"274f9fd31ac65cdc7dd9a6c568fb1163c2b043f6d5fcad30d5177961e9e3e240","blockSize":4194304,"blocks":["274f9fd31ac65cdc7dd9a6c568fb1163c2b043f6d5fcad30d5177961e9e3e240"]},"offset":"891689"},"move-sync.js":{"size":1485,"integrity":{"algorithm":"SHA256","hash":"10c9f85215adcbc49661e5629d81ab4a5dbae552dd59032836d28cb2836d1cce","blockSize":4194304,"blocks":["10c9f85215adcbc49661e5629d81ab4a5dbae552dd59032836d28cb2836d1cce"]},"offset":"891836"},"move.js":{"size":2010,"integrity":{"algorithm":"SHA256","hash":"5487cd460cb8af3e0b2ed0055d61185e56bea35d08c01972b7f1a87e0433aabe","blockSize":4194304,"blocks":["5487cd460cb8af3e0b2ed0055d61185e56bea35d08c01972b7f1a87e0433aabe"]},"offset":"893321"}}},"output-file":{"files":{"index.js":{"size":947,"integrity":{"algorithm":"SHA256","hash":"a27d1a72ed1ecddffc57e70187a4b72467ed0dd34092b7e3d2817b9f4359ab5d","blockSize":4194304,"blocks":["a27d1a72ed1ecddffc57e70187a4b72467ed0dd34092b7e3d2817b9f4359ab5d"]},"offset":"895331"}}},"path-exists":{"files":{"index.js":{"size":263,"integrity":{"algorithm":"SHA256","hash":"5ce096c95daec0259817248921b39a9e0df4d342db171138ccb62440cc7a0cbe","blockSize":4194304,"blocks":["5ce096c95daec0259817248921b39a9e0df4d342db171138ccb62440cc7a0cbe"]},"offset":"896278"}}},"remove":{"files":{"index.js":{"size":489,"integrity":{"algorithm":"SHA256","hash":"ad79431e3d1cae731565d3e7403f619aee21f3b276d3541fe794ec7fd59ab0da","blockSize":4194304,"blocks":["ad79431e3d1cae731565d3e7403f619aee21f3b276d3541fe794ec7fd59ab0da"]},"offset":"896541"},"rimraf.js":{"size":7443,"integrity":{"algorithm":"SHA256","hash":"931cd85d1564a59db583841196cf2773940e7eee30830514b448d2d4919cc534","blockSize":4194304,"blocks":["931cd85d1564a59db583841196cf2773940e7eee30830514b448d2d4919cc534"]},"offset":"897030"}}},"util":{"files":{"stat.js":{"size":5226,"integrity":{"algorithm":"SHA256","hash":"fe33d6c739866764c937e8aaeb518bbda7a36b0f3c006855b26c5bdd846081c3","blockSize":4194304,"blocks":["fe33d6c739866764c937e8aaeb518bbda7a36b0f3c006855b26c5bdd846081c3"]},"offset":"904473"},"utimes.js":{"size":615,"integrity":{"algorithm":"SHA256","hash":"4a049bcd580984957b8690fb05f7a6bf5c7e59bfc78d6817882945c35f3a44d4","blockSize":4194304,"blocks":["4a049bcd580984957b8690fb05f7a6bf5c7e59bfc78d6817882945c35f3a44d4"]},"offset":"909699"}}}}},"package.json":{"size":950,"integrity":{"algorithm":"SHA256","hash":"8625f8d6674f3dacbdd5ed9fc553d9583234a6403ef90b1612f786b8fad17711","blockSize":4194304,"blocks":["8625f8d6674f3dacbdd5ed9fc553d9583234a6403ef90b1612f786b8fad17711"]},"offset":"910314"}}},"jsonfile":{"files":{"LICENSE":{"size":1110,"integrity":{"algorithm":"SHA256","hash":"a9801fb52ba22ef808682a094da8a7a480584b7ed0dfd0d888ab543616335031","blockSize":4194304,"blocks":["a9801fb52ba22ef808682a094da8a7a480584b7ed0dfd0d888ab543616335031"]},"offset":"911264"},"index.js":{"size":2014,"integrity":{"algorithm":"SHA256","hash":"ec5a9f1f45014486f1df4a8c11a5b078671e9936c0651e035b67cb5e763954e8","blockSize":4194304,"blocks":["ec5a9f1f45014486f1df4a8c11a5b078671e9936c0651e035b67cb5e763954e8"]},"offset":"912374"},"package.json":{"size":558,"integrity":{"algorithm":"SHA256","hash":"3043c6a921afa1effb6d050a55ee6be00f4b8d940a21c95d598522467c263c7a","blockSize":4194304,"blocks":["3043c6a921afa1effb6d050a55ee6be00f4b8d940a21c95d598522467c263c7a"]},"offset":"914388"},"utils.js":{"size":498,"integrity":{"algorithm":"SHA256","hash":"b0c188696676561411f3c5784d7de61bf21927f9c334e0cfb9136a8b7c82be5d","blockSize":4194304,"blocks":["b0c188696676561411f3c5784d7de61bf21927f9c334e0cfb9136a8b7c82be5d"]},"offset":"914946"}}},"semver":{"files":{"LICENSE":{"size":765,"integrity":{"algorithm":"SHA256","hash":"4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b","blockSize":4194304,"blocks":["4ec3d4c66cd87f5c8d8ad911b10f99bf27cb00cdfcff82621956e379186b016b"]},"offset":"915444"},"bin":{"files":{"semver.js":{"size":4739,"integrity":{"algorithm":"SHA256","hash":"ad25dc10977d5f51e783a48f8721fcc8f0f2284f1a99614d14eb1428b959ce47","blockSize":4194304,"blocks":["ad25dc10977d5f51e783a48f8721fcc8f0f2284f1a99614d14eb1428b959ce47"]},"offset":"916209","executable":true}}},"classes":{"files":{"comparator.js":{"size":3631,"integrity":{"algorithm":"SHA256","hash":"054202956430d63d5ff4599fae09760ce465b489e4f0b5ef5ce7cc7ac21157ac","blockSize":4194304,"blocks":["054202956430d63d5ff4599fae09760ce465b489e4f0b5ef5ce7cc7ac21157ac"]},"offset":"920948"},"index.js":{"size":143,"integrity":{"algorithm":"SHA256","hash":"3bb69280c2a788d0eb16f915bb9df4dbe812075182024c753dca2283bcea1b17","blockSize":4194304,"blocks":["3bb69280c2a788d0eb16f915bb9df4dbe812075182024c753dca2283bcea1b17"]},"offset":"924579"},"range.js":{"size":14977,"integrity":{"algorithm":"SHA256","hash":"cf8f8eb6934663ae2a9d04838d4d71555427a2abd3c8748ee5219507969a6b46","blockSize":4194304,"blocks":["cf8f8eb6934663ae2a9d04838d4d71555427a2abd3c8748ee5219507969a6b46"]},"offset":"924722"},"semver.js":{"size":9480,"integrity":{"algorithm":"SHA256","hash":"d5ba57e5c93f031b1d234fca4bb746746fcd1fe51be7e5ee895601e2c12e2083","blockSize":4194304,"blocks":["d5ba57e5c93f031b1d234fca4bb746746fcd1fe51be7e5ee895601e2c12e2083"]},"offset":"939699"}}},"functions":{"files":{"clean.js":{"size":205,"integrity":{"algorithm":"SHA256","hash":"4eadb0892844cf3ae295121a86163a66c73f89acd1b7f0b114ec115b4539512f","blockSize":4194304,"blocks":["4eadb0892844cf3ae295121a86163a66c73f89acd1b7f0b114ec115b4539512f"]},"offset":"949179"},"cmp.js":{"size":961,"integrity":{"algorithm":"SHA256","hash":"a63d74e87b73788e78e9ce0a4892b5333d6b809c0de88b31e4ed76cbf17f94b3","blockSize":4194304,"blocks":["a63d74e87b73788e78e9ce0a4892b5333d6b809c0de88b31e4ed76cbf17f94b3"]},"offset":"949384"},"coerce.js":{"size":2004,"integrity":{"algorithm":"SHA256","hash":"28a251c5ab210ddf9e97551b9f37a53329fcce91f0c3943dcbc02de1a1de915a","blockSize":4194304,"blocks":["28a251c5ab210ddf9e97551b9f37a53329fcce91f0c3943dcbc02de1a1de915a"]},"offset":"950345"},"compare-build.js":{"size":281,"integrity":{"algorithm":"SHA256","hash":"5ab651d5b40af289bd85c645a92b6d8cfe1a986dc413c797cfcc8d623d7c844c","blockSize":4194304,"blocks":["5ab651d5b40af289bd85c645a92b6d8cfe1a986dc413c797cfcc8d623d7c844c"]},"offset":"952349"},"compare-loose.js":{"size":132,"integrity":{"algorithm":"SHA256","hash":"07b6a3a1db0a5210ceb784c1708bd4679f3a94fc73a9c9eb349349e7070a6f78","blockSize":4194304,"blocks":["07b6a3a1db0a5210ceb784c1708bd4679f3a94fc73a9c9eb349349e7070a6f78"]},"offset":"952630"},"compare.js":{"size":170,"integrity":{"algorithm":"SHA256","hash":"d404b5aa48aaddc8a654c5da8fb7d4443404b7948589b21ac4b045d1cee4e34c","blockSize":4194304,"blocks":["d404b5aa48aaddc8a654c5da8fb7d4443404b7948589b21ac4b045d1cee4e34c"]},"offset":"952762"},"diff.js":{"size":1421,"integrity":{"algorithm":"SHA256","hash":"ea876a3256d09f1301d33a95cd6451b6312c055328abfc8fc49b5f27fe6d2afe","blockSize":4194304,"blocks":["ea876a3256d09f1301d33a95cd6451b6312c055328abfc8fc49b5f27fe6d2afe"]},"offset":"952932"},"eq.js":{"size":126,"integrity":{"algorithm":"SHA256","hash":"b6e30a7168e52723216fc163d300e2bbabf92ec0251f9ac5438bb6ccf57c8936","blockSize":4194304,"blocks":["b6e30a7168e52723216fc163d300e2bbabf92ec0251f9ac5438bb6ccf57c8936"]},"offset":"954353"},"gt.js":{"size":124,"integrity":{"algorithm":"SHA256","hash":"135523704aa48cd98834dd170ee9f74f0e68043b379f32d021db11e6304c5c93","blockSize":4194304,"blocks":["135523704aa48cd98834dd170ee9f74f0e68043b379f32d021db11e6304c5c93"]},"offset":"954479"},"gte.js":{"size":127,"integrity":{"algorithm":"SHA256","hash":"991c5bbe48ecb210a562646872f05862ad9fc0d42186d85aa60bdc6fa323eb9d","blockSize":4194304,"blocks":["991c5bbe48ecb210a562646872f05862ad9fc0d42186d85aa60bdc6fa323eb9d"]},"offset":"954603"},"inc.js":{"size":478,"integrity":{"algorithm":"SHA256","hash":"952069fc8690b7d3af0fe9d55f7c54fe2ac067b48c5e74f6a54f9ce19a334493","blockSize":4194304,"blocks":["952069fc8690b7d3af0fe9d55f7c54fe2ac067b48c5e74f6a54f9ce19a334493"]},"offset":"954730"},"lt.js":{"size":124,"integrity":{"algorithm":"SHA256","hash":"1c897a9bc849320e2e9dc0f6c09555c01ee3ddf30734515d717b88ad7740ea25","blockSize":4194304,"blocks":["1c897a9bc849320e2e9dc0f6c09555c01ee3ddf30734515d717b88ad7740ea25"]},"offset":"955208"},"lte.js":{"size":127,"integrity":{"algorithm":"SHA256","hash":"3a8d0b1d00423f60cc7cb810b36ab77b61330831ad237dbe73eb5cecfa412800","blockSize":4194304,"blocks":["3a8d0b1d00423f60cc7cb810b36ab77b61330831ad237dbe73eb5cecfa412800"]},"offset":"955332"},"major.js":{"size":136,"integrity":{"algorithm":"SHA256","hash":"5c678480d882f511200fed2c16ec3847dfedb08a1d70328dc2f031d35d825276","blockSize":4194304,"blocks":["5c678480d882f511200fed2c16ec3847dfedb08a1d70328dc2f031d35d825276"]},"offset":"955459"},"minor.js":{"size":136,"integrity":{"algorithm":"SHA256","hash":"1b051794f1713adec2a236517196691687c35f82e0b596ff3316a78b3cc10ae6","blockSize":4194304,"blocks":["1b051794f1713adec2a236517196691687c35f82e0b596ff3316a78b3cc10ae6"]},"offset":"955595"},"neq.js":{"size":128,"integrity":{"algorithm":"SHA256","hash":"a662883751918822c162183b46b9e20d09489132f82686c92ab78bee67f3a127","blockSize":4194304,"blocks":["a662883751918822c162183b46b9e20d09489132f82686c92ab78bee67f3a127"]},"offset":"955731"},"parse.js":{"size":331,"integrity":{"algorithm":"SHA256","hash":"29a69e15b6d02fe381d573f861881a89590e9d0f0f0ca740c5f85eaf0234c4ad","blockSize":4194304,"blocks":["29a69e15b6d02fe381d573f861881a89590e9d0f0f0ca740c5f85eaf0234c4ad"]},"offset":"955859"},"patch.js":{"size":136,"integrity":{"algorithm":"SHA256","hash":"f02d3c1b059fe3d96ce124886f7eef321d381a95638fd3c4a8d5ccd8e76ffadd","blockSize":4194304,"blocks":["f02d3c1b059fe3d96ce124886f7eef321d381a95638fd3c4a8d5ccd8e76ffadd"]},"offset":"956190"},"prerelease.js":{"size":234,"integrity":{"algorithm":"SHA256","hash":"baedbf503d5610ad041bfb56071efa48feb331ca278295c399537d35d3ffb593","blockSize":4194304,"blocks":["baedbf503d5610ad041bfb56071efa48feb331ca278295c399537d35d3ffb593"]},"offset":"956326"},"rcompare.js":{"size":132,"integrity":{"algorithm":"SHA256","hash":"84fa5e88adf08d15c993cac8cdec6d1a65045b7e95a9c55184230a7f807f4dc0","blockSize":4194304,"blocks":["84fa5e88adf08d15c993cac8cdec6d1a65045b7e95a9c55184230a7f807f4dc0"]},"offset":"956560"},"rsort.js":{"size":163,"integrity":{"algorithm":"SHA256","hash":"6ec659ce3b6c2b173c719286caab04409adba046c0917874ec3b5e36ddfbc7e3","blockSize":4194304,"blocks":["6ec659ce3b6c2b173c719286caab04409adba046c0917874ec3b5e36ddfbc7e3"]},"offset":"956692"},"satisfies.js":{"size":247,"integrity":{"algorithm":"SHA256","hash":"8cf5e122b757251671ed6c9d9680904b71cd375845853f05312e608cf2cc2946","blockSize":4194304,"blocks":["8cf5e122b757251671ed6c9d9680904b71cd375845853f05312e608cf2cc2946"]},"offset":"956855"},"sort.js":{"size":161,"integrity":{"algorithm":"SHA256","hash":"c2fe2d3ed0be8a4e9de8f02abdfd5d9c0d3bcc510d88e87af84185592882c4b8","blockSize":4194304,"blocks":["c2fe2d3ed0be8a4e9de8f02abdfd5d9c0d3bcc510d88e87af84185592882c4b8"]},"offset":"957102"},"valid.js":{"size":176,"integrity":{"algorithm":"SHA256","hash":"0de7ea736cb7807179d46dfac09c830a9338e02b6a07db12d7040cde2def6025","blockSize":4194304,"blocks":["0de7ea736cb7807179d46dfac09c830a9338e02b6a07db12d7040cde2def6025"]},"offset":"957263"}}},"index.js":{"size":2630,"integrity":{"algorithm":"SHA256","hash":"646e0b707f56dca7cb90cebc6fe687278bcc1a16fdcc83756dbe23083ff15e06","blockSize":4194304,"blocks":["646e0b707f56dca7cb90cebc6fe687278bcc1a16fdcc83756dbe23083ff15e06"]},"offset":"957439"},"internal":{"files":{"constants.js":{"size":873,"integrity":{"algorithm":"SHA256","hash":"38a112baf27ceca0260082ff26ac2fd7a9861cab1af12dd65e720277f68e6ce9","blockSize":4194304,"blocks":["38a112baf27ceca0260082ff26ac2fd7a9861cab1af12dd65e720277f68e6ce9"]},"offset":"960069"},"debug.js":{"size":240,"integrity":{"algorithm":"SHA256","hash":"8a9f420572260f3cf944463b5090d62a60f0730589dc23a7ec4ca25e2ee41bb3","blockSize":4194304,"blocks":["8a9f420572260f3cf944463b5090d62a60f0730589dc23a7ec4ca25e2ee41bb3"]},"offset":"960942"},"identifiers.js":{"size":525,"integrity":{"algorithm":"SHA256","hash":"b4916b09dc7869ae0eb05e71c855c942a3a7365f7e6e89185d59a9e45a2451d7","blockSize":4194304,"blocks":["b4916b09dc7869ae0eb05e71c855c942a3a7365f7e6e89185d59a9e45a2451d7"]},"offset":"961182"},"lrucache.js":{"size":802,"integrity":{"algorithm":"SHA256","hash":"14d087c87da87b6f5c36fc4cdd7d2d14077874b14a68e20fce5b6138fa2ca34f","blockSize":4194304,"blocks":["14d087c87da87b6f5c36fc4cdd7d2d14077874b14a68e20fce5b6138fa2ca34f"]},"offset":"961707"},"parse-options.js":{"size":338,"integrity":{"algorithm":"SHA256","hash":"fdf51d0de8d5442c35a997ef58cd530d239ce206f961d14c5121354451b01d01","blockSize":4194304,"blocks":["fdf51d0de8d5442c35a997ef58cd530d239ce206f961d14c5121354451b01d01"]},"offset":"962509"},"re.js":{"size":8141,"integrity":{"algorithm":"SHA256","hash":"016655766a1381078a83ba04cd6ba39afc6e64c3e5a95789ad82c3672ae87a94","blockSize":4194304,"blocks":["016655766a1381078a83ba04cd6ba39afc6e64c3e5a95789ad82c3672ae87a94"]},"offset":"962847"}}},"package.json":{"size":1350,"integrity":{"algorithm":"SHA256","hash":"39245ea8261405e7056b1d025073f6f3b2d0eb9f9111cd307663668fe62d93e1","blockSize":4194304,"blocks":["39245ea8261405e7056b1d025073f6f3b2d0eb9f9111cd307663668fe62d93e1"]},"offset":"970988"},"preload.js":{"size":83,"integrity":{"algorithm":"SHA256","hash":"edb6808911bebcb324b2df57e5c9935149e56984ff083b74c6cfe215f5b710ba","blockSize":4194304,"blocks":["edb6808911bebcb324b2df57e5c9935149e56984ff083b74c6cfe215f5b710ba"]},"offset":"972338"},"range.bnf":{"size":619,"integrity":{"algorithm":"SHA256","hash":"ed628fdaff64be366d07f6cc4559eae4de109826f743ea7f5e1588c370bca49a","blockSize":4194304,"blocks":["ed628fdaff64be366d07f6cc4559eae4de109826f743ea7f5e1588c370bca49a"]},"offset":"972421"},"ranges":{"files":{"gtr.js":{"size":231,"integrity":{"algorithm":"SHA256","hash":"8fadad28e36d28e93d498ac7ac20badba2a407312845eabc18e82e90a0732b19","blockSize":4194304,"blocks":["8fadad28e36d28e93d498ac7ac20badba2a407312845eabc18e82e90a0732b19"]},"offset":"973040"},"intersects.js":{"size":224,"integrity":{"algorithm":"SHA256","hash":"fe87ac5d3020010ad3ec00636dadbf0c669ff07d0f57e0a8165a8264f79a676f","blockSize":4194304,"blocks":["fe87ac5d3020010ad3ec00636dadbf0c669ff07d0f57e0a8165a8264f79a676f"]},"offset":"973271"},"ltr.js":{"size":227,"integrity":{"algorithm":"SHA256","hash":"e5186fcc03018acf9be6d968755d4c49727aeb0d981d179eb568ae5fbe983038","blockSize":4194304,"blocks":["e5186fcc03018acf9be6d968755d4c49727aeb0d981d179eb568ae5fbe983038"]},"offset":"973495"},"max-satisfying.js":{"size":593,"integrity":{"algorithm":"SHA256","hash":"e1a2c0d6144cc772cd20bbc8ecb9e8a3a4074e9172a3d8e794838b591cdeb416","blockSize":4194304,"blocks":["e1a2c0d6144cc772cd20bbc8ecb9e8a3a4074e9172a3d8e794838b591cdeb416"]},"offset":"973722"},"min-satisfying.js":{"size":591,"integrity":{"algorithm":"SHA256","hash":"2681abf54098aa670f12826b76a6ec77a2441186ae4243afde3be8ae4908f7ca","blockSize":4194304,"blocks":["2681abf54098aa670f12826b76a6ec77a2441186ae4243afde3be8ae4908f7ca"]},"offset":"974315"},"min-version.js":{"size":1514,"integrity":{"algorithm":"SHA256","hash":"fefba0a88c2bf74d5cede504b5ae50a8dc3edfd69cf0174a491e2cf3e442614b","blockSize":4194304,"blocks":["fefba0a88c2bf74d5cede504b5ae50a8dc3edfd69cf0174a491e2cf3e442614b"]},"offset":"974906"},"outside.js":{"size":2204,"integrity":{"algorithm":"SHA256","hash":"3a2b0b23593d2f49419c06af2af75450cab103b0c25d665d48fe5bca495a21ca","blockSize":4194304,"blocks":["3a2b0b23593d2f49419c06af2af75450cab103b0c25d665d48fe5bca495a21ca"]},"offset":"976420"},"simplify.js":{"size":1355,"integrity":{"algorithm":"SHA256","hash":"7b78581c13322bc68ece2088685386b2a9b51c15b94d0a2063bdf2546bd41934","blockSize":4194304,"blocks":["7b78581c13322bc68ece2088685386b2a9b51c15b94d0a2063bdf2546bd41934"]},"offset":"978624"},"subset.js":{"size":7524,"integrity":{"algorithm":"SHA256","hash":"299abae66d0bcf7ac4f4bdf593fcf14e6c94964ffdd7c72b844357925693d3c2","blockSize":4194304,"blocks":["299abae66d0bcf7ac4f4bdf593fcf14e6c94964ffdd7c72b844357925693d3c2"]},"offset":"979979"},"to-comparators.js":{"size":282,"integrity":{"algorithm":"SHA256","hash":"6c5e966210cff270fa2850668aaf8460fac7759f8d99f282521ef7a78f4564e9","blockSize":4194304,"blocks":["6c5e966210cff270fa2850668aaf8460fac7759f8d99f282521ef7a78f4564e9"]},"offset":"987503"},"valid.js":{"size":326,"integrity":{"algorithm":"SHA256","hash":"5ef6f995af801868925940cf8df5735d565ebabb090b068695cae65218bcd3ac","blockSize":4194304,"blocks":["5ef6f995af801868925940cf8df5735d565ebabb090b068695cae65218bcd3ac"]},"offset":"987785"}}}}},"universalify":{"files":{"LICENSE":{"size":1100,"integrity":{"algorithm":"SHA256","hash":"3fda5977c0904e226190b4e21d64340c1731e2142d6fe5f3dee0090a216b8b63","blockSize":4194304,"blocks":["3fda5977c0904e226190b4e21d64340c1731e2142d6fe5f3dee0090a216b8b63"]},"offset":"988111"},"index.js":{"size":706,"integrity":{"algorithm":"SHA256","hash":"83b02adb3872f6c482db4e57c300fa39b5cad65e317fc2f70b9de7d305c035a1","blockSize":4194304,"blocks":["83b02adb3872f6c482db4e57c300fa39b5cad65e317fc2f70b9de7d305c035a1"]},"offset":"989211"},"package.json":{"size":618,"integrity":{"algorithm":"SHA256","hash":"5b39e9c6305a5ba27c76caf4817244dd1a308b68c7559dfe15471173466cf06e","blockSize":4194304,"blocks":["5b39e9c6305a5ba27c76caf4817244dd1a308b68c7559dfe15471173466cf06e"]},"offset":"989917"}}}}}}},"graceful-fs":{"files":{"LICENSE":{"size":791,"integrity":{"algorithm":"SHA256","hash":"f65c5d9f22a317b2a10803bd1868461ce6499c2ed7217bc80c0cc772a748789c","blockSize":4194304,"blocks":["f65c5d9f22a317b2a10803bd1868461ce6499c2ed7217bc80c0cc772a748789c"]},"offset":"990535"},"clone.js":{"size":496,"integrity":{"algorithm":"SHA256","hash":"7258eca52e65d69845759503f9fdd66c252f40e5eafb76db5d481172e31ac9ed","blockSize":4194304,"blocks":["7258eca52e65d69845759503f9fdd66c252f40e5eafb76db5d481172e31ac9ed"]},"offset":"991326"},"graceful-fs.js":{"size":12680,"integrity":{"algorithm":"SHA256","hash":"7da35669b6b6b0e4aafee31674c033f2cebb0c8f9ae010f709dcc185d3f17786","blockSize":4194304,"blocks":["7da35669b6b6b0e4aafee31674c033f2cebb0c8f9ae010f709dcc185d3f17786"]},"offset":"991822"},"legacy-streams.js":{"size":2655,"integrity":{"algorithm":"SHA256","hash":"60a6a7ecf7c3e55a3ffaae13433b6cff388b7205bba6daf393c863f77a949e36","blockSize":4194304,"blocks":["60a6a7ecf7c3e55a3ffaae13433b6cff388b7205bba6daf393c863f77a949e36"]},"offset":"1004502"},"package.json":{"size":600,"integrity":{"algorithm":"SHA256","hash":"5f558a45ee1f8ea431e950ab3864f842b9de5325e30a31ba1bd68f6f768457ed","blockSize":4194304,"blocks":["5f558a45ee1f8ea431e950ab3864f842b9de5325e30a31ba1bd68f6f768457ed"]},"offset":"1007157"},"polyfills.js":{"size":10141,"integrity":{"algorithm":"SHA256","hash":"66ea1687ed5edf39d67296d26edccc8da695d9a869303a78d0e580cd770aca27","blockSize":4194304,"blocks":["66ea1687ed5edf39d67296d26edccc8da695d9a869303a78d0e580cd770aca27"]},"offset":"1007757"}}},"js-yaml":{"files":{"LICENSE":{"size":1084,"integrity":{"algorithm":"SHA256","hash":"a07bc24468b9654ce76a547d47a2db282d07733b715db4c73a98bd63961f9550","blockSize":4194304,"blocks":["a07bc24468b9654ce76a547d47a2db282d07733b715db4c73a98bd63961f9550"]},"offset":"1017898"},"bin":{"files":{"js-yaml.js":{"size":2736,"integrity":{"algorithm":"SHA256","hash":"6d7749dfd8019095970f4366cd09ec3abef9deaa3f870709dffecb027e58902d","blockSize":4194304,"blocks":["6d7749dfd8019095970f4366cd09ec3abef9deaa3f870709dffecb027e58902d"]},"offset":"1018982","executable":true}}},"dist":{"files":{"js-yaml.js":{"size":114359,"integrity":{"algorithm":"SHA256","hash":"c738b0020702aa631abd8de23a902a3079d99d3060e44166955cb51f570881c4","blockSize":4194304,"blocks":["c738b0020702aa631abd8de23a902a3079d99d3060e44166955cb51f570881c4"]},"offset":"1021718"},"js-yaml.min.js":{"size":39430,"integrity":{"algorithm":"SHA256","hash":"45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7","blockSize":4194304,"blocks":["45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7"]},"offset":"1136077"},"js-yaml.mjs":{"size":107533,"integrity":{"algorithm":"SHA256","hash":"16f210b939b359b6ec8dde581eb62c157185711dc7b719b33779c43db5c31a91","blockSize":4194304,"blocks":["16f210b939b359b6ec8dde581eb62c157185711dc7b719b33779c43db5c31a91"]},"offset":"1175507"}}},"index.js":{"size":1793,"integrity":{"algorithm":"SHA256","hash":"7d1ebc0d9929b9124997b439d1a1fd9aff8feb6bb0a1b59e977ea638944f34ba","blockSize":4194304,"blocks":["7d1ebc0d9929b9124997b439d1a1fd9aff8feb6bb0a1b59e977ea638944f34ba"]},"offset":"1283040"},"lib":{"files":{"common.js":{"size":1177,"integrity":{"algorithm":"SHA256","hash":"9211491f8e0058a419a4664e36bb4ec6509655aabe6bd537eddf941fdf34e734","blockSize":4194304,"blocks":["9211491f8e0058a419a4664e36bb4ec6509655aabe6bd537eddf941fdf34e734"]},"offset":"1284833"},"dumper.js":{"size":31893,"integrity":{"algorithm":"SHA256","hash":"1a0c7fc01df0e950caf526c2a96b1e9fbac1dbc5dc125e83657f7b723a505ca3","blockSize":4194304,"blocks":["1a0c7fc01df0e950caf526c2a96b1e9fbac1dbc5dc125e83657f7b723a505ca3"]},"offset":"1286010"},"exception.js":{"size":1299,"integrity":{"algorithm":"SHA256","hash":"3dcd70e20270a93b8769204174a1949a133a41afbc8f1a74a9c6ab73fd60a179","blockSize":4194304,"blocks":["3dcd70e20270a93b8769204174a1949a133a41afbc8f1a74a9c6ab73fd60a179"]},"offset":"1317903"},"loader.js":{"size":47142,"integrity":{"algorithm":"SHA256","hash":"dd1053d4a607cc29dd2020ac77afa283002c8fd1d9b0d7042a7fc763c883f794","blockSize":4194304,"blocks":["dd1053d4a607cc29dd2020ac77afa283002c8fd1d9b0d7042a7fc763c883f794"]},"offset":"1319202"},"schema.js":{"size":3384,"integrity":{"algorithm":"SHA256","hash":"be14297ea2917dcb9ee11a7deb5b3a871f57ad978e5368c62407c83cd4dd18bf","blockSize":4194304,"blocks":["be14297ea2917dcb9ee11a7deb5b3a871f57ad978e5368c62407c83cd4dd18bf"]},"offset":"1366344"},"schema":{"files":{"core.js":{"size":288,"integrity":{"algorithm":"SHA256","hash":"d736e58b5a947a5b86056bf4b881c8002314b6534ab1a697a67cc47e1b2dc2a0","blockSize":4194304,"blocks":["d736e58b5a947a5b86056bf4b881c8002314b6534ab1a697a67cc47e1b2dc2a0"]},"offset":"1369728"},"default.js":{"size":538,"integrity":{"algorithm":"SHA256","hash":"aa09d88b4be7c51d8b6cb0b533c51ae17f534deed476c576b8d4cd3ce1bf165a","blockSize":4194304,"blocks":["aa09d88b4be7c51d8b6cb0b533c51ae17f534deed476c576b8d4cd3ce1bf165a"]},"offset":"1370016"},"failsafe.js":{"size":278,"integrity":{"algorithm":"SHA256","hash":"96d4b5b129b966f49d8028fc752a54cb9ca0c80cc4d076240766b946a2b329c5","blockSize":4194304,"blocks":["96d4b5b129b966f49d8028fc752a54cb9ca0c80cc4d076240766b946a2b329c5"]},"offset":"1370554"},"json.js":{"size":523,"integrity":{"algorithm":"SHA256","hash":"aa53e414f077035b4d477d19095ac01e60d9df73af716a188fd2772314041f92","blockSize":4194304,"blocks":["aa53e414f077035b4d477d19095ac01e60d9df73af716a188fd2772314041f92"]},"offset":"1370832"}}},"snippet.js":{"size":3088,"integrity":{"algorithm":"SHA256","hash":"1658b8ec688ebdd2e2dffc93fffc9cba0e9a93ad2a9a1d39b08ed5a1df5afade","blockSize":4194304,"blocks":["1658b8ec688ebdd2e2dffc93fffc9cba0e9a93ad2a9a1d39b08ed5a1df5afade"]},"offset":"1371355"},"type.js":{"size":1849,"integrity":{"algorithm":"SHA256","hash":"11d7ff8e46ecc9ef8b5334aa491973ee95a5f43841afa27e14a0594cca464170","blockSize":4194304,"blocks":["11d7ff8e46ecc9ef8b5334aa491973ee95a5f43841afa27e14a0594cca464170"]},"offset":"1374443"},"type":{"files":{"binary.js":{"size":2912,"integrity":{"algorithm":"SHA256","hash":"245745c866e306704407d6738e1a77776ce41e79e4cc3b2f418ae475bd00c3c9","blockSize":4194304,"blocks":["245745c866e306704407d6738e1a77776ce41e79e4cc3b2f418ae475bd00c3c9"]},"offset":"1376292"},"bool.js":{"size":971,"integrity":{"algorithm":"SHA256","hash":"634b7821ceb0877b5320a17b3b0fc3fb60ac3092b86c9d069722f18e2421c1db","blockSize":4194304,"blocks":["634b7821ceb0877b5320a17b3b0fc3fb60ac3092b86c9d069722f18e2421c1db"]},"offset":"1379204"},"float.js":{"size":2467,"integrity":{"algorithm":"SHA256","hash":"2d762d35ad3e06d96f512fb5ece8f7172e2543bb19c551f64c5e4005a66bbca2","blockSize":4194304,"blocks":["2d762d35ad3e06d96f512fb5ece8f7172e2543bb19c551f64c5e4005a66bbca2"]},"offset":"1380175"},"int.js":{"size":3691,"integrity":{"algorithm":"SHA256","hash":"0dac842d32923113f2a6a153a280f6120f6ccc2da9024ba01fd4d99065d29fcf","blockSize":4194304,"blocks":["0dac842d32923113f2a6a153a280f6120f6ccc2da9024ba01fd4d99065d29fcf"]},"offset":"1382642"},"map.js":{"size":190,"integrity":{"algorithm":"SHA256","hash":"b9bf146012164a0a59ea8c5f6576052706d330a1e41ab8092e11a67d6b9ccf2c","blockSize":4194304,"blocks":["b9bf146012164a0a59ea8c5f6576052706d330a1e41ab8092e11a67d6b9ccf2c"]},"offset":"1386333"},"merge.js":{"size":230,"integrity":{"algorithm":"SHA256","hash":"bf34d9da7bb1158c5bdd8ae4474d11645c824440f68de79813c384cd77c4791b","blockSize":4194304,"blocks":["bf34d9da7bb1158c5bdd8ae4474d11645c824440f68de79813c384cd77c4791b"]},"offset":"1386523"},"null.js":{"size":808,"integrity":{"algorithm":"SHA256","hash":"8f3abf27966dfc51e80ea72b363ca74b6d3bca0b15695f61e93bfee2858531f1","blockSize":4194304,"blocks":["8f3abf27966dfc51e80ea72b363ca74b6d3bca0b15695f61e93bfee2858531f1"]},"offset":"1386753"},"omap.js":{"size":1023,"integrity":{"algorithm":"SHA256","hash":"a4fa54ca0343665eb199503d772a4fe4aab792e4e08bee682e70c0d4a5ada043","blockSize":4194304,"blocks":["a4fa54ca0343665eb199503d772a4fe4aab792e4e08bee682e70c0d4a5ada043"]},"offset":"1387561"},"pairs.js":{"size":1084,"integrity":{"algorithm":"SHA256","hash":"faebb6d8a9d1b0cd755f92113e49464711d87060f17d1e807695924866f89a4a","blockSize":4194304,"blocks":["faebb6d8a9d1b0cd755f92113e49464711d87060f17d1e807695924866f89a4a"]},"offset":"1388584"},"seq.js":{"size":191,"integrity":{"algorithm":"SHA256","hash":"f3d76a1db2a6772a51ac32059dcc18b6666ae9c5a60a649467b5853a2fbaf425","blockSize":4194304,"blocks":["f3d76a1db2a6772a51ac32059dcc18b6666ae9c5a60a649467b5853a2fbaf425"]},"offset":"1389668"},"set.js":{"size":547,"integrity":{"algorithm":"SHA256","hash":"60d13edc50b58b037a6ef561d2f751c601826e455c011acf48c830baa1412107","blockSize":4194304,"blocks":["60d13edc50b58b037a6ef561d2f751c601826e455c011acf48c830baa1412107"]},"offset":"1389859"},"str.js":{"size":189,"integrity":{"algorithm":"SHA256","hash":"41e56af5fad426839bfe41c9a3f489de6efec71447490124a69f8f4785c46ab9","blockSize":4194304,"blocks":["41e56af5fad426839bfe41c9a3f489de6efec71447490124a69f8f4785c46ab9"]},"offset":"1390406"},"timestamp.js":{"size":2571,"integrity":{"algorithm":"SHA256","hash":"9e4f77c8d504a3a8319108343d6d6b2b6ed95ba6e96f4fe9b204208d04cfd691","blockSize":4194304,"blocks":["9e4f77c8d504a3a8319108343d6d6b2b6ed95ba6e96f4fe9b204208d04cfd691"]},"offset":"1390595"}}}}},"package.json":{"size":1075,"integrity":{"algorithm":"SHA256","hash":"85aba0e672f9202b2fc0571326c721c67bc22d1cadcb358d9ab103d29e836242","blockSize":4194304,"blocks":["85aba0e672f9202b2fc0571326c721c67bc22d1cadcb358d9ab103d29e836242"]},"offset":"1393166"}}},"lazy-val":{"files":{"out":{"files":{"main.js":{"size":605,"integrity":{"algorithm":"SHA256","hash":"358fa8cba70c9140edafa85c0b7b25c7261939480186167e6b3440905f5b47da","blockSize":4194304,"blocks":["358fa8cba70c9140edafa85c0b7b25c7261939480186167e6b3440905f5b47da"]},"offset":"1394241"},"main.js.map":{"size":1156,"integrity":{"algorithm":"SHA256","hash":"aa3e70f08a0ce115832e5324c4b96aa1475a3b8b36728f50091ebd22aa0f6646","blockSize":4194304,"blocks":["aa3e70f08a0ce115832e5324c4b96aa1475a3b8b36728f50091ebd22aa0f6646"]},"offset":"1394846"}}},"package.json":{"size":330,"integrity":{"algorithm":"SHA256","hash":"a6f4140d0187f32d95545835aca38684e18d0fcfbecb51709b0aaa54decd3c0b","blockSize":4194304,"blocks":["a6f4140d0187f32d95545835aca38684e18d0fcfbecb51709b0aaa54decd3c0b"]},"offset":"1396002"}}},"lodash.escaperegexp":{"files":{"LICENSE":{"size":1951,"integrity":{"algorithm":"SHA256","hash":"ffd8b33b354585f4ce119f19c53728281e48a97b074491eb6bf6d5c5ff305272","blockSize":4194304,"blocks":["ffd8b33b354585f4ce119f19c53728281e48a97b074491eb6bf6d5c5ff305272"]},"offset":"1396332"},"index.js":{"size":4398,"integrity":{"algorithm":"SHA256","hash":"584de6ec78e35344eaef8291338a671f223ec225c4df4220b6f91d8f0c004d8d","blockSize":4194304,"blocks":["584de6ec78e35344eaef8291338a671f223ec225c4df4220b6f91d8f0c004d8d"]},"offset":"1398283"},"package.json":{"size":356,"integrity":{"algorithm":"SHA256","hash":"c71b659d3f3f5dfab55d736b6bd17d97f822b13bcf9b1edbce479f8e691e7892","blockSize":4194304,"blocks":["c71b659d3f3f5dfab55d736b6bd17d97f822b13bcf9b1edbce479f8e691e7892"]},"offset":"1402681"}}},"lodash.isequal":{"files":{"LICENSE":{"size":1950,"integrity":{"algorithm":"SHA256","hash":"e159c6d48c989185448658f276375bfb2300362ec6d4ae5525a2d49c4bcb947d","blockSize":4194304,"blocks":["e159c6d48c989185448658f276375bfb2300362ec6d4ae5525a2d49c4bcb947d"]},"offset":"1403037"},"index.js":{"size":49598,"integrity":{"algorithm":"SHA256","hash":"e552928a511748303101cfd03826a777cfa359eade6a4a60f92c923edbf9184c","blockSize":4194304,"blocks":["e552928a511748303101cfd03826a777cfa359eade6a4a60f92c923edbf9184c"]},"offset":"1404987"},"package.json":{"size":346,"integrity":{"algorithm":"SHA256","hash":"6e84ac44b54c17317d096a280e9d0bd72d736e0a0245095cc7c5d72657890406","blockSize":4194304,"blocks":["6e84ac44b54c17317d096a280e9d0bd72d736e0a0245095cc7c5d72657890406"]},"offset":"1454585"}}},"ms":{"files":{"index.js":{"size":3024,"integrity":{"algorithm":"SHA256","hash":"e5f0b6a946a9b2b356a28557728410717df54ea2f599edb619f9839df6b7b0e9","blockSize":4194304,"blocks":["e5f0b6a946a9b2b356a28557728410717df54ea2f599edb619f9839df6b7b0e9"]},"offset":"1454931"},"license.md":{"size":1079,"integrity":{"algorithm":"SHA256","hash":"1662fae9b5314d11cf51284e2dcd1f006a354f7343f08712a730fcff9a359801","blockSize":4194304,"blocks":["1662fae9b5314d11cf51284e2dcd1f006a354f7343f08712a730fcff9a359801"]},"offset":"1457955"},"package.json":{"size":497,"integrity":{"algorithm":"SHA256","hash":"f983ec581f1dd5a47b7f12b58f97c0b44c4e0cce56cbecc40140031aeef99bdf","blockSize":4194304,"blocks":["f983ec581f1dd5a47b7f12b58f97c0b44c4e0cce56cbecc40140031aeef99bdf"]},"offset":"1459034"}}},"sax":{"files":{"LICENSE":{"size":2031,"integrity":{"algorithm":"SHA256","hash":"e8bf477df410baa41d44132e676d16a5372cf1798599fac2823376dc95e94eee","blockSize":4194304,"blocks":["e8bf477df410baa41d44132e676d16a5372cf1798599fac2823376dc95e94eee"]},"offset":"1459531"},"lib":{"files":{"sax.js":{"size":44774,"integrity":{"algorithm":"SHA256","hash":"e221d28f41ed2b3d7122cf5962772cffe43ae976d8c060cc116470d5cedf54c0","blockSize":4194304,"blocks":["e221d28f41ed2b3d7122cf5962772cffe43ae976d8c060cc116470d5cedf54c0"]},"offset":"1461562"}}},"package.json":{"size":483,"integrity":{"algorithm":"SHA256","hash":"97adb7c524eb2900a54a31f535b543e24aea848e3ff2e4af20810dfef8aeffd0","blockSize":4194304,"blocks":["97adb7c524eb2900a54a31f535b543e24aea848e3ff2e4af20810dfef8aeffd0"]},"offset":"1506336"}}},"tiny-typed-emitter":{"files":{"LICENSE":{"size":1104,"integrity":{"algorithm":"SHA256","hash":"4b3faf884ee71eec3df920b66c98fc6618af28e824cf3a32ef3d8774048cc76d","blockSize":4194304,"blocks":["4b3faf884ee71eec3df920b66c98fc6618af28e824cf3a32ef3d8774048cc76d"]},"offset":"1506819"},"lib":{"files":{"index.js":{"size":132,"integrity":{"algorithm":"SHA256","hash":"1401fdda105ed67f365bd775397aedb2f5f9e43ace031288f0f6868f9ab041be","blockSize":4194304,"blocks":["1401fdda105ed67f365bd775397aedb2f5f9e43ace031288f0f6868f9ab041be"]},"offset":"1507923"}}},"package.json":{"size":395,"integrity":{"algorithm":"SHA256","hash":"eb7f51a4a5a7f41baf54271c726724a047f60d45762d650dc00439a10c37645b","blockSize":4194304,"blocks":["eb7f51a4a5a7f41baf54271c726724a047f60d45762d650dc00439a10c37645b"]},"offset":"1508055"}}}}},"Dockerfile":{"size":693,"integrity":{"algorithm":"SHA256","hash":"a4c82f1d7d26ecd1e257e14a99a472970e8b3bfcdb8a885da8cd94ca8740de5d","blockSize":4194304,"blocks":["a4c82f1d7d26ecd1e257e14a99a472970e8b3bfcdb8a885da8cd94ca8740de5d"]},"offset":"1508450"},"nginx.conf":{"size":1322,"integrity":{"algorithm":"SHA256","hash":"0110b1c56ebcb40fa42d5a1970b2344301397d44636ff764e682c16e27e44d80","blockSize":4194304,"blocks":["0110b1c56ebcb40fa42d5a1970b2344301397d44636ff764e682c16e27e44d80"]},"offset":"1509143"},"out":{"files":{"main":{"files":{"index.js":{"size":10540,"integrity":{"algorithm":"SHA256","hash":"f53f7790bf5b1894793803f022faa3f47dba1e67520d7a280660be4ad5e9ba9d","blockSize":4194304,"blocks":["f53f7790bf5b1894793803f022faa3f47dba1e67520d7a280660be4ad5e9ba9d"]},"offset":"1510465"}}},"preload":{"files":{"index.js":{"size":830,"integrity":{"algorithm":"SHA256","hash":"a8f898f410ac2f81c786c4c2583b23d0933bbe86b38b5052b0d71b2139fd8cc2","blockSize":4194304,"blocks":["a8f898f410ac2f81c786c4c2583b23d0933bbe86b38b5052b0d71b2139fd8cc2"]},"offset":"1521005"}}},"renderer":{"files":{"index.html":{"size":2502,"integrity":{"algorithm":"SHA256","hash":"90604085343e65aa2f03b31458f398b10fd5b2fe5753878d05fabbfc1c5b53bd","blockSize":4194304,"blocks":["90604085343e65aa2f03b31458f398b10fd5b2fe5753878d05fabbfc1c5b53bd"]},"offset":"1521835"}}}}},"package.json":{"size":428,"integrity":{"algorithm":"SHA256","hash":"17ece2a1af6a8ec833d98b5de8c3eafb151348c073f85d351da23b45bf513862","blockSize":4194304,"blocks":["17ece2a1af6a8ec833d98b5de8c3eafb151348c073f85d351da23b45bf513862"]},"offset":"1524337"},"resources":{"files":{"icon.ico":{"size":127770,"integrity":{"algorithm":"SHA256","hash":"2c33d50f69dd4adcb1570c9cc914b2c629aec19ab401209e1375702ad42521aa","blockSize":4194304,"blocks":["2c33d50f69dd4adcb1570c9cc914b2c629aec19ab401209e1375702ad42521aa"]},"unpacked":true},"icon.png":{"size":58613,"integrity":{"algorithm":"SHA256","hash":"9f2a109f2a1266e4aad4f21e72473dca830c22e2acc8d95fe95426e6926e2477","blockSize":4194304,"blocks":["9f2a109f2a1266e4aad4f21e72473dca830c22e2acc8d95fe95426e6926e2477"]},"unpacked":true}}}}} MIT License

Copyright (c) 2022-present, Alex.Wei

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
'use strict';

var electron = require('electron');

const electronAPI = {
    ipcRenderer: {
        send(channel, ...args) {
            electron.ipcRenderer.send(channel, ...args);
        },
        sendTo(webContentsId, channel, ...args) {
            const electronVer = process.versions.electron;
            const electronMajorVer = electronVer ? parseInt(electronVer.split('.')[0]) : 0;
            if (electronMajorVer >= 28) {
                throw new Error('"sendTo" method has been removed since Electron 28.');
            }
            else {
                electron.ipcRenderer.sendTo(webContentsId, channel, ...args);
            }
        },
        sendSync(channel, ...args) {
            return electron.ipcRenderer.sendSync(channel, ...args);
        },
        sendToHost(channel, ...args) {
            electron.ipcRenderer.sendToHost(channel, ...args);
        },
        postMessage(channel, message, transfer) {
            electron.ipcRenderer.postMessage(channel, message, transfer);
        },
        invoke(channel, ...args) {
            return electron.ipcRenderer.invoke(channel, ...args);
        },
        on(channel, listener) {
            electron.ipcRenderer.on(channel, listener);
            return () => {
                electron.ipcRenderer.removeListener(channel, listener);
            };
        },
        once(channel, listener) {
            electron.ipcRenderer.once(channel, listener);
            return () => {
                electron.ipcRenderer.removeListener(channel, listener);
            };
        },
        removeListener(channel, listener) {
            electron.ipcRenderer.removeListener(channel, listener);
            return this;
        },
        removeAllListeners(channel) {
            electron.ipcRenderer.removeAllListeners(channel);
        }
    },
    webFrame: {
        insertCSS(css) {
            return electron.webFrame.insertCSS(css);
        },
        setZoomFactor(factor) {
            if (typeof factor === 'number' && factor > 0) {
                electron.webFrame.setZoomFactor(factor);
            }
        },
        setZoomLevel(level) {
            if (typeof level === 'number') {
                electron.webFrame.setZoomLevel(level);
            }
        }
    },
    webUtils: {
        getPathForFile(file) {
            return electron.webUtils.getPathForFile(file);
        }
    },
    process: {
        get platform() {
            return process.platform;
        },
        get versions() {
            return process.versions;
        },
        get env() {
            return { ...process.env };
        }
    }
};
/**
 * Expose Electron APIs from your preload script, the API
 * will be accessible from the website on `window.electron`.
 */
function exposeElectronAPI() {
    if (process.contextIsolated) {
        try {
            electron.contextBridge.exposeInMainWorld('electron', electronAPI);
        }
        catch (error) {
            console.error(error);
        }
    }
    else {
        // @ts-ignore (need dts)
        window.electron = electronAPI;
    }
}

exports.electronAPI = electronAPI;
exports.exposeElectronAPI = exposeElectronAPI;
import { webUtils, webFrame, ipcRenderer, contextBridge } from 'electron';

const electronAPI = {
    ipcRenderer: {
        send(channel, ...args) {
            ipcRenderer.send(channel, ...args);
        },
        sendTo(webContentsId, channel, ...args) {
            const electronVer = process.versions.electron;
            const electronMajorVer = electronVer ? parseInt(electronVer.split('.')[0]) : 0;
            if (electronMajorVer >= 28) {
                throw new Error('"sendTo" method has been removed since Electron 28.');
            }
            else {
                ipcRenderer.sendTo(webContentsId, channel, ...args);
            }
        },
        sendSync(channel, ...args) {
            return ipcRenderer.sendSync(channel, ...args);
        },
        sendToHost(channel, ...args) {
            ipcRenderer.sendToHost(channel, ...args);
        },
        postMessage(channel, message, transfer) {
            ipcRenderer.postMessage(channel, message, transfer);
        },
        invoke(channel, ...args) {
            return ipcRenderer.invoke(channel, ...args);
        },
        on(channel, listener) {
            ipcRenderer.on(channel, listener);
            return () => {
                ipcRenderer.removeListener(channel, listener);
            };
        },
        once(channel, listener) {
            ipcRenderer.once(channel, listener);
            return () => {
                ipcRenderer.removeListener(channel, listener);
            };
        },
        removeListener(channel, listener) {
            ipcRenderer.removeListener(channel, listener);
            return this;
        },
        removeAllListeners(channel) {
            ipcRenderer.removeAllListeners(channel);
        }
    },
    webFrame: {
        insertCSS(css) {
            return webFrame.insertCSS(css);
        },
        setZoomFactor(factor) {
            if (typeof factor === 'number' && factor > 0) {
                webFrame.setZoomFactor(factor);
            }
        },
        setZoomLevel(level) {
            if (typeof level === 'number') {
                webFrame.setZoomLevel(level);
            }
        }
    },
    webUtils: {
        getPathForFile(file) {
            return webUtils.getPathForFile(file);
        }
    },
    process: {
        get platform() {
            return process.platform;
        },
        get versions() {
            return process.versions;
        },
        get env() {
            return { ...process.env };
        }
    }
};
/**
 * Expose Electron APIs from your preload script, the API
 * will be accessible from the website on `window.electron`.
 */
function exposeElectronAPI() {
    if (process.contextIsolated) {
        try {
            contextBridge.exposeInMainWorld('electron', electronAPI);
        }
        catch (error) {
            console.error(error);
        }
    }
    else {
        // @ts-ignore (need dts)
        window.electron = electronAPI;
    }
}

export { electronAPI, exposeElectronAPI };
{
  "name": "@electron-toolkit/preload",
  "version": "3.0.2",
  "description": "Toolkit for electron preload scripts.",
  "main": "dist/index.cjs",
  "module": "dist/index.mjs",
  "types": "dist/index.d.ts",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  },
  "files": [
    "dist"
  ],
  "author": "Alex Wei<https://github.com/alex8088>",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/alex8088/electron-toolkit.git",
    "directory": "packages/preload"
  },
  "homepage": "https://github.com/alex8088/electron-toolkit/tree/master/packages/preload#readme",
  "peerDependencies": {
    "electron": ">=13.0.0"
  }
}MIT License

Copyright (c) 2022-present, Alex.Wei

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
'use strict';

const electron = require('electron');

const is = {
  dev: !electron.app.isPackaged
};

const platform = {
  isWindows: process.platform === "win32",
  isMacOS: process.platform === "darwin",
  isLinux: process.platform === "linux"
};

const electronApp = {
  setAppUserModelId(id) {
    if (platform.isWindows)
      electron.app.setAppUserModelId(is.dev ? process.execPath : id);
  },
  setAutoLaunch(auto) {
    if (platform.isLinux)
      return false;
    const isOpenAtLogin = () => {
      return electron.app.getLoginItemSettings().openAtLogin;
    };
    if (isOpenAtLogin() !== auto) {
      electron.app.setLoginItemSettings({ openAtLogin: auto });
      return isOpenAtLogin() === auto;
    } else {
      return true;
    }
  },
  skipProxy() {
    return electron.session.defaultSession.setProxy({ mode: "direct" });
  }
};

const optimizer = {
  watchWindowShortcuts(window, shortcutOptions) {
    if (!window)
      return;
    const { webContents } = window;
    const { escToCloseWindow = false, zoom = false } = shortcutOptions || {};
    webContents.on("before-input-event", (event, input) => {
      if (input.type === "keyDown") {
        if (!is.dev) {
          if (input.code === "KeyR" && (input.control || input.meta))
            event.preventDefault();
          if (input.code === "KeyI" && (input.alt && input.meta || input.control && input.shift)) {
            event.preventDefault();
          }
        } else {
          if (input.code === "F12") {
            if (webContents.isDevToolsOpened()) {
              webContents.closeDevTools();
            } else {
              webContents.openDevTools({ mode: "undocked" });
              console.log("Open dev tool...");
            }
          }
        }
        if (escToCloseWindow) {
          if (input.code === "Escape" && input.key !== "Process") {
            window.close();
            event.preventDefault();
          }
        }
        if (!zoom) {
          if (input.code === "Minus" && (input.control || input.meta))
            event.preventDefault();
          if (input.code === "Equal" && input.shift && (input.control || input.meta))
            event.preventDefault();
        }
      }
    });
  },
  registerFramelessWindowIpc() {
    electron.ipcMain.on("win:invoke", (event, action) => {
      const win = electron.BrowserWindow.fromWebContents(event.sender);
      if (win) {
        if (action === "show") {
          win.show();
        } else if (action === "showInactive") {
          win.showInactive();
        } else if (action === "min") {
          win.minimize();
        } else if (action === "max") {
          const isMaximized = win.isMaximized();
          if (isMaximized) {
            win.unmaximize();
          } else {
            win.maximize();
          }
        } else if (action === "close") {
          win.close();
        }
      }
    });
  }
};

exports.electronApp = electronApp;
exports.is = is;
exports.optimizer = optimizer;
exports.platform = platform;
import { BrowserWindow } from 'electron';

interface Is {
    dev: boolean;
}
declare const is: Is;

interface Platform {
    isWindows: boolean;
    isMacOS: boolean;
    isLinux: boolean;
}
declare const platform: Platform;

interface ElectronApp {
    /**
     * Changes the Application User Model ID to id.
     *
     * The `id` is used only when the applcation is packaged. otherwise use the
     * `process.execPath` value as id.
     *
     * see https://www.electronjs.org/docs/latest/tutorial/notifications#windows
     * @platform — win32
     */
    setAppUserModelId: (id: string) => void;
    /**
     * Whether the call succeeded.
     *
     * Set the app open at login or not.
     *
     *  **Note:** `false` always on Linux.
     * @platform — darwin,win32
     */
    setAutoLaunch: (auto: boolean) => boolean;
    /**
     * Skip proxy for Electron app.
     */
    skipProxy: () => Promise<void>;
}
declare const electronApp: ElectronApp;

type shortcutOptions = {
    /**
     * Use `ESC` key to close window, default `false`.
     */
    escToCloseWindow?: boolean;
    /**
     * Zoom in (`Minus + CommandOrControl`) or zoom out(`Equal + Shift + CommandOrControl`), default `false`.
     */
    zoom?: boolean;
};
interface Optimizer {
    /**
     * Default open or close DevTools by `F12` in development and
     * ignore `CommandOrControl + R` in production.
     *
     * Use `shortcutOptions` to control more shortcuts.
     */
    watchWindowShortcuts: (window: BrowserWindow, shortcutOptions?: shortcutOptions) => void;
    /**
     * If use a frameless window which hide the system's native window controls,
     * we may need to create custom window controls in HTML.
     *
     * The frameless window ipc allow the renderer process to control the
     * browser window.
     *
     * The ipc channel named `win:invoke`.
     *
     * For Example:
     *
     * ```
     * ipcRenderer.send('win:invoke', 'show')
     * ipcRenderer.send('win:invoke', 'showInactive')
     * ipcRenderer.send('win:invoke', 'min')
     * ipcRenderer.send('win:invoke', 'max')
     * ipcRenderer.send('win:invoke', 'close')
     * ```
     */
    registerFramelessWindowIpc: () => void;
}
declare const optimizer: Optimizer;

export { type ElectronApp, type Is, type Optimizer, type Platform, electronApp, is, optimizer, platform, type shortcutOptions };
import { BrowserWindow } from 'electron';

interface Is {
    dev: boolean;
}
declare const is: Is;

interface Platform {
    isWindows: boolean;
    isMacOS: boolean;
    isLinux: boolean;
}
declare const platform: Platform;

interface ElectronApp {
    /**
     * Changes the Application User Model ID to id.
     *
     * The `id` is used only when the applcation is packaged. otherwise use the
     * `process.execPath` value as id.
     *
     * see https://www.electronjs.org/docs/latest/tutorial/notifications#windows
     * @platform — win32
     */
    setAppUserModelId: (id: string) => void;
    /**
     * Whether the call succeeded.
     *
     * Set the app open at login or not.
     *
     *  **Note:** `false` always on Linux.
     * @platform — darwin,win32
     */
    setAutoLaunch: (auto: boolean) => boolean;
    /**
     * Skip proxy for Electron app.
     */
    skipProxy: () => Promise<void>;
}
declare const electronApp: ElectronApp;

type shortcutOptions = {
    /**
     * Use `ESC` key to close window, default `false`.
     */
    escToCloseWindow?: boolean;
    /**
     * Zoom in (`Minus + CommandOrControl`) or zoom out(`Equal + Shift + CommandOrControl`), default `false`.
     */
    zoom?: boolean;
};
interface Optimizer {
    /**
     * Default open or close DevTools by `F12` in development and
     * ignore `CommandOrControl + R` in production.
     *
     * Use `shortcutOptions` to control more shortcuts.
     */
    watchWindowShortcuts: (window: BrowserWindow, shortcutOptions?: shortcutOptions) => void;
    /**
     * If use a frameless window which hide the system's native window controls,
     * we may need to create custom window controls in HTML.
     *
     * The frameless window ipc allow the renderer process to control the
     * browser window.
     *
     * The ipc channel named `win:invoke`.
     *
     * For Example:
     *
     * ```
     * ipcRenderer.send('win:invoke', 'show')
     * ipcRenderer.send('win:invoke', 'showInactive')
     * ipcRenderer.send('win:invoke', 'min')
     * ipcRenderer.send('win:invoke', 'max')
     * ipcRenderer.send('win:invoke', 'close')
     * ```
     */
    registerFramelessWindowIpc: () => void;
}
declare const optimizer: Optimizer;

export { type ElectronApp, type Is, type Optimizer, type Platform, electronApp, is, optimizer, platform, type shortcutOptions };
import { app, session, ipcMain, BrowserWindow } from 'electron';

const is = {
  dev: !app.isPackaged
};

const platform = {
  isWindows: process.platform === "win32",
  isMacOS: process.platform === "darwin",
  isLinux: process.platform === "linux"
};

const electronApp = {
  setAppUserModelId(id) {
    if (platform.isWindows)
      app.setAppUserModelId(is.dev ? process.execPath : id);
  },
  setAutoLaunch(auto) {
    if (platform.isLinux)
      return false;
    const isOpenAtLogin = () => {
      return app.getLoginItemSettings().openAtLogin;
    };
    if (isOpenAtLogin() !== auto) {
      app.setLoginItemSettings({ openAtLogin: auto });
      return isOpenAtLogin() === auto;
    } else {
      return true;
    }
  },
  skipProxy() {
    return session.defaultSession.setProxy({ mode: "direct" });
  }
};

const optimizer = {
  watchWindowShortcuts(window, shortcutOptions) {
    if (!window)
      return;
    const { webContents } = window;
    const { escToCloseWindow = false, zoom = false } = shortcutOptions || {};
    webContents.on("before-input-event", (event, input) => {
      if (input.type === "keyDown") {
        if (!is.dev) {
          if (input.code === "KeyR" && (input.control || input.meta))
            event.preventDefault();
          if (input.code === "KeyI" && (input.alt && input.meta || input.control && input.shift)) {
            event.preventDefault();
          }
        } else {
          if (input.code === "F12") {
            if (webContents.isDevToolsOpened()) {
              webContents.closeDevTools();
            } else {
              webContents.openDevTools({ mode: "undocked" });
              console.log("Open dev tool...");
            }
          }
        }
        if (escToCloseWindow) {
          if (input.code === "Escape" && input.key !== "Process") {
            window.close();
            event.preventDefault();
          }
        }
        if (!zoom) {
          if (input.code === "Minus" && (input.control || input.meta))
            event.preventDefault();
          if (input.code === "Equal" && input.shift && (input.control || input.meta))
            event.preventDefault();
        }
      }
    });
  },
  registerFramelessWindowIpc() {
    ipcMain.on("win:invoke", (event, action) => {
      const win = BrowserWindow.fromWebContents(event.sender);
      if (win) {
        if (action === "show") {
          win.show();
        } else if (action === "showInactive") {
          win.showInactive();
        } else if (action === "min") {
          win.minimize();
        } else if (action === "max") {
          const isMaximized = win.isMaximized();
          if (isMaximized) {
            win.unmaximize();
          } else {
            win.maximize();
          }
        } else if (action === "close") {
          win.close();
        }
      }
    });
  }
};

export { electronApp, is, optimizer, platform };
{
  "name": "@electron-toolkit/utils",
  "version": "4.0.0",
  "description": "Utils for Electron main process.",
  "main": "dist/index.cjs",
  "module": "dist/index.mjs",
  "types": "dist/index.d.ts",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  },
  "files": [
    "dist"
  ],
  "author": "Alex Wei<https://github.com/alex8088>",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/alex8088/electron-toolkit.git",
    "directory": "packages/utils"
  },
  "homepage": "https://github.com/alex8088/electron-toolkit/tree/master/packages/utils#readme",
  "peerDependencies": {
    "electron": ">=13.0.0"
  }
}A. HISTORY OF THE SOFTWARE
==========================

Python was created in the early 1990s by Guido van Rossum at Stichting
Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
as a successor of a language called ABC.  Guido remains Python's
principal author, although it includes many contributions from others.

In 1995, Guido continued his work on Python at the Corporation for
National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
in Reston, Virginia where he released several versions of the
software.

In May 2000, Guido and the Python core development team moved to
BeOpen.com to form the BeOpen PythonLabs team.  In October of the same
year, the PythonLabs team moved to Digital Creations, which became
Zope Corporation.  In 2001, the Python Software Foundation (PSF, see
https://www.python.org/psf/) was formed, a non-profit organization
created specifically to own Python-related Intellectual Property.
Zope Corporation was a sponsoring member of the PSF.

All Python releases are Open Source (see http://www.opensource.org for
the Open Source Definition).  Historically, most, but not all, Python
releases have also been GPL-compatible; the table below summarizes
the various releases.

    Release         Derived     Year        Owner       GPL-
                    from                                compatible? (1)

    0.9.0 thru 1.2              1991-1995   CWI         yes
    1.3 thru 1.5.2  1.2         1995-1999   CNRI        yes
    1.6             1.5.2       2000        CNRI        no
    2.0             1.6         2000        BeOpen.com  no
    1.6.1           1.6         2001        CNRI        yes (2)
    2.1             2.0+1.6.1   2001        PSF         no
    2.0.1           2.0+1.6.1   2001        PSF         yes
    2.1.1           2.1+2.0.1   2001        PSF         yes
    2.1.2           2.1.1       2002        PSF         yes
    2.1.3           2.1.2       2002        PSF         yes
    2.2 and above   2.1.1       2001-now    PSF         yes

Footnotes:

(1) GPL-compatible doesn't mean that we're distributing Python under
    the GPL.  All Python licenses, unlike the GPL, let you distribute
    a modified version without making your changes open source.  The
    GPL-compatible licenses make it possible to combine Python with
    other software that is released under the GPL; the others don't.

(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
    because its license has a choice of law clause.  According to
    CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
    is "not incompatible" with the GPL.

Thanks to the many outside volunteers who have worked under Guido's
direction to make these releases possible.


B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
===============================================================

PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
--------------------------------------------

1. This LICENSE AGREEMENT is between the Python Software Foundation
("PSF"), and the Individual or Organization ("Licensee") accessing and
otherwise using this software ("Python") in source or binary form and
its associated documentation.

2. Subject to the terms and conditions of this License Agreement, PSF hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation;
All Rights Reserved" are retained in Python alone or in any derivative version
prepared by Licensee.

3. In the event Licensee prepares a derivative work that is based on
or incorporates Python or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python.

4. PSF is making Python available to Licensee on an "AS IS"
basis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.

5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.

6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.

7. Nothing in this License Agreement shall be deemed to create any
relationship of agency, partnership, or joint venture between PSF and
Licensee.  This License Agreement does not grant permission to use PSF
trademarks or trade name in a trademark sense to endorse or promote
products or services of Licensee, or any third party.

8. By copying, installing or otherwise using Python, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.


BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
-------------------------------------------

BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1

1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
Individual or Organization ("Licensee") accessing and otherwise using
this software in source or binary form and its associated
documentation ("the Software").

2. Subject to the terms and conditions of this BeOpen Python License
Agreement, BeOpen hereby grants Licensee a non-exclusive,
royalty-free, world-wide license to reproduce, analyze, test, perform
and/or display publicly, prepare derivative works, distribute, and
otherwise use the Software alone or in any derivative version,
provided, however, that the BeOpen Python License is retained in the
Software, alone or in any derivative version prepared by Licensee.

3. BeOpen is making the Software available to Licensee on an "AS IS"
basis.  BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.

4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.

5. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.

6. This License Agreement shall be governed by and interpreted in all
respects by the law of the State of California, excluding conflict of
law provisions.  Nothing in this License Agreement shall be deemed to
create any relationship of agency, partnership, or joint venture
between BeOpen and Licensee.  This License Agreement does not grant
permission to use BeOpen trademarks or trade names in a trademark
sense to endorse or promote products or services of Licensee, or any
third party.  As an exception, the "BeOpen Python" logos available at
http://www.pythonlabs.com/logos.html may be used according to the
permissions granted on that web page.

7. By copying, installing or otherwise using the software, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.


CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
---------------------------------------

1. This LICENSE AGREEMENT is between the Corporation for National
Research Initiatives, having an office at 1895 Preston White Drive,
Reston, VA 20191 ("CNRI"), and the Individual or Organization
("Licensee") accessing and otherwise using Python 1.6.1 software in
source or binary form and its associated documentation.

2. Subject to the terms and conditions of this License Agreement, CNRI
hereby grants Licensee a nonexclusive, royalty-free, world-wide
license to reproduce, analyze, test, perform and/or display publicly,
prepare derivative works, distribute, and otherwise use Python 1.6.1
alone or in any derivative version, provided, however, that CNRI's
License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
1995-2001 Corporation for National Research Initiatives; All Rights
Reserved" are retained in Python 1.6.1 alone or in any derivative
version prepared by Licensee.  Alternately, in lieu of CNRI's License
Agreement, Licensee may substitute the following text (omitting the
quotes): "Python 1.6.1 is made available subject to the terms and
conditions in CNRI's License Agreement.  This Agreement together with
Python 1.6.1 may be located on the Internet using the following
unique, persistent identifier (known as a handle): 1895.22/1013.  This
Agreement may also be obtained from a proxy server on the Internet
using the following URL: http://hdl.handle.net/1895.22/1013".

3. In the event Licensee prepares a derivative work that is based on
or incorporates Python 1.6.1 or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python 1.6.1.

4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
basis.  CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.

5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.

6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.

7. This License Agreement shall be governed by the federal
intellectual property law of the United States, including without
limitation the federal copyright law, and, to the extent such
U.S. federal law does not apply, by the law of the Commonwealth of
Virginia, excluding Virginia's conflict of law provisions.
Notwithstanding the foregoing, with regard to derivative works based
on Python 1.6.1 that incorporate non-separable material that was
previously distributed under the GNU General Public License (GPL), the
law of the Commonwealth of Virginia shall govern this License
Agreement only as to issues arising under or with respect to
Paragraphs 4, 5, and 7 of this License Agreement.  Nothing in this
License Agreement shall be deemed to create any relationship of
agency, partnership, or joint venture between CNRI and Licensee.  This
License Agreement does not grant permission to use CNRI trademarks or
trade name in a trademark sense to endorse or promote products or
services of Licensee, or any third party.

8. By clicking on the "ACCEPT" button where indicated, or by copying,
installing or otherwise using Python 1.6.1, Licensee agrees to be
bound by the terms and conditions of this License Agreement.

        ACCEPT


CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
--------------------------------------------------

Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
The Netherlands.  All rights reserved.

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.

STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// Port of python's argparse module, version 3.9.0:
// https://github.com/python/cpython/blob/v3.9.0rc1/Lib/argparse.py

'use strict'

// Copyright (C) 2010-2020 Python Software Foundation.
// Copyright (C) 2020 argparse.js authors

/*
 * Command-line parsing library
 *
 * This module is an optparse-inspired command-line parsing library that:
 *
 *     - handles both optional and positional arguments
 *     - produces highly informative usage messages
 *     - supports parsers that dispatch to sub-parsers
 *
 * The following is a simple usage example that sums integers from the
 * command-line and writes the result to a file::
 *
 *     parser = argparse.ArgumentParser(
 *         description='sum the integers at the command line')
 *     parser.add_argument(
 *         'integers', metavar='int', nargs='+', type=int,
 *         help='an integer to be summed')
 *     parser.add_argument(
 *         '--log', default=sys.stdout, type=argparse.FileType('w'),
 *         help='the file where the sum should be written')
 *     args = parser.parse_args()
 *     args.log.write('%s' % sum(args.integers))
 *     args.log.close()
 *
 * The module contains the following public classes:
 *
 *     - ArgumentParser -- The main entry point for command-line parsing. As the
 *         example above shows, the add_argument() method is used to populate
 *         the parser with actions for optional and positional arguments. Then
 *         the parse_args() method is invoked to convert the args at the
 *         command-line into an object with attributes.
 *
 *     - ArgumentError -- The exception raised by ArgumentParser objects when
 *         there are errors with the parser's actions. Errors raised while
 *         parsing the command-line are caught by ArgumentParser and emitted
 *         as command-line messages.
 *
 *     - FileType -- A factory for defining types of files to be created. As the
 *         example above shows, instances of FileType are typically passed as
 *         the type= argument of add_argument() calls.
 *
 *     - Action -- The base class for parser actions. Typically actions are
 *         selected by passing strings like 'store_true' or 'append_const' to
 *         the action= argument of add_argument(). However, for greater
 *         customization of ArgumentParser actions, subclasses of Action may
 *         be defined and passed as the action= argument.
 *
 *     - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter,
 *         ArgumentDefaultsHelpFormatter -- Formatter classes which
 *         may be passed as the formatter_class= argument to the
 *         ArgumentParser constructor. HelpFormatter is the default,
 *         RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser
 *         not to change the formatting for help text, and
 *         ArgumentDefaultsHelpFormatter adds information about argument defaults
 *         to the help.
 *
 * All other classes in this module are considered implementation details.
 * (Also note that HelpFormatter and RawDescriptionHelpFormatter are only
 * considered public as object names -- the API of the formatter objects is
 * still considered an implementation detail.)
 */

const SUPPRESS = '==SUPPRESS=='

const OPTIONAL = '?'
const ZERO_OR_MORE = '*'
const ONE_OR_MORE = '+'
const PARSER = 'A...'
const REMAINDER = '...'
const _UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args'


// ==================================
// Utility functions used for porting
// ==================================
const assert = require('assert')
const util = require('util')
const fs = require('fs')
const sub = require('./lib/sub')
const path = require('path')
const repr = util.inspect

function get_argv() {
    // omit first argument (which is assumed to be interpreter - `node`, `coffee`, `ts-node`, etc.)
    return process.argv.slice(1)
}

function get_terminal_size() {
    return {
        columns: +process.env.COLUMNS || process.stdout.columns || 80
    }
}

function hasattr(object, name) {
    return Object.prototype.hasOwnProperty.call(object, name)
}

function getattr(object, name, value) {
    return hasattr(object, name) ? object[name] : value
}

function setattr(object, name, value) {
    object[name] = value
}

function setdefault(object, name, value) {
    if (!hasattr(object, name)) object[name] = value
    return object[name]
}

function delattr(object, name) {
    delete object[name]
}

function range(from, to, step=1) {
    // range(10) is equivalent to range(0, 10)
    if (arguments.length === 1) [ to, from ] = [ from, 0 ]
    if (typeof from !== 'number' || typeof to !== 'number' || typeof step !== 'number') {
        throw new TypeError('argument cannot be interpreted as an integer')
    }
    if (step === 0) throw new TypeError('range() arg 3 must not be zero')

    let result = []
    if (step > 0) {
        for (let i = from; i < to; i += step) result.push(i)
    } else {
        for (let i = from; i > to; i += step) result.push(i)
    }
    return result
}

function splitlines(str, keepends = false) {
    let result
    if (!keepends) {
        result = str.split(/\r\n|[\n\r\v\f\x1c\x1d\x1e\x85\u2028\u2029]/)
    } else {
        result = []
        let parts = str.split(/(\r\n|[\n\r\v\f\x1c\x1d\x1e\x85\u2028\u2029])/)
        for (let i = 0; i < parts.length; i += 2) {
            result.push(parts[i] + (i + 1 < parts.length ? parts[i + 1] : ''))
        }
    }
    if (!result[result.length - 1]) result.pop()
    return result
}

function _string_lstrip(string, prefix_chars) {
    let idx = 0
    while (idx < string.length && prefix_chars.includes(string[idx])) idx++
    return idx ? string.slice(idx) : string
}

function _string_split(string, sep, maxsplit) {
    let result = string.split(sep)
    if (result.length > maxsplit) {
        result = result.slice(0, maxsplit).concat([ result.slice(maxsplit).join(sep) ])
    }
    return result
}

function _array_equal(array1, array2) {
    if (array1.length !== array2.length) return false
    for (let i = 0; i < array1.length; i++) {
        if (array1[i] !== array2[i]) return false
    }
    return true
}

function _array_remove(array, item) {
    let idx = array.indexOf(item)
    if (idx === -1) throw new TypeError(sub('%r not in list', item))
    array.splice(idx, 1)
}

// normalize choices to array;
// this isn't required in python because `in` and `map` operators work with anything,
// but in js dealing with multiple types here is too clunky
function _choices_to_array(choices) {
    if (choices === undefined) {
        return []
    } else if (Array.isArray(choices)) {
        return choices
    } else if (choices !== null && typeof choices[Symbol.iterator] === 'function') {
        return Array.from(choices)
    } else if (typeof choices === 'object' && choices !== null) {
        return Object.keys(choices)
    } else {
        throw new Error(sub('invalid choices value: %r', choices))
    }
}

// decorator that allows a class to be called without new
function _callable(cls) {
    let result = { // object is needed for inferred class name
        [cls.name]: function (...args) {
            let this_class = new.target === result || !new.target
            return Reflect.construct(cls, args, this_class ? cls : new.target)
        }
    }
    result[cls.name].prototype = cls.prototype
    // fix default tag for toString, e.g. [object Action] instead of [object Object]
    cls.prototype[Symbol.toStringTag] = cls.name
    return result[cls.name]
}

function _alias(object, from, to) {
    try {
        let name = object.constructor.name
        Object.defineProperty(object, from, {
            value: util.deprecate(object[to], sub('%s.%s() is renamed to %s.%s()',
                name, from, name, to)),
            enumerable: false
        })
    } catch {}
}

// decorator that allows snake_case class methods to be called with camelCase and vice versa
function _camelcase_alias(_class) {
    for (let name of Object.getOwnPropertyNames(_class.prototype)) {
        let camelcase = name.replace(/\w_[a-z]/g, s => s[0] + s[2].toUpperCase())
        if (camelcase !== name) _alias(_class.prototype, camelcase, name)
    }
    return _class
}

function _to_legacy_name(key) {
    key = key.replace(/\w_[a-z]/g, s => s[0] + s[2].toUpperCase())
    if (key === 'default') key = 'defaultValue'
    if (key === 'const') key = 'constant'
    return key
}

function _to_new_name(key) {
    if (key === 'defaultValue') key = 'default'
    if (key === 'constant') key = 'const'
    key = key.replace(/[A-Z]/g, c => '_' + c.toLowerCase())
    return key
}

// parse options
let no_default = Symbol('no_default_value')
function _parse_opts(args, descriptor) {
    function get_name() {
        let stack = new Error().stack.split('\n')
            .map(x => x.match(/^    at (.*) \(.*\)$/))
            .filter(Boolean)
            .map(m => m[1])
            .map(fn => fn.match(/[^ .]*$/)[0])

        if (stack.length && stack[0] === get_name.name) stack.shift()
        if (stack.length && stack[0] === _parse_opts.name) stack.shift()
        return stack.length ? stack[0] : ''
    }

    args = Array.from(args)
    let kwargs = {}
    let result = []
    let last_opt = args.length && args[args.length - 1]

    if (typeof last_opt === 'object' && last_opt !== null && !Array.isArray(last_opt) &&
        (!last_opt.constructor || last_opt.constructor.name === 'Object')) {
        kwargs = Object.assign({}, args.pop())
    }

    // LEGACY (v1 compatibility): camelcase
    let renames = []
    for (let key of Object.keys(descriptor)) {
        let old_name = _to_legacy_name(key)
        if (old_name !== key && (old_name in kwargs)) {
            if (key in kwargs) {
                // default and defaultValue specified at the same time, happens often in old tests
                //throw new TypeError(sub('%s() got multiple values for argument %r', get_name(), key))
            } else {
                kwargs[key] = kwargs[old_name]
            }
            renames.push([ old_name, key ])
            delete kwargs[old_name]
        }
    }
    if (renames.length) {
        let name = get_name()
        deprecate('camelcase_' + name, sub('%s(): following options are renamed: %s',
            name, renames.map(([ a, b ]) => sub('%r -> %r', a, b))))
    }
    // end

    let missing_positionals = []
    let positional_count = args.length

    for (let [ key, def ] of Object.entries(descriptor)) {
        if (key[0] === '*') {
            if (key.length > 0 && key[1] === '*') {
                // LEGACY (v1 compatibility): camelcase
                let renames = []
                for (let key of Object.keys(kwargs)) {
                    let new_name = _to_new_name(key)
                    if (new_name !== key && (key in kwargs)) {
                        if (new_name in kwargs) {
                            // default and defaultValue specified at the same time, happens often in old tests
                            //throw new TypeError(sub('%s() got multiple values for argument %r', get_name(), new_name))
                        } else {
                            kwargs[new_name] = kwargs[key]
                        }
                        renames.push([ key, new_name ])
                        delete kwargs[key]
                    }
                }
                if (renames.length) {
                    let name = get_name()
                    deprecate('camelcase_' + name, sub('%s(): following options are renamed: %s',
                        name, renames.map(([ a, b ]) => sub('%r -> %r', a, b))))
                }
                // end
                result.push(kwargs)
                kwargs = {}
            } else {
                result.push(args)
                args = []
            }
        } else if (key in kwargs && args.length > 0) {
            throw new TypeError(sub('%s() got multiple values for argument %r', get_name(), key))
        } else if (key in kwargs) {
            result.push(kwargs[key])
            delete kwargs[key]
        } else if (args.length > 0) {
            result.push(args.shift())
        } else if (def !== no_default) {
            result.push(def)
        } else {
            missing_positionals.push(key)
        }
    }

    if (Object.keys(kwargs).length) {
        throw new TypeError(sub('%s() got an unexpected keyword argument %r',
            get_name(), Object.keys(kwargs)[0]))
    }

    if (args.length) {
        let from = Object.entries(descriptor).filter(([ k, v ]) => k[0] !== '*' && v !== no_default).length
        let to = Object.entries(descriptor).filter(([ k ]) => k[0] !== '*').length
        throw new TypeError(sub('%s() takes %s positional argument%s but %s %s given',
            get_name(),
            from === to ? sub('from %s to %s', from, to) : to,
            from === to && to === 1 ? '' : 's',
            positional_count,
            positional_count === 1 ? 'was' : 'were'))
    }

    if (missing_positionals.length) {
        let strs = missing_positionals.map(repr)
        if (strs.length > 1) strs[strs.length - 1] = 'and ' + strs[strs.length - 1]
        let str_joined = strs.join(strs.length === 2 ? '' : ', ')
        throw new TypeError(sub('%s() missing %i required positional argument%s: %s',
            get_name(), strs.length, strs.length === 1 ? '' : 's', str_joined))
    }

    return result
}

let _deprecations = {}
function deprecate(id, string) {
    _deprecations[id] = _deprecations[id] || util.deprecate(() => {}, string)
    _deprecations[id]()
}


// =============================
// Utility functions and classes
// =============================
function _AttributeHolder(cls = Object) {
    /*
     *  Abstract base class that provides __repr__.
     *
     *  The __repr__ method returns a string in the format::
     *      ClassName(attr=name, attr=name, ...)
     *  The attributes are determined either by a class-level attribute,
     *  '_kwarg_names', or by inspecting the instance __dict__.
     */

    return class _AttributeHolder extends cls {
        [util.inspect.custom]() {
            let type_name = this.constructor.name
            let arg_strings = []
            let star_args = {}
            for (let arg of this._get_args()) {
                arg_strings.push(repr(arg))
            }
            for (let [ name, value ] of this._get_kwargs()) {
                if (/^[a-z_][a-z0-9_$]*$/i.test(name)) {
                    arg_strings.push(sub('%s=%r', name, value))
                } else {
                    star_args[name] = value
                }
            }
            if (Object.keys(star_args).length) {
                arg_strings.push(sub('**%s', repr(star_args)))
            }
            return sub('%s(%s)', type_name, arg_strings.join(', '))
        }

        toString() {
            return this[util.inspect.custom]()
        }

        _get_kwargs() {
            return Object.entries(this)
        }

        _get_args() {
            return []
        }
    }
}


function _copy_items(items) {
    if (items === undefined) {
        return []
    }
    return items.slice(0)
}


// ===============
// Formatting Help
// ===============
const HelpFormatter = _camelcase_alias(_callable(class HelpFormatter {
    /*
     *  Formatter for generating usage messages and argument help strings.
     *
     *  Only the name of this class is considered a public API. All the methods
     *  provided by the class are considered an implementation detail.
     */

    constructor() {
        let [
            prog,
            indent_increment,
            max_help_position,
            width
        ] = _parse_opts(arguments, {
            prog: no_default,
            indent_increment: 2,
            max_help_position: 24,
            width: undefined
        })

        // default setting for width
        if (width === undefined) {
            width = get_terminal_size().columns
            width -= 2
        }

        this._prog = prog
        this._indent_increment = indent_increment
        this._max_help_position = Math.min(max_help_position,
                                      Math.max(width - 20, indent_increment * 2))
        this._width = width

        this._current_indent = 0
        this._level = 0
        this._action_max_length = 0

        this._root_section = this._Section(this, undefined)
        this._current_section = this._root_section

        this._whitespace_matcher = /[ \t\n\r\f\v]+/g // equivalent to python /\s+/ with ASCII flag
        this._long_break_matcher = /\n\n\n+/g
    }

    // ===============================
    // Section and indentation methods
    // ===============================
    _indent() {
        this._current_indent += this._indent_increment
        this._level += 1
    }

    _dedent() {
        this._current_indent -= this._indent_increment
        assert(this._current_indent >= 0, 'Indent decreased below 0.')
        this._level -= 1
    }

    _add_item(func, args) {
        this._current_section.items.push([ func, args ])
    }

    // ========================
    // Message building methods
    // ========================
    start_section(heading) {
        this._indent()
        let section = this._Section(this, this._current_section, heading)
        this._add_item(section.format_help.bind(section), [])
        this._current_section = section
    }

    end_section() {
        this._current_section = this._current_section.parent
        this._dedent()
    }

    add_text(text) {
        if (text !== SUPPRESS && text !== undefined) {
            this._add_item(this._format_text.bind(this), [text])
        }
    }

    add_usage(usage, actions, groups, prefix = undefined) {
        if (usage !== SUPPRESS) {
            let args = [ usage, actions, groups, prefix ]
            this._add_item(this._format_usage.bind(this), args)
        }
    }

    add_argument(action) {
        if (action.help !== SUPPRESS) {

            // find all invocations
            let invocations = [this._format_action_invocation(action)]
            for (let subaction of this._iter_indented_subactions(action)) {
                invocations.push(this._format_action_invocation(subaction))
            }

            // update the maximum item length
            let invocation_length = Math.max(...invocations.map(invocation => invocation.length))
            let action_length = invocation_length + this._current_indent
            this._action_max_length = Math.max(this._action_max_length,
                                               action_length)

            // add the item to the list
            this._add_item(this._format_action.bind(this), [action])
        }
    }

    add_arguments(actions) {
        for (let action of actions) {
            this.add_argument(action)
        }
    }

    // =======================
    // Help-formatting methods
    // =======================
    format_help() {
        let help = this._root_section.format_help()
        if (help) {
            help = help.replace(this._long_break_matcher, '\n\n')
            help = help.replace(/^\n+|\n+$/g, '') + '\n'
        }
        return help
    }

    _join_parts(part_strings) {
        return part_strings.filter(part => part && part !== SUPPRESS).join('')
    }

    _format_usage(usage, actions, groups, prefix) {
        if (prefix === undefined) {
            prefix = 'usage: '
        }

        // if usage is specified, use that
        if (usage !== undefined) {
            usage = sub(usage, { prog: this._prog })

        // if no optionals or positionals are available, usage is just prog
        } else if (usage === undefined && !actions.length) {
            usage = sub('%(prog)s', { prog: this._prog })

        // if optionals and positionals are available, calculate usage
        } else if (usage === undefined) {
            let prog = sub('%(prog)s', { prog: this._prog })

            // split optionals from positionals
            let optionals = []
            let positionals = []
            for (let action of actions) {
                if (action.option_strings.length) {
                    optionals.push(action)
                } else {
                    positionals.push(action)
                }
            }

            // build full usage string
            let action_usage = this._format_actions_usage([].concat(optionals).concat(positionals), groups)
            usage = [ prog, action_usage ].map(String).join(' ')

            // wrap the usage parts if it's too long
            let text_width = this._width - this._current_indent
            if (prefix.length + usage.length > text_width) {

                // break usage into wrappable parts
                let part_regexp = /\(.*?\)+(?=\s|$)|\[.*?\]+(?=\s|$)|\S+/g
                let opt_usage = this._format_actions_usage(optionals, groups)
                let pos_usage = this._format_actions_usage(positionals, groups)
                let opt_parts = opt_usage.match(part_regexp) || []
                let pos_parts = pos_usage.match(part_regexp) || []
                assert(opt_parts.join(' ') === opt_usage)
                assert(pos_parts.join(' ') === pos_usage)

                // helper for wrapping lines
                let get_lines = (parts, indent, prefix = undefined) => {
                    let lines = []
                    let line = []
                    let line_len
                    if (prefix !== undefined) {
                        line_len = prefix.length - 1
                    } else {
                        line_len = indent.length - 1
                    }
                    for (let part of parts) {
                        if (line_len + 1 + part.length > text_width && line) {
                            lines.push(indent + line.join(' '))
                            line = []
                            line_len = indent.length - 1
                        }
                        line.push(part)
                        line_len += part.length + 1
                    }
                    if (line.length) {
                        lines.push(indent + line.join(' '))
                    }
                    if (prefix !== undefined) {
                        lines[0] = lines[0].slice(indent.length)
                    }
                    return lines
                }

                let lines

                // if prog is short, follow it with optionals or positionals
                if (prefix.length + prog.length <= 0.75 * text_width) {
                    let indent = ' '.repeat(prefix.length + prog.length + 1)
                    if (opt_parts.length) {
                        lines = get_lines([prog].concat(opt_parts), indent, prefix)
                        lines = lines.concat(get_lines(pos_parts, indent))
                    } else if (pos_parts.length) {
                        lines = get_lines([prog].concat(pos_parts), indent, prefix)
                    } else {
                        lines = [prog]
                    }

                // if prog is long, put it on its own line
                } else {
                    let indent = ' '.repeat(prefix.length)
                    let parts = [].concat(opt_parts).concat(pos_parts)
                    lines = get_lines(parts, indent)
                    if (lines.length > 1) {
                        lines = []
                        lines = lines.concat(get_lines(opt_parts, indent))
                        lines = lines.concat(get_lines(pos_parts, indent))
                    }
                    lines = [prog].concat(lines)
                }

                // join lines into usage
                usage = lines.join('\n')
            }
        }

        // prefix with 'usage:'
        return sub('%s%s\n\n', prefix, usage)
    }

    _format_actions_usage(actions, groups) {
        // find group indices and identify actions in groups
        let group_actions = new Set()
        let inserts = {}
        for (let group of groups) {
            let start = actions.indexOf(group._group_actions[0])
            if (start === -1) {
                continue
            } else {
                let end = start + group._group_actions.length
                if (_array_equal(actions.slice(start, end), group._group_actions)) {
                    for (let action of group._group_actions) {
                        group_actions.add(action)
                    }
                    if (!group.required) {
                        if (start in inserts) {
                            inserts[start] += ' ['
                        } else {
                            inserts[start] = '['
                        }
                        if (end in inserts) {
                            inserts[end] += ']'
                        } else {
                            inserts[end] = ']'
                        }
                    } else {
                        if (start in inserts) {
                            inserts[start] += ' ('
                        } else {
                            inserts[start] = '('
                        }
                        if (end in inserts) {
                            inserts[end] += ')'
                        } else {
                            inserts[end] = ')'
                        }
                    }
                    for (let i of range(start + 1, end)) {
                        inserts[i] = '|'
                    }
                }
            }
        }

        // collect all actions format strings
        let parts = []
        for (let [ i, action ] of Object.entries(actions)) {

            // suppressed arguments are marked with None
            // remove | separators for suppressed arguments
            if (action.help === SUPPRESS) {
                parts.push(undefined)
                if (inserts[+i] === '|') {
                    delete inserts[+i]
                } else if (inserts[+i + 1] === '|') {
                    delete inserts[+i + 1]
                }

            // produce all arg strings
            } else if (!action.option_strings.length) {
                let default_value = this._get_default_metavar_for_positional(action)
                let part = this._format_args(action, default_value)

                // if it's in a group, strip the outer []
                if (group_actions.has(action)) {
                    if (part[0] === '[' && part[part.length - 1] === ']') {
                        part = part.slice(1, -1)
                    }
                }

                // add the action string to the list
                parts.push(part)

            // produce the first way to invoke the option in brackets
            } else {
                let option_string = action.option_strings[0]
                let part

                // if the Optional doesn't take a value, format is:
                //    -s or --long
                if (action.nargs === 0) {
                    part = action.format_usage()

                // if the Optional takes a value, format is:
                //    -s ARGS or --long ARGS
                } else {
                    let default_value = this._get_default_metavar_for_optional(action)
                    let args_string = this._format_args(action, default_value)
                    part = sub('%s %s', option_string, args_string)
                }

                // make it look optional if it's not required or in a group
                if (!action.required && !group_actions.has(action)) {
                    part = sub('[%s]', part)
                }

                // add the action string to the list
                parts.push(part)
            }
        }

        // insert things at the necessary indices
        for (let i of Object.keys(inserts).map(Number).sort((a, b) => b - a)) {
            parts.splice(+i, 0, inserts[+i])
        }

        // join all the action items with spaces
        let text = parts.filter(Boolean).join(' ')

        // clean up separators for mutually exclusive groups
        text = text.replace(/([\[(]) /g, '$1')
        text = text.replace(/ ([\])])/g, '$1')
        text = text.replace(/[\[(] *[\])]/g, '')
        text = text.replace(/\(([^|]*)\)/g, '$1', text)
        text = text.trim()

        // return the text
        return text
    }

    _format_text(text) {
        if (text.includes('%(prog)')) {
            text = sub(text, { prog: this._prog })
        }
        let text_width = Math.max(this._width - this._current_indent, 11)
        let indent = ' '.repeat(this._current_indent)
        return this._fill_text(text, text_width, indent) + '\n\n'
    }

    _format_action(action) {
        // determine the required width and the entry label
        let help_position = Math.min(this._action_max_length + 2,
                                     this._max_help_position)
        let help_width = Math.max(this._width - help_position, 11)
        let action_width = help_position - this._current_indent - 2
        let action_header = this._format_action_invocation(action)
        let indent_first

        // no help; start on same line and add a final newline
        if (!action.help) {
            let tup = [ this._current_indent, '', action_header ]
            action_header = sub('%*s%s\n', ...tup)

        // short action name; start on the same line and pad two spaces
        } else if (action_header.length <= action_width) {
            let tup = [ this._current_indent, '', action_width, action_header ]
            action_header = sub('%*s%-*s  ', ...tup)
            indent_first = 0

        // long action name; start on the next line
        } else {
            let tup = [ this._current_indent, '', action_header ]
            action_header = sub('%*s%s\n', ...tup)
            indent_first = help_position
        }

        // collect the pieces of the action help
        let parts = [action_header]

        // if there was help for the action, add lines of help text
        if (action.help) {
            let help_text = this._expand_help(action)
            let help_lines = this._split_lines(help_text, help_width)
            parts.push(sub('%*s%s\n', indent_first, '', help_lines[0]))
            for (let line of help_lines.slice(1)) {
                parts.push(sub('%*s%s\n', help_position, '', line))
            }

        // or add a newline if the description doesn't end with one
        } else if (!action_header.endsWith('\n')) {
            parts.push('\n')
        }

        // if there are any sub-actions, add their help as well
        for (let subaction of this._iter_indented_subactions(action)) {
            parts.push(this._format_action(subaction))
        }

        // return a single string
        return this._join_parts(parts)
    }

    _format_action_invocation(action) {
        if (!action.option_strings.length) {
            let default_value = this._get_default_metavar_for_positional(action)
            let metavar = this._metavar_formatter(action, default_value)(1)[0]
            return metavar

        } else {
            let parts = []

            // if the Optional doesn't take a value, format is:
            //    -s, --long
            if (action.nargs === 0) {
                parts = parts.concat(action.option_strings)

            // if the Optional takes a value, format is:
            //    -s ARGS, --long ARGS
            } else {
                let default_value = this._get_default_metavar_for_optional(action)
                let args_string = this._format_args(action, default_value)
                for (let option_string of action.option_strings) {
                    parts.push(sub('%s %s', option_string, args_string))
                }
            }

            return parts.join(', ')
        }
    }

    _metavar_formatter(action, default_metavar) {
        let result
        if (action.metavar !== undefined) {
            result = action.metavar
        } else if (action.choices !== undefined) {
            let choice_strs = _choices_to_array(action.choices).map(String)
            result = sub('{%s}', choice_strs.join(','))
        } else {
            result = default_metavar
        }

        function format(tuple_size) {
            if (Array.isArray(result)) {
                return result
            } else {
                return Array(tuple_size).fill(result)
            }
        }
        return format
    }

    _format_args(action, default_metavar) {
        let get_metavar = this._metavar_formatter(action, default_metavar)
        let result
        if (action.nargs === undefined) {
            result = sub('%s', ...get_metavar(1))
        } else if (action.nargs === OPTIONAL) {
            result = sub('[%s]', ...get_metavar(1))
        } else if (action.nargs === ZERO_OR_MORE) {
            let metavar = get_metavar(1)
            if (metavar.length === 2) {
                result = sub('[%s [%s ...]]', ...metavar)
            } else {
                result = sub('[%s ...]', ...metavar)
            }
        } else if (action.nargs === ONE_OR_MORE) {
            result = sub('%s [%s ...]', ...get_metavar(2))
        } else if (action.nargs === REMAINDER) {
            result = '...'
        } else if (action.nargs === PARSER) {
            result = sub('%s ...', ...get_metavar(1))
        } else if (action.nargs === SUPPRESS) {
            result = ''
        } else {
            let formats
            try {
                formats = range(action.nargs).map(() => '%s')
            } catch (err) {
                throw new TypeError('invalid nargs value')
            }
            result = sub(formats.join(' '), ...get_metavar(action.nargs))
        }
        return result
    }

    _expand_help(action) {
        let params = Object.assign({ prog: this._prog }, action)
        for (let name of Object.keys(params)) {
            if (params[name] === SUPPRESS) {
                delete params[name]
            }
        }
        for (let name of Object.keys(params)) {
            if (params[name] && params[name].name) {
                params[name] = params[name].name
            }
        }
        if (params.choices !== undefined) {
            let choices_str = _choices_to_array(params.choices).map(String).join(', ')
            params.choices = choices_str
        }
        // LEGACY (v1 compatibility): camelcase
        for (let key of Object.keys(params)) {
            let old_name = _to_legacy_name(key)
            if (old_name !== key) {
                params[old_name] = params[key]
            }
        }
        // end
        return sub(this._get_help_string(action), params)
    }

    * _iter_indented_subactions(action) {
        if (typeof action._get_subactions === 'function') {
            this._indent()
            yield* action._get_subactions()
            this._dedent()
        }
    }

    _split_lines(text, width) {
        text = text.replace(this._whitespace_matcher, ' ').trim()
        // The textwrap module is used only for formatting help.
        // Delay its import for speeding up the common usage of argparse.
        let textwrap = require('./lib/textwrap')
        return textwrap.wrap(text, { width })
    }

    _fill_text(text, width, indent) {
        text = text.replace(this._whitespace_matcher, ' ').trim()
        let textwrap = require('./lib/textwrap')
        return textwrap.fill(text, { width,
                                     initial_indent: indent,
                                     subsequent_indent: indent })
    }

    _get_help_string(action) {
        return action.help
    }

    _get_default_metavar_for_optional(action) {
        return action.dest.toUpperCase()
    }

    _get_default_metavar_for_positional(action) {
        return action.dest
    }
}))

HelpFormatter.prototype._Section = _callable(class _Section {

    constructor(formatter, parent, heading = undefined) {
        this.formatter = formatter
        this.parent = parent
        this.heading = heading
        this.items = []
    }

    format_help() {
        // format the indented section
        if (this.parent !== undefined) {
            this.formatter._indent()
        }
        let item_help = this.formatter._join_parts(this.items.map(([ func, args ]) => func.apply(null, args)))
        if (this.parent !== undefined) {
            this.formatter._dedent()
        }

        // return nothing if the section was empty
        if (!item_help) {
            return ''
        }

        // add the heading if the section was non-empty
        let heading
        if (this.heading !== SUPPRESS && this.heading !== undefined) {
            let current_indent = this.formatter._current_indent
            heading = sub('%*s%s:\n', current_indent, '', this.heading)
        } else {
            heading = ''
        }

        // join the section-initial newline, the heading and the help
        return this.formatter._join_parts(['\n', heading, item_help, '\n'])
    }
})


const RawDescriptionHelpFormatter = _camelcase_alias(_callable(class RawDescriptionHelpFormatter extends HelpFormatter {
    /*
     *  Help message formatter which retains any formatting in descriptions.
     *
     *  Only the name of this class is considered a public API. All the methods
     *  provided by the class are considered an implementation detail.
     */

    _fill_text(text, width, indent) {
        return splitlines(text, true).map(line => indent + line).join('')
    }
}))


const RawTextHelpFormatter = _camelcase_alias(_callable(class RawTextHelpFormatter extends RawDescriptionHelpFormatter {
    /*
     *  Help message formatter which retains formatting of all help text.
     *
     *  Only the name of this class is considered a public API. All the methods
     *  provided by the class are considered an implementation detail.
     */

    _split_lines(text/*, width*/) {
        return splitlines(text)
    }
}))


const ArgumentDefaultsHelpFormatter = _camelcase_alias(_callable(class ArgumentDefaultsHelpFormatter extends HelpFormatter {
    /*
     *  Help message formatter which adds default values to argument help.
     *
     *  Only the name of this class is considered a public API. All the methods
     *  provided by the class are considered an implementation detail.
     */

    _get_help_string(action) {
        let help = action.help
        // LEGACY (v1 compatibility): additional check for defaultValue needed
        if (!action.help.includes('%(default)') && !action.help.includes('%(defaultValue)')) {
            if (action.default !== SUPPRESS) {
                let defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
                if (action.option_strings.length || defaulting_nargs.includes(action.nargs)) {
                    help += ' (default: %(default)s)'
                }
            }
        }
        return help
    }
}))


const MetavarTypeHelpFormatter = _camelcase_alias(_callable(class MetavarTypeHelpFormatter extends HelpFormatter {
    /*
     *  Help message formatter which uses the argument 'type' as the default
     *  metavar value (instead of the argument 'dest')
     *
     *  Only the name of this class is considered a public API. All the methods
     *  provided by the class are considered an implementation detail.
     */

    _get_default_metavar_for_optional(action) {
        return typeof action.type === 'function' ? action.type.name : action.type
    }

    _get_default_metavar_for_positional(action) {
        return typeof action.type === 'function' ? action.type.name : action.type
    }
}))


// =====================
// Options and Arguments
// =====================
function _get_action_name(argument) {
    if (argument === undefined) {
        return undefined
    } else if (argument.option_strings.length) {
        return argument.option_strings.join('/')
    } else if (![ undefined, SUPPRESS ].includes(argument.metavar)) {
        return argument.metavar
    } else if (![ undefined, SUPPRESS ].includes(argument.dest)) {
        return argument.dest
    } else {
        return undefined
    }
}


const ArgumentError = _callable(class ArgumentError extends Error {
    /*
     *  An error from creating or using an argument (optional or positional).
     *
     *  The string value of this exception is the message, augmented with
     *  information about the argument that caused it.
     */

    constructor(argument, message) {
        super()
        this.name = 'ArgumentError'
        this._argument_name = _get_action_name(argument)
        this._message = message
        this.message = this.str()
    }

    str() {
        let format
        if (this._argument_name === undefined) {
            format = '%(message)s'
        } else {
            format = 'argument %(argument_name)s: %(message)s'
        }
        return sub(format, { message: this._message,
                             argument_name: this._argument_name })
    }
})


const ArgumentTypeError = _callable(class ArgumentTypeError extends Error {
    /*
     * An error from trying to convert a command line string to a type.
     */

    constructor(message) {
        super(message)
        this.name = 'ArgumentTypeError'
    }
})


// ==============
// Action classes
// ==============
const Action = _camelcase_alias(_callable(class Action extends _AttributeHolder(Function) {
    /*
     *  Information about how to convert command line strings to Python objects.
     *
     *  Action objects are used by an ArgumentParser to represent the information
     *  needed to parse a single argument from one or more strings from the
     *  command line. The keyword arguments to the Action constructor are also
     *  all attributes of Action instances.
     *
     *  Keyword Arguments:
     *
     *      - option_strings -- A list of command-line option strings which
     *          should be associated with this action.
     *
     *      - dest -- The name of the attribute to hold the created object(s)
     *
     *      - nargs -- The number of command-line arguments that should be
     *          consumed. By default, one argument will be consumed and a single
     *          value will be produced.  Other values include:
     *              - N (an integer) consumes N arguments (and produces a list)
     *              - '?' consumes zero or one arguments
     *              - '*' consumes zero or more arguments (and produces a list)
     *              - '+' consumes one or more arguments (and produces a list)
     *          Note that the difference between the default and nargs=1 is that
     *          with the default, a single value will be produced, while with
     *          nargs=1, a list containing a single value will be produced.
     *
     *      - const -- The value to be produced if the option is specified and the
     *          option uses an action that takes no values.
     *
     *      - default -- The value to be produced if the option is not specified.
     *
     *      - type -- A callable that accepts a single string argument, and
     *          returns the converted value.  The standard Python types str, int,
     *          float, and complex are useful examples of such callables.  If None,
     *          str is used.
     *
     *      - choices -- A container of values that should be allowed. If not None,
     *          after a command-line argument has been converted to the appropriate
     *          type, an exception will be raised if it is not a member of this
     *          collection.
     *
     *      - required -- True if the action must always be specified at the
     *          command line. This is only meaningful for optional command-line
     *          arguments.
     *
     *      - help -- The help string describing the argument.
     *
     *      - metavar -- The name to be used for the option's argument with the
     *          help string. If None, the 'dest' value will be used as the name.
     */

    constructor() {
        let [
            option_strings,
            dest,
            nargs,
            const_value,
            default_value,
            type,
            choices,
            required,
            help,
            metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            nargs: undefined,
            const: undefined,
            default: undefined,
            type: undefined,
            choices: undefined,
            required: false,
            help: undefined,
            metavar: undefined
        })

        // when this class is called as a function, redirect it to .call() method of itself
        super('return arguments.callee.call.apply(arguments.callee, arguments)')

        this.option_strings = option_strings
        this.dest = dest
        this.nargs = nargs
        this.const = const_value
        this.default = default_value
        this.type = type
        this.choices = choices
        this.required = required
        this.help = help
        this.metavar = metavar
    }

    _get_kwargs() {
        let names = [
            'option_strings',
            'dest',
            'nargs',
            'const',
            'default',
            'type',
            'choices',
            'help',
            'metavar'
        ]
        return names.map(name => [ name, getattr(this, name) ])
    }

    format_usage() {
        return this.option_strings[0]
    }

    call(/*parser, namespace, values, option_string = undefined*/) {
        throw new Error('.call() not defined')
    }
}))


const BooleanOptionalAction = _camelcase_alias(_callable(class BooleanOptionalAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            default_value,
            type,
            choices,
            required,
            help,
            metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            default: undefined,
            type: undefined,
            choices: undefined,
            required: false,
            help: undefined,
            metavar: undefined
        })

        let _option_strings = []
        for (let option_string of option_strings) {
            _option_strings.push(option_string)

            if (option_string.startsWith('--')) {
                option_string = '--no-' + option_string.slice(2)
                _option_strings.push(option_string)
            }
        }

        if (help !== undefined && default_value !== undefined) {
            help += ` (default: ${default_value})`
        }

        super({
            option_strings: _option_strings,
            dest,
            nargs: 0,
            default: default_value,
            type,
            choices,
            required,
            help,
            metavar
        })
    }

    call(parser, namespace, values, option_string = undefined) {
        if (this.option_strings.includes(option_string)) {
            setattr(namespace, this.dest, !option_string.startsWith('--no-'))
        }
    }

    format_usage() {
        return this.option_strings.join(' | ')
    }
}))


const _StoreAction = _callable(class _StoreAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            nargs,
            const_value,
            default_value,
            type,
            choices,
            required,
            help,
            metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            nargs: undefined,
            const: undefined,
            default: undefined,
            type: undefined,
            choices: undefined,
            required: false,
            help: undefined,
            metavar: undefined
        })

        if (nargs === 0) {
            throw new TypeError('nargs for store actions must be != 0; if you ' +
                        'have nothing to store, actions such as store ' +
                        'true or store const may be more appropriate')
        }
        if (const_value !== undefined && nargs !== OPTIONAL) {
            throw new TypeError(sub('nargs must be %r to supply const', OPTIONAL))
        }
        super({
            option_strings,
            dest,
            nargs,
            const: const_value,
            default: default_value,
            type,
            choices,
            required,
            help,
            metavar
        })
    }

    call(parser, namespace, values/*, option_string = undefined*/) {
        setattr(namespace, this.dest, values)
    }
})


const _StoreConstAction = _callable(class _StoreConstAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            const_value,
            default_value,
            required,
            help
            //, metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            const: no_default,
            default: undefined,
            required: false,
            help: undefined,
            metavar: undefined
        })

        super({
            option_strings,
            dest,
            nargs: 0,
            const: const_value,
            default: default_value,
            required,
            help
        })
    }

    call(parser, namespace/*, values, option_string = undefined*/) {
        setattr(namespace, this.dest, this.const)
    }
})


const _StoreTrueAction = _callable(class _StoreTrueAction extends _StoreConstAction {

    constructor() {
        let [
            option_strings,
            dest,
            default_value,
            required,
            help
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            default: false,
            required: false,
            help: undefined
        })

        super({
            option_strings,
            dest,
            const: true,
            default: default_value,
            required,
            help
        })
    }
})


const _StoreFalseAction = _callable(class _StoreFalseAction extends _StoreConstAction {

    constructor() {
        let [
            option_strings,
            dest,
            default_value,
            required,
            help
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            default: true,
            required: false,
            help: undefined
        })

        super({
            option_strings,
            dest,
            const: false,
            default: default_value,
            required,
            help
        })
    }
})


const _AppendAction = _callable(class _AppendAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            nargs,
            const_value,
            default_value,
            type,
            choices,
            required,
            help,
            metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            nargs: undefined,
            const: undefined,
            default: undefined,
            type: undefined,
            choices: undefined,
            required: false,
            help: undefined,
            metavar: undefined
        })

        if (nargs === 0) {
            throw new TypeError('nargs for append actions must be != 0; if arg ' +
                        'strings are not supplying the value to append, ' +
                        'the append const action may be more appropriate')
        }
        if (const_value !== undefined && nargs !== OPTIONAL) {
            throw new TypeError(sub('nargs must be %r to supply const', OPTIONAL))
        }
        super({
            option_strings,
            dest,
            nargs,
            const: const_value,
            default: default_value,
            type,
            choices,
            required,
            help,
            metavar
        })
    }

    call(parser, namespace, values/*, option_string = undefined*/) {
        let items = getattr(namespace, this.dest, undefined)
        items = _copy_items(items)
        items.push(values)
        setattr(namespace, this.dest, items)
    }
})


const _AppendConstAction = _callable(class _AppendConstAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            const_value,
            default_value,
            required,
            help,
            metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            const: no_default,
            default: undefined,
            required: false,
            help: undefined,
            metavar: undefined
        })

        super({
            option_strings,
            dest,
            nargs: 0,
            const: const_value,
            default: default_value,
            required,
            help,
            metavar
        })
    }

    call(parser, namespace/*, values, option_string = undefined*/) {
        let items = getattr(namespace, this.dest, undefined)
        items = _copy_items(items)
        items.push(this.const)
        setattr(namespace, this.dest, items)
    }
})


const _CountAction = _callable(class _CountAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            default_value,
            required,
            help
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: no_default,
            default: undefined,
            required: false,
            help: undefined
        })

        super({
            option_strings,
            dest,
            nargs: 0,
            default: default_value,
            required,
            help
        })
    }

    call(parser, namespace/*, values, option_string = undefined*/) {
        let count = getattr(namespace, this.dest, undefined)
        if (count === undefined) {
            count = 0
        }
        setattr(namespace, this.dest, count + 1)
    }
})


const _HelpAction = _callable(class _HelpAction extends Action {

    constructor() {
        let [
            option_strings,
            dest,
            default_value,
            help
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            dest: SUPPRESS,
            default: SUPPRESS,
            help: undefined
        })

        super({
            option_strings,
            dest,
            default: default_value,
            nargs: 0,
            help
        })
    }

    call(parser/*, namespace, values, option_string = undefined*/) {
        parser.print_help()
        parser.exit()
    }
})


const _VersionAction = _callable(class _VersionAction extends Action {

    constructor() {
        let [
            option_strings,
            version,
            dest,
            default_value,
            help
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            version: undefined,
            dest: SUPPRESS,
            default: SUPPRESS,
            help: "show program's version number and exit"
        })

        super({
            option_strings,
            dest,
            default: default_value,
            nargs: 0,
            help
        })
        this.version = version
    }

    call(parser/*, namespace, values, option_string = undefined*/) {
        let version = this.version
        if (version === undefined) {
            version = parser.version
        }
        let formatter = parser._get_formatter()
        formatter.add_text(version)
        parser._print_message(formatter.format_help(), process.stdout)
        parser.exit()
    }
})


const _SubParsersAction = _camelcase_alias(_callable(class _SubParsersAction extends Action {

    constructor() {
        let [
            option_strings,
            prog,
            parser_class,
            dest,
            required,
            help,
            metavar
        ] = _parse_opts(arguments, {
            option_strings: no_default,
            prog: no_default,
            parser_class: no_default,
            dest: SUPPRESS,
            required: false,
            help: undefined,
            metavar: undefined
        })

        let name_parser_map = {}

        super({
            option_strings,
            dest,
            nargs: PARSER,
            choices: name_parser_map,
            required,
            help,
            metavar
        })

        this._prog_prefix = prog
        this._parser_class = parser_class
        this._name_parser_map = name_parser_map
        this._choices_actions = []
    }

    add_parser() {
        let [
            name,
            kwargs
        ] = _parse_opts(arguments, {
            name: no_default,
            '**kwargs': no_default
        })

        // set prog from the existing prefix
        if (kwargs.prog === undefined) {
            kwargs.prog = sub('%s %s', this._prog_prefix, name)
        }

        let aliases = getattr(kwargs, 'aliases', [])
        delete kwargs.aliases

        // create a pseudo-action to hold the choice help
        if ('help' in kwargs) {
            let help = kwargs.help
            delete kwargs.help
            let choice_action = this._ChoicesPseudoAction(name, aliases, help)
            this._choices_actions.push(choice_action)
        }

        // create the parser and add it to the map
        let parser = new this._parser_class(kwargs)
        this._name_parser_map[name] = parser

        // make parser available under aliases also
        for (let alias of aliases) {
            this._name_parser_map[alias] = parser
        }

        return parser
    }

    _get_subactions() {
        return this._choices_actions
    }

    call(parser, namespace, values/*, option_string = undefined*/) {
        let parser_name = values[0]
        let arg_strings = values.slice(1)

        // set the parser name if requested
        if (this.dest !== SUPPRESS) {
            setattr(namespace, this.dest, parser_name)
        }

        // select the parser
        if (hasattr(this._name_parser_map, parser_name)) {
            parser = this._name_parser_map[parser_name]
        } else {
            let args = {parser_name,
                        choices: this._name_parser_map.join(', ')}
            let msg = sub('unknown parser %(parser_name)r (choices: %(choices)s)', args)
            throw new ArgumentError(this, msg)
        }

        // parse all the remaining options into the namespace
        // store any unrecognized options on the object, so that the top
        // level parser can decide what to do with them

        // In case this subparser defines new defaults, we parse them
        // in a new namespace object and then update the original
        // namespace for the relevant parts.
        let subnamespace
        [ subnamespace, arg_strings ] = parser.parse_known_args(arg_strings, undefined)
        for (let [ key, value ] of Object.entries(subnamespace)) {
            setattr(namespace, key, value)
        }

        if (arg_strings.length) {
            setdefault(namespace, _UNRECOGNIZED_ARGS_ATTR, [])
            getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).push(...arg_strings)
        }
    }
}))


_SubParsersAction.prototype._ChoicesPseudoAction = _callable(class _ChoicesPseudoAction extends Action {
    constructor(name, aliases, help) {
        let metavar = name, dest = name
        if (aliases.length) {
            metavar += sub(' (%s)', aliases.join(', '))
        }
        super({ option_strings: [], dest, help, metavar })
    }
})


const _ExtendAction = _callable(class _ExtendAction extends _AppendAction {
    call(parser, namespace, values/*, option_string = undefined*/) {
        let items = getattr(namespace, this.dest, undefined)
        items = _copy_items(items)
        items = items.concat(values)
        setattr(namespace, this.dest, items)
    }
})


// ==============
// Type classes
// ==============
const FileType = _callable(class FileType extends Function {
    /*
     *  Factory for creating file object types
     *
     *  Instances of FileType are typically passed as type= arguments to the
     *  ArgumentParser add_argument() method.
     *
     *  Keyword Arguments:
     *      - mode -- A string indicating how the file is to be opened. Accepts the
     *          same values as the builtin open() function.
     *      - bufsize -- The file's desired buffer size. Accepts the same values as
     *          the builtin open() function.
     *      - encoding -- The file's encoding. Accepts the same values as the
     *          builtin open() function.
     *      - errors -- A string indicating how encoding and decoding errors are to
     *          be handled. Accepts the same value as the builtin open() function.
     */

    constructor() {
        let [
            flags,
            encoding,
            mode,
            autoClose,
            emitClose,
            start,
            end,
            highWaterMark,
            fs
        ] = _parse_opts(arguments, {
            flags: 'r',
            encoding: undefined,
            mode: undefined, // 0o666
            autoClose: undefined, // true
            emitClose: undefined, // false
            start: undefined, // 0
            end: undefined, // Infinity
            highWaterMark: undefined, // 64 * 1024
            fs: undefined
        })

        // when this class is called as a function, redirect it to .call() method of itself
        super('return arguments.callee.call.apply(arguments.callee, arguments)')

        Object.defineProperty(this, 'name', {
            get() {
                return sub('FileType(%r)', flags)
            }
        })
        this._flags = flags
        this._options = {}
        if (encoding !== undefined) this._options.encoding = encoding
        if (mode !== undefined) this._options.mode = mode
        if (autoClose !== undefined) this._options.autoClose = autoClose
        if (emitClose !== undefined) this._options.emitClose = emitClose
        if (start !== undefined) this._options.start = start
        if (end !== undefined) this._options.end = end
        if (highWaterMark !== undefined) this._options.highWaterMark = highWaterMark
        if (fs !== undefined) this._options.fs = fs
    }

    call(string) {
        // the special argument "-" means sys.std{in,out}
        if (string === '-') {
            if (this._flags.includes('r')) {
                return process.stdin
            } else if (this._flags.includes('w')) {
                return process.stdout
            } else {
                let msg = sub('argument "-" with mode %r', this._flags)
                throw new TypeError(msg)
            }
        }

        // all other arguments are used as file names
        let fd
        try {
            fd = fs.openSync(string, this._flags, this._options.mode)
        } catch (e) {
            let args = { filename: string, error: e.message }
            let message = "can't open '%(filename)s': %(error)s"
            throw new ArgumentTypeError(sub(message, args))
        }

        let options = Object.assign({ fd, flags: this._flags }, this._options)
        if (this._flags.includes('r')) {
            return fs.createReadStream(undefined, options)
        } else if (this._flags.includes('w')) {
            return fs.createWriteStream(undefined, options)
        } else {
            let msg = sub('argument "%s" with mode %r', string, this._flags)
            throw new TypeError(msg)
        }
    }

    [util.inspect.custom]() {
        let args = [ this._flags ]
        let kwargs = Object.entries(this._options).map(([ k, v ]) => {
            if (k === 'mode') v = { value: v, [util.inspect.custom]() { return '0o' + this.value.toString(8) } }
            return [ k, v ]
        })
        let args_str = []
                .concat(args.filter(arg => arg !== -1).map(repr))
                .concat(kwargs.filter(([/*kw*/, arg]) => arg !== undefined)
                    .map(([kw, arg]) => sub('%s=%r', kw, arg)))
                .join(', ')
        return sub('%s(%s)', this.constructor.name, args_str)
    }

    toString() {
        return this[util.inspect.custom]()
    }
})

// ===========================
// Optional and Positional Parsing
// ===========================
const Namespace = _callable(class Namespace extends _AttributeHolder() {
    /*
     *  Simple object for storing attributes.
     *
     *  Implements equality by attribute names and values, and provides a simple
     *  string representation.
     */

    constructor(options = {}) {
        super()
        Object.assign(this, options)
    }
})

// unset string tag to mimic plain object
Namespace.prototype[Symbol.toStringTag] = undefined


const _ActionsContainer = _camelcase_alias(_callable(class _ActionsContainer {

    constructor() {
        let [
            description,
            prefix_chars,
            argument_default,
            conflict_handler
        ] = _parse_opts(arguments, {
            description: no_default,
            prefix_chars: no_default,
            argument_default: no_default,
            conflict_handler: no_default
        })

        this.description = description
        this.argument_default = argument_default
        this.prefix_chars = prefix_chars
        this.conflict_handler = conflict_handler

        // set up registries
        this._registries = {}

        // register actions
        this.register('action', undefined, _StoreAction)
        this.register('action', 'store', _StoreAction)
        this.register('action', 'store_const', _StoreConstAction)
        this.register('action', 'store_true', _StoreTrueAction)
        this.register('action', 'store_false', _StoreFalseAction)
        this.register('action', 'append', _AppendAction)
        this.register('action', 'append_const', _AppendConstAction)
        this.register('action', 'count', _CountAction)
        this.register('action', 'help', _HelpAction)
        this.register('action', 'version', _VersionAction)
        this.register('action', 'parsers', _SubParsersAction)
        this.register('action', 'extend', _ExtendAction)
        // LEGACY (v1 compatibility): camelcase variants
        ;[ 'storeConst', 'storeTrue', 'storeFalse', 'appendConst' ].forEach(old_name => {
            let new_name = _to_new_name(old_name)
            this.register('action', old_name, util.deprecate(this._registry_get('action', new_name),
                sub('{action: "%s"} is renamed to {action: "%s"}', old_name, new_name)))
        })
        // end

        // raise an exception if the conflict handler is invalid
        this._get_handler()

        // action storage
        this._actions = []
        this._option_string_actions = {}

        // groups
        this._action_groups = []
        this._mutually_exclusive_groups = []

        // defaults storage
        this._defaults = {}

        // determines whether an "option" looks like a negative number
        this._negative_number_matcher = /^-\d+$|^-\d*\.\d+$/

        // whether or not there are any optionals that look like negative
        // numbers -- uses a list so it can be shared and edited
        this._has_negative_number_optionals = []
    }

    // ====================
    // Registration methods
    // ====================
    register(registry_name, value, object) {
        let registry = setdefault(this._registries, registry_name, {})
        registry[value] = object
    }

    _registry_get(registry_name, value, default_value = undefined) {
        return getattr(this._registries[registry_name], value, default_value)
    }

    // ==================================
    // Namespace default accessor methods
    // ==================================
    set_defaults(kwargs) {
        Object.assign(this._defaults, kwargs)

        // if these defaults match any existing arguments, replace
        // the previous default on the object with the new one
        for (let action of this._actions) {
            if (action.dest in kwargs) {
                action.default = kwargs[action.dest]
            }
        }
    }

    get_default(dest) {
        for (let action of this._actions) {
            if (action.dest === dest && action.default !== undefined) {
                return action.default
            }
        }
        return this._defaults[dest]
    }


    // =======================
    // Adding argument actions
    // =======================
    add_argument() {
        /*
         *  add_argument(dest, ..., name=value, ...)
         *  add_argument(option_string, option_string, ..., name=value, ...)
         */
        let [
            args,
            kwargs
        ] = _parse_opts(arguments, {
            '*args': no_default,
            '**kwargs': no_default
        })
        // LEGACY (v1 compatibility), old-style add_argument([ args ], { options })
        if (args.length === 1 && Array.isArray(args[0])) {
            args = args[0]
            deprecate('argument-array',
                sub('use add_argument(%(args)s, {...}) instead of add_argument([ %(args)s ], { ... })', {
                    args: args.map(repr).join(', ')
                }))
        }
        // end

        // if no positional args are supplied or only one is supplied and
        // it doesn't look like an option string, parse a positional
        // argument
        let chars = this.prefix_chars
        if (!args.length || args.length === 1 && !chars.includes(args[0][0])) {
            if (args.length && 'dest' in kwargs) {
                throw new TypeError('dest supplied twice for positional argument')
            }
            kwargs = this._get_positional_kwargs(...args, kwargs)

        // otherwise, we're adding an optional argument
        } else {
            kwargs = this._get_optional_kwargs(...args, kwargs)
        }

        // if no default was supplied, use the parser-level default
        if (!('default' in kwargs)) {
            let dest = kwargs.dest
            if (dest in this._defaults) {
                kwargs.default = this._defaults[dest]
            } else if (this.argument_default !== undefined) {
                kwargs.default = this.argument_default
            }
        }

        // create the action object, and add it to the parser
        let action_class = this._pop_action_class(kwargs)
        if (typeof action_class !== 'function') {
            throw new TypeError(sub('unknown action "%s"', action_class))
        }
        // eslint-disable-next-line new-cap
        let action = new action_class(kwargs)

        // raise an error if the action type is not callable
        let type_func = this._registry_get('type', action.type, action.type)
        if (typeof type_func !== 'function') {
            throw new TypeError(sub('%r is not callable', type_func))
        }

        if (type_func === FileType) {
            throw new TypeError(sub('%r is a FileType class object, instance of it' +
                                    ' must be passed', type_func))
        }

        // raise an error if the metavar does not match the type
        if ('_get_formatter' in this) {
            try {
                this._get_formatter()._format_args(action, undefined)
            } catch (err) {
                // check for 'invalid nargs value' is an artifact of TypeError and ValueError in js being the same
                if (err instanceof TypeError && err.message !== 'invalid nargs value') {
                    throw new TypeError('length of metavar tuple does not match nargs')
                } else {
                    throw err
                }
            }
        }

        return this._add_action(action)
    }

    add_argument_group() {
        let group = _ArgumentGroup(this, ...arguments)
        this._action_groups.push(group)
        return group
    }

    add_mutually_exclusive_group() {
        // eslint-disable-next-line no-use-before-define
        let group = _MutuallyExclusiveGroup(this, ...arguments)
        this._mutually_exclusive_groups.push(group)
        return group
    }

    _add_action(action) {
        // resolve any conflicts
        this._check_conflict(action)

        // add to actions list
        this._actions.push(action)
        action.container = this

        // index the action by any option strings it has
        for (let option_string of action.option_strings) {
            this._option_string_actions[option_string] = action
        }

        // set the flag if any option strings look like negative numbers
        for (let option_string of action.option_strings) {
            if (this._negative_number_matcher.test(option_string)) {
                if (!this._has_negative_number_optionals.length) {
                    this._has_negative_number_optionals.push(true)
                }
            }
        }

        // return the created action
        return action
    }

    _remove_action(action) {
        _array_remove(this._actions, action)
    }

    _add_container_actions(container) {
        // collect groups by titles
        let title_group_map = {}
        for (let group of this._action_groups) {
            if (group.title in title_group_map) {
                let msg = 'cannot merge actions - two groups are named %r'
                throw new TypeError(sub(msg, group.title))
            }
            title_group_map[group.title] = group
        }

        // map each action to its group
        let group_map = new Map()
        for (let group of container._action_groups) {

            // if a group with the title exists, use that, otherwise
            // create a new group matching the container's group
            if (!(group.title in title_group_map)) {
                title_group_map[group.title] = this.add_argument_group({
                    title: group.title,
                    description: group.description,
                    conflict_handler: group.conflict_handler
                })
            }

            // map the actions to their new group
            for (let action of group._group_actions) {
                group_map.set(action, title_group_map[group.title])
            }
        }

        // add container's mutually exclusive groups
        // NOTE: if add_mutually_exclusive_group ever gains title= and
        // description= then this code will need to be expanded as above
        for (let group of container._mutually_exclusive_groups) {
            let mutex_group = this.add_mutually_exclusive_group({
                required: group.required
            })

            // map the actions to their new mutex group
            for (let action of group._group_actions) {
                group_map.set(action, mutex_group)
            }
        }

        // add all actions to this container or their group
        for (let action of container._actions) {
            group_map.get(action)._add_action(action)
        }
    }

    _get_positional_kwargs() {
        let [
            dest,
            kwargs
        ] = _parse_opts(arguments, {
            dest: no_default,
            '**kwargs': no_default
        })

        // make sure required is not specified
        if ('required' in kwargs) {
            let msg = "'required' is an invalid argument for positionals"
            throw new TypeError(msg)
        }

        // mark positional arguments as required if at least one is
        // always required
        if (![OPTIONAL, ZERO_OR_MORE].includes(kwargs.nargs)) {
            kwargs.required = true
        }
        if (kwargs.nargs === ZERO_OR_MORE && !('default' in kwargs)) {
            kwargs.required = true
        }

        // return the keyword arguments with no option strings
        return Object.assign(kwargs, { dest, option_strings: [] })
    }

    _get_optional_kwargs() {
        let [
            args,
            kwargs
        ] = _parse_opts(arguments, {
            '*args': no_default,
            '**kwargs': no_default
        })

        // determine short and long option strings
        let option_strings = []
        let long_option_strings = []
        let option_string
        for (option_string of args) {
            // error on strings that don't start with an appropriate prefix
            if (!this.prefix_chars.includes(option_string[0])) {
                let args = {option: option_string,
                            prefix_chars: this.prefix_chars}
                let msg = 'invalid option string %(option)r: ' +
                          'must start with a character %(prefix_chars)r'
                throw new TypeError(sub(msg, args))
            }

            // strings starting with two prefix characters are long options
            option_strings.push(option_string)
            if (option_string.length > 1 && this.prefix_chars.includes(option_string[1])) {
                long_option_strings.push(option_string)
            }
        }

        // infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
        let dest = kwargs.dest
        delete kwargs.dest
        if (dest === undefined) {
            let dest_option_string
            if (long_option_strings.length) {
                dest_option_string = long_option_strings[0]
            } else {
                dest_option_string = option_strings[0]
            }
            dest = _string_lstrip(dest_option_string, this.prefix_chars)
            if (!dest) {
                let msg = 'dest= is required for options like %r'
                throw new TypeError(sub(msg, option_string))
            }
            dest = dest.replace(/-/g, '_')
        }

        // return the updated keyword arguments
        return Object.assign(kwargs, { dest, option_strings })
    }

    _pop_action_class(kwargs, default_value = undefined) {
        let action = getattr(kwargs, 'action', default_value)
        delete kwargs.action
        return this._registry_get('action', action, action)
    }

    _get_handler() {
        // determine function from conflict handler string
        let handler_func_name = sub('_handle_conflict_%s', this.conflict_handler)
        if (typeof this[handler_func_name] === 'function') {
            return this[handler_func_name]
        } else {
            let msg = 'invalid conflict_resolution value: %r'
            throw new TypeError(sub(msg, this.conflict_handler))
        }
    }

    _check_conflict(action) {

        // find all options that conflict with this option
        let confl_optionals = []
        for (let option_string of action.option_strings) {
            if (hasattr(this._option_string_actions, option_string)) {
                let confl_optional = this._option_string_actions[option_string]
                confl_optionals.push([ option_string, confl_optional ])
            }
        }

        // resolve any conflicts
        if (confl_optionals.length) {
            let conflict_handler = this._get_handler()
            conflict_handler.call(this, action, confl_optionals)
        }
    }

    _handle_conflict_error(action, conflicting_actions) {
        let message = conflicting_actions.length === 1 ?
            'conflicting option string: %s' :
            'conflicting option strings: %s'
        let conflict_string = conflicting_actions.map(([ option_string/*, action*/ ]) => option_string).join(', ')
        throw new ArgumentError(action, sub(message, conflict_string))
    }

    _handle_conflict_resolve(action, conflicting_actions) {

        // remove all conflicting options
        for (let [ option_string, action ] of conflicting_actions) {

            // remove the conflicting option
            _array_remove(action.option_strings, option_string)
            delete this._option_string_actions[option_string]

            // if the option now has no option string, remove it from the
            // container holding it
            if (!action.option_strings.length) {
                action.container._remove_action(action)
            }
        }
    }
}))


const _ArgumentGroup = _callable(class _ArgumentGroup extends _ActionsContainer {

    constructor() {
        let [
            container,
            title,
            description,
            kwargs
        ] = _parse_opts(arguments, {
            container: no_default,
            title: undefined,
            description: undefined,
            '**kwargs': no_default
        })

        // add any missing keyword arguments by checking the container
        setdefault(kwargs, 'conflict_handler', container.conflict_handler)
        setdefault(kwargs, 'prefix_chars', container.prefix_chars)
        setdefault(kwargs, 'argument_default', container.argument_default)
        super(Object.assign({ description }, kwargs))

        // group attributes
        this.title = title
        this._group_actions = []

        // share most attributes with the container
        this._registries = container._registries
        this._actions = container._actions
        this._option_string_actions = container._option_string_actions
        this._defaults = container._defaults
        this._has_negative_number_optionals =
            container._has_negative_number_optionals
        this._mutually_exclusive_groups = container._mutually_exclusive_groups
    }

    _add_action(action) {
        action = super._add_action(action)
        this._group_actions.push(action)
        return action
    }

    _remove_action(action) {
        super._remove_action(action)
        _array_remove(this._group_actions, action)
    }
})


const _MutuallyExclusiveGroup = _callable(class _MutuallyExclusiveGroup extends _ArgumentGroup {

    constructor() {
        let [
            container,
            required
        ] = _parse_opts(arguments, {
            container: no_default,
            required: false
        })

        super(container)
        this.required = required
        this._container = container
    }

    _add_action(action) {
        if (action.required) {
            let msg = 'mutually exclusive arguments must be optional'
            throw new TypeError(msg)
        }
        action = this._container._add_action(action)
        this._group_actions.push(action)
        return action
    }

    _remove_action(action) {
        this._container._remove_action(action)
        _array_remove(this._group_actions, action)
    }
})


const ArgumentParser = _camelcase_alias(_callable(class ArgumentParser extends _AttributeHolder(_ActionsContainer) {
    /*
     *  Object for parsing command line strings into Python objects.
     *
     *  Keyword Arguments:
     *      - prog -- The name of the program (default: sys.argv[0])
     *      - usage -- A usage message (default: auto-generated from arguments)
     *      - description -- A description of what the program does
     *      - epilog -- Text following the argument descriptions
     *      - parents -- Parsers whose arguments should be copied into this one
     *      - formatter_class -- HelpFormatter class for printing help messages
     *      - prefix_chars -- Characters that prefix optional arguments
     *      - fromfile_prefix_chars -- Characters that prefix files containing
     *          additional arguments
     *      - argument_default -- The default value for all arguments
     *      - conflict_handler -- String indicating how to handle conflicts
     *      - add_help -- Add a -h/-help option
     *      - allow_abbrev -- Allow long options to be abbreviated unambiguously
     *      - exit_on_error -- Determines whether or not ArgumentParser exits with
     *          error info when an error occurs
     */

    constructor() {
        let [
            prog,
            usage,
            description,
            epilog,
            parents,
            formatter_class,
            prefix_chars,
            fromfile_prefix_chars,
            argument_default,
            conflict_handler,
            add_help,
            allow_abbrev,
            exit_on_error,
            debug, // LEGACY (v1 compatibility), debug mode
            version // LEGACY (v1 compatibility), version
        ] = _parse_opts(arguments, {
            prog: undefined,
            usage: undefined,
            description: undefined,
            epilog: undefined,
            parents: [],
            formatter_class: HelpFormatter,
            prefix_chars: '-',
            fromfile_prefix_chars: undefined,
            argument_default: undefined,
            conflict_handler: 'error',
            add_help: true,
            allow_abbrev: true,
            exit_on_error: true,
            debug: undefined, // LEGACY (v1 compatibility), debug mode
            version: undefined // LEGACY (v1 compatibility), version
        })

        // LEGACY (v1 compatibility)
        if (debug !== undefined) {
            deprecate('debug',
                'The "debug" argument to ArgumentParser is deprecated. Please ' +
                'override ArgumentParser.exit function instead.'
            )
        }

        if (version !== undefined) {
            deprecate('version',
                'The "version" argument to ArgumentParser is deprecated. Please use ' +
                "add_argument(..., { action: 'version', version: 'N', ... }) instead."
            )
        }
        // end

        super({
            description,
            prefix_chars,
            argument_default,
            conflict_handler
        })

        // default setting for prog
        if (prog === undefined) {
            prog = path.basename(get_argv()[0] || '')
        }

        this.prog = prog
        this.usage = usage
        this.epilog = epilog
        this.formatter_class = formatter_class
        this.fromfile_prefix_chars = fromfile_prefix_chars
        this.add_help = add_help
        this.allow_abbrev = allow_abbrev
        this.exit_on_error = exit_on_error
        // LEGACY (v1 compatibility), debug mode
        this.debug = debug
        // end

        this._positionals = this.add_argument_group('positional arguments')
        this._optionals = this.add_argument_group('optional arguments')
        this._subparsers = undefined

        // register types
        function identity(string) {
            return string
        }
        this.register('type', undefined, identity)
        this.register('type', null, identity)
        this.register('type', 'auto', identity)
        this.register('type', 'int', function (x) {
            let result = Number(x)
            if (!Number.isInteger(result)) {
                throw new TypeError(sub('could not convert string to int: %r', x))
            }
            return result
        })
        this.register('type', 'float', function (x) {
            let result = Number(x)
            if (isNaN(result)) {
                throw new TypeError(sub('could not convert string to float: %r', x))
            }
            return result
        })
        this.register('type', 'str', String)
        // LEGACY (v1 compatibility): custom types
        this.register('type', 'string',
            util.deprecate(String, 'use {type:"str"} or {type:String} instead of {type:"string"}'))
        // end

        // add help argument if necessary
        // (using explicit default to override global argument_default)
        let default_prefix = prefix_chars.includes('-') ? '-' : prefix_chars[0]
        if (this.add_help) {
            this.add_argument(
                default_prefix + 'h',
                default_prefix.repeat(2) + 'help',
                {
                    action: 'help',
                    default: SUPPRESS,
                    help: 'show this help message and exit'
                }
            )
        }
        // LEGACY (v1 compatibility), version
        if (version) {
            this.add_argument(
                default_prefix + 'v',
                default_prefix.repeat(2) + 'version',
                {
                    action: 'version',
                    default: SUPPRESS,
                    version: this.version,
                    help: "show program's version number and exit"
                }
            )
        }
        // end

        // add parent arguments and defaults
        for (let parent of parents) {
            this._add_container_actions(parent)
            Object.assign(this._defaults, parent._defaults)
        }
    }

    // =======================
    // Pretty __repr__ methods
    // =======================
    _get_kwargs() {
        let names = [
            'prog',
            'usage',
            'description',
            'formatter_class',
            'conflict_handler',
            'add_help'
        ]
        return names.map(name => [ name, getattr(this, name) ])
    }

    // ==================================
    // Optional/Positional adding methods
    // ==================================
    add_subparsers() {
        let [
            kwargs
        ] = _parse_opts(arguments, {
            '**kwargs': no_default
        })

        if (this._subparsers !== undefined) {
            this.error('cannot have multiple subparser arguments')
        }

        // add the parser class to the arguments if it's not present
        setdefault(kwargs, 'parser_class', this.constructor)

        if ('title' in kwargs || 'description' in kwargs) {
            let title = getattr(kwargs, 'title', 'subcommands')
            let description = getattr(kwargs, 'description', undefined)
            delete kwargs.title
            delete kwargs.description
            this._subparsers = this.add_argument_group(title, description)
        } else {
            this._subparsers = this._positionals
        }

        // prog defaults to the usage message of this parser, skipping
        // optional arguments and with no "usage:" prefix
        if (kwargs.prog === undefined) {
            let formatter = this._get_formatter()
            let positionals = this._get_positional_actions()
            let groups = this._mutually_exclusive_groups
            formatter.add_usage(this.usage, positionals, groups, '')
            kwargs.prog = formatter.format_help().trim()
        }

        // create the parsers action and add it to the positionals list
        let parsers_class = this._pop_action_class(kwargs, 'parsers')
        // eslint-disable-next-line new-cap
        let action = new parsers_class(Object.assign({ option_strings: [] }, kwargs))
        this._subparsers._add_action(action)

        // return the created parsers action
        return action
    }

    _add_action(action) {
        if (action.option_strings.length) {
            this._optionals._add_action(action)
        } else {
            this._positionals._add_action(action)
        }
        return action
    }

    _get_optional_actions() {
        return this._actions.filter(action => action.option_strings.length)
    }

    _get_positional_actions() {
        return this._actions.filter(action => !action.option_strings.length)
    }

    // =====================================
    // Command line argument parsing methods
    // =====================================
    parse_args(args = undefined, namespace = undefined) {
        let argv
        [ args, argv ] = this.parse_known_args(args, namespace)
        if (argv && argv.length > 0) {
            let msg = 'unrecognized arguments: %s'
            this.error(sub(msg, argv.join(' ')))
        }
        return args
    }

    parse_known_args(args = undefined, namespace = undefined) {
        if (args === undefined) {
            args = get_argv().slice(1)
        }

        // default Namespace built from parser defaults
        if (namespace === undefined) {
            namespace = new Namespace()
        }

        // add any action defaults that aren't present
        for (let action of this._actions) {
            if (action.dest !== SUPPRESS) {
                if (!hasattr(namespace, action.dest)) {
                    if (action.default !== SUPPRESS) {
                        setattr(namespace, action.dest, action.default)
                    }
                }
            }
        }

        // add any parser defaults that aren't present
        for (let dest of Object.keys(this._defaults)) {
            if (!hasattr(namespace, dest)) {
                setattr(namespace, dest, this._defaults[dest])
            }
        }

        // parse the arguments and exit if there are any errors
        if (this.exit_on_error) {
            try {
                [ namespace, args ] = this._parse_known_args(args, namespace)
            } catch (err) {
                if (err instanceof ArgumentError) {
                    this.error(err.message)
                } else {
                    throw err
                }
            }
        } else {
            [ namespace, args ] = this._parse_known_args(args, namespace)
        }

        if (hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR)) {
            args = args.concat(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR))
            delattr(namespace, _UNRECOGNIZED_ARGS_ATTR)
        }

        return [ namespace, args ]
    }

    _parse_known_args(arg_strings, namespace) {
        // replace arg strings that are file references
        if (this.fromfile_prefix_chars !== undefined) {
            arg_strings = this._read_args_from_files(arg_strings)
        }

        // map all mutually exclusive arguments to the other arguments
        // they can't occur with
        let action_conflicts = new Map()
        for (let mutex_group of this._mutually_exclusive_groups) {
            let group_actions = mutex_group._group_actions
            for (let [ i, mutex_action ] of Object.entries(mutex_group._group_actions)) {
                let conflicts = action_conflicts.get(mutex_action) || []
                conflicts = conflicts.concat(group_actions.slice(0, +i))
                conflicts = conflicts.concat(group_actions.slice(+i + 1))
                action_conflicts.set(mutex_action, conflicts)
            }
        }

        // find all option indices, and determine the arg_string_pattern
        // which has an 'O' if there is an option at an index,
        // an 'A' if there is an argument, or a '-' if there is a '--'
        let option_string_indices = {}
        let arg_string_pattern_parts = []
        let arg_strings_iter = Object.entries(arg_strings)[Symbol.iterator]()
        for (let [ i, arg_string ] of arg_strings_iter) {

            // all args after -- are non-options
            if (arg_string === '--') {
                arg_string_pattern_parts.push('-')
                for ([ i, arg_string ] of arg_strings_iter) {
                    arg_string_pattern_parts.push('A')
                }

            // otherwise, add the arg to the arg strings
            // and note the index if it was an option
            } else {
                let option_tuple = this._parse_optional(arg_string)
                let pattern
                if (option_tuple === undefined) {
                    pattern = 'A'
                } else {
                    option_string_indices[i] = option_tuple
                    pattern = 'O'
                }
                arg_string_pattern_parts.push(pattern)
            }
        }

        // join the pieces together to form the pattern
        let arg_strings_pattern = arg_string_pattern_parts.join('')

        // converts arg strings to the appropriate and then takes the action
        let seen_actions = new Set()
        let seen_non_default_actions = new Set()
        let extras

        let take_action = (action, argument_strings, option_string = undefined) => {
            seen_actions.add(action)
            let argument_values = this._get_values(action, argument_strings)

            // error if this argument is not allowed with other previously
            // seen arguments, assuming that actions that use the default
            // value don't really count as "present"
            if (argument_values !== action.default) {
                seen_non_default_actions.add(action)
                for (let conflict_action of action_conflicts.get(action) || []) {
                    if (seen_non_default_actions.has(conflict_action)) {
                        let msg = 'not allowed with argument %s'
                        let action_name = _get_action_name(conflict_action)
                        throw new ArgumentError(action, sub(msg, action_name))
                    }
                }
            }

            // take the action if we didn't receive a SUPPRESS value
            // (e.g. from a default)
            if (argument_values !== SUPPRESS) {
                action(this, namespace, argument_values, option_string)
            }
        }

        // function to convert arg_strings into an optional action
        let consume_optional = start_index => {

            // get the optional identified at this index
            let option_tuple = option_string_indices[start_index]
            let [ action, option_string, explicit_arg ] = option_tuple

            // identify additional optionals in the same arg string
            // (e.g. -xyz is the same as -x -y -z if no args are required)
            let action_tuples = []
            let stop
            for (;;) {

                // if we found no optional action, skip it
                if (action === undefined) {
                    extras.push(arg_strings[start_index])
                    return start_index + 1
                }

                // if there is an explicit argument, try to match the
                // optional's string arguments to only this
                if (explicit_arg !== undefined) {
                    let arg_count = this._match_argument(action, 'A')

                    // if the action is a single-dash option and takes no
                    // arguments, try to parse more single-dash options out
                    // of the tail of the option string
                    let chars = this.prefix_chars
                    if (arg_count === 0 && !chars.includes(option_string[1])) {
                        action_tuples.push([ action, [], option_string ])
                        let char = option_string[0]
                        option_string = char + explicit_arg[0]
                        let new_explicit_arg = explicit_arg.slice(1) || undefined
                        let optionals_map = this._option_string_actions
                        if (hasattr(optionals_map, option_string)) {
                            action = optionals_map[option_string]
                            explicit_arg = new_explicit_arg
                        } else {
                            let msg = 'ignored explicit argument %r'
                            throw new ArgumentError(action, sub(msg, explicit_arg))
                        }

                    // if the action expect exactly one argument, we've
                    // successfully matched the option; exit the loop
                    } else if (arg_count === 1) {
                        stop = start_index + 1
                        let args = [ explicit_arg ]
                        action_tuples.push([ action, args, option_string ])
                        break

                    // error if a double-dash option did not use the
                    // explicit argument
                    } else {
                        let msg = 'ignored explicit argument %r'
                        throw new ArgumentError(action, sub(msg, explicit_arg))
                    }

                // if there is no explicit argument, try to match the
                // optional's string arguments with the following strings
                // if successful, exit the loop
                } else {
                    let start = start_index + 1
                    let selected_patterns = arg_strings_pattern.slice(start)
                    let arg_count = this._match_argument(action, selected_patterns)
                    stop = start + arg_count
                    let args = arg_strings.slice(start, stop)
                    action_tuples.push([ action, args, option_string ])
                    break
                }
            }

            // add the Optional to the list and return the index at which
            // the Optional's string args stopped
            assert(action_tuples.length)
            for (let [ action, args, option_string ] of action_tuples) {
                take_action(action, args, option_string)
            }
            return stop
        }

        // the list of Positionals left to be parsed; this is modified
        // by consume_positionals()
        let positionals = this._get_positional_actions()

        // function to convert arg_strings into positional actions
        let consume_positionals = start_index => {
            // match as many Positionals as possible
            let selected_pattern = arg_strings_pattern.slice(start_index)
            let arg_counts = this._match_arguments_partial(positionals, selected_pattern)

            // slice off the appropriate arg strings for each Positional
            // and add the Positional and its args to the list
            for (let i = 0; i < positionals.length && i < arg_counts.length; i++) {
                let action = positionals[i]
                let arg_count = arg_counts[i]
                let args = arg_strings.slice(start_index, start_index + arg_count)
                start_index += arg_count
                take_action(action, args)
            }

            // slice off the Positionals that we just parsed and return the
            // index at which the Positionals' string args stopped
            positionals = positionals.slice(arg_counts.length)
            return start_index
        }

        // consume Positionals and Optionals alternately, until we have
        // passed the last option string
        extras = []
        let start_index = 0
        let max_option_string_index = Math.max(-1, ...Object.keys(option_string_indices).map(Number))
        while (start_index <= max_option_string_index) {

            // consume any Positionals preceding the next option
            let next_option_string_index = Math.min(
                // eslint-disable-next-line no-loop-func
                ...Object.keys(option_string_indices).map(Number).filter(index => index >= start_index)
            )
            if (start_index !== next_option_string_index) {
                let positionals_end_index = consume_positionals(start_index)

                // only try to parse the next optional if we didn't consume
                // the option string during the positionals parsing
                if (positionals_end_index > start_index) {
                    start_index = positionals_end_index
                    continue
                } else {
                    start_index = positionals_end_index
                }
            }

            // if we consumed all the positionals we could and we're not
            // at the index of an option string, there were extra arguments
            if (!(start_index in option_string_indices)) {
                let strings = arg_strings.slice(start_index, next_option_string_index)
                extras = extras.concat(strings)
                start_index = next_option_string_index
            }

            // consume the next optional and any arguments for it
            start_index = consume_optional(start_index)
        }

        // consume any positionals following the last Optional
        let stop_index = consume_positionals(start_index)

        // if we didn't consume all the argument strings, there were extras
        extras = extras.concat(arg_strings.slice(stop_index))

        // make sure all required actions were present and also convert
        // action defaults which were not given as arguments
        let required_actions = []
        for (let action of this._actions) {
            if (!seen_actions.has(action)) {
                if (action.required) {
                    required_actions.push(_get_action_name(action))
                } else {
                    // Convert action default now instead of doing it before
                    // parsing arguments to avoid calling convert functions
                    // twice (which may fail) if the argument was given, but
                    // only if it was defined already in the namespace
                    if (action.default !== undefined &&
                        typeof action.default === 'string' &&
                        hasattr(namespace, action.dest) &&
                        action.default === getattr(namespace, action.dest)) {
                        setattr(namespace, action.dest,
                                this._get_value(action, action.default))
                    }
                }
            }
        }

        if (required_actions.length) {
            this.error(sub('the following arguments are required: %s',
                       required_actions.join(', ')))
        }

        // make sure all required groups had one option present
        for (let group of this._mutually_exclusive_groups) {
            if (group.required) {
                let no_actions_used = true
                for (let action of group._group_actions) {
                    if (seen_non_default_actions.has(action)) {
                        no_actions_used = false
                        break
                    }
                }

                // if no actions were used, report the error
                if (no_actions_used) {
                    let names = group._group_actions
                        .filter(action => action.help !== SUPPRESS)
                        .map(action => _get_action_name(action))
                    let msg = 'one of the arguments %s is required'
                    this.error(sub(msg, names.join(' ')))
                }
            }
        }

        // return the updated namespace and the extra arguments
        return [ namespace, extras ]
    }

    _read_args_from_files(arg_strings) {
        // expand arguments referencing files
        let new_arg_strings = []
        for (let arg_string of arg_strings) {

            // for regular arguments, just add them back into the list
            if (!arg_string || !this.fromfile_prefix_chars.includes(arg_string[0])) {
                new_arg_strings.push(arg_string)

            // replace arguments referencing files with the file content
            } else {
                try {
                    let args_file = fs.readFileSync(arg_string.slice(1), 'utf8')
                    let arg_strings = []
                    for (let arg_line of splitlines(args_file)) {
                        for (let arg of this.convert_arg_line_to_args(arg_line)) {
                            arg_strings.push(arg)
                        }
                    }
                    arg_strings = this._read_args_from_files(arg_strings)
                    new_arg_strings = new_arg_strings.concat(arg_strings)
                } catch (err) {
                    this.error(err.message)
                }
            }
        }

        // return the modified argument list
        return new_arg_strings
    }

    convert_arg_line_to_args(arg_line) {
        return [arg_line]
    }

    _match_argument(action, arg_strings_pattern) {
        // match the pattern for this action to the arg strings
        let nargs_pattern = this._get_nargs_pattern(action)
        let match = arg_strings_pattern.match(new RegExp('^' + nargs_pattern))

        // raise an exception if we weren't able to find a match
        if (match === null) {
            let nargs_errors = {
                undefined: 'expected one argument',
                [OPTIONAL]: 'expected at most one argument',
                [ONE_OR_MORE]: 'expected at least one argument'
            }
            let msg = nargs_errors[action.nargs]
            if (msg === undefined) {
                msg = sub(action.nargs === 1 ? 'expected %s argument' : 'expected %s arguments', action.nargs)
            }
            throw new ArgumentError(action, msg)
        }

        // return the number of arguments matched
        return match[1].length
    }

    _match_arguments_partial(actions, arg_strings_pattern) {
        // progressively shorten the actions list by slicing off the
        // final actions until we find a match
        let result = []
        for (let i of range(actions.length, 0, -1)) {
            let actions_slice = actions.slice(0, i)
            let pattern = actions_slice.map(action => this._get_nargs_pattern(action)).join('')
            let match = arg_strings_pattern.match(new RegExp('^' + pattern))
            if (match !== null) {
                result = result.concat(match.slice(1).map(string => string.length))
                break
            }
        }

        // return the list of arg string counts
        return result
    }

    _parse_optional(arg_string) {
        // if it's an empty string, it was meant to be a positional
        if (!arg_string) {
            return undefined
        }

        // if it doesn't start with a prefix, it was meant to be positional
        if (!this.prefix_chars.includes(arg_string[0])) {
            return undefined
        }

        // if the option string is present in the parser, return the action
        if (arg_string in this._option_string_actions) {
            let action = this._option_string_actions[arg_string]
            return [ action, arg_string, undefined ]
        }

        // if it's just a single character, it was meant to be positional
        if (arg_string.length === 1) {
            return undefined
        }

        // if the option string before the "=" is present, return the action
        if (arg_string.includes('=')) {
            let [ option_string, explicit_arg ] = _string_split(arg_string, '=', 1)
            if (option_string in this._option_string_actions) {
                let action = this._option_string_actions[option_string]
                return [ action, option_string, explicit_arg ]
            }
        }

        // search through all possible prefixes of the option string
        // and all actions in the parser for possible interpretations
        let option_tuples = this._get_option_tuples(arg_string)

        // if multiple actions match, the option string was ambiguous
        if (option_tuples.length > 1) {
            let options = option_tuples.map(([ /*action*/, option_string/*, explicit_arg*/ ]) => option_string).join(', ')
            let args = {option: arg_string, matches: options}
            let msg = 'ambiguous option: %(option)s could match %(matches)s'
            this.error(sub(msg, args))

        // if exactly one action matched, this segmentation is good,
        // so return the parsed action
        } else if (option_tuples.length === 1) {
            let [ option_tuple ] = option_tuples
            return option_tuple
        }

        // if it was not found as an option, but it looks like a negative
        // number, it was meant to be positional
        // unless there are negative-number-like options
        if (this._negative_number_matcher.test(arg_string)) {
            if (!this._has_negative_number_optionals.length) {
                return undefined
            }
        }

        // if it contains a space, it was meant to be a positional
        if (arg_string.includes(' ')) {
            return undefined
        }

        // it was meant to be an optional but there is no such option
        // in this parser (though it might be a valid option in a subparser)
        return [ undefined, arg_string, undefined ]
    }

    _get_option_tuples(option_string) {
        let result = []

        // option strings starting with two prefix characters are only
        // split at the '='
        let chars = this.prefix_chars
        if (chars.includes(option_string[0]) && chars.includes(option_string[1])) {
            if (this.allow_abbrev) {
                let option_prefix, explicit_arg
                if (option_string.includes('=')) {
                    [ option_prefix, explicit_arg ] = _string_split(option_string, '=', 1)
                } else {
                    option_prefix = option_string
                    explicit_arg = undefined
                }
                for (let option_string of Object.keys(this._option_string_actions)) {
                    if (option_string.startsWith(option_prefix)) {
                        let action = this._option_string_actions[option_string]
                        let tup = [ action, option_string, explicit_arg ]
                        result.push(tup)
                    }
                }
            }

        // single character options can be concatenated with their arguments
        // but multiple character options always have to have their argument
        // separate
        } else if (chars.includes(option_string[0]) && !chars.includes(option_string[1])) {
            let option_prefix = option_string
            let explicit_arg = undefined
            let short_option_prefix = option_string.slice(0, 2)
            let short_explicit_arg = option_string.slice(2)

            for (let option_string of Object.keys(this._option_string_actions)) {
                if (option_string === short_option_prefix) {
                    let action = this._option_string_actions[option_string]
                    let tup = [ action, option_string, short_explicit_arg ]
                    result.push(tup)
                } else if (option_string.startsWith(option_prefix)) {
                    let action = this._option_string_actions[option_string]
                    let tup = [ action, option_string, explicit_arg ]
                    result.push(tup)
                }
            }

        // shouldn't ever get here
        } else {
            this.error(sub('unexpected option string: %s', option_string))
        }

        // return the collected option tuples
        return result
    }

    _get_nargs_pattern(action) {
        // in all examples below, we have to allow for '--' args
        // which are represented as '-' in the pattern
        let nargs = action.nargs
        let nargs_pattern

        // the default (None) is assumed to be a single argument
        if (nargs === undefined) {
            nargs_pattern = '(-*A-*)'

        // allow zero or one arguments
        } else if (nargs === OPTIONAL) {
            nargs_pattern = '(-*A?-*)'

        // allow zero or more arguments
        } else if (nargs === ZERO_OR_MORE) {
            nargs_pattern = '(-*[A-]*)'

        // allow one or more arguments
        } else if (nargs === ONE_OR_MORE) {
            nargs_pattern = '(-*A[A-]*)'

        // allow any number of options or arguments
        } else if (nargs === REMAINDER) {
            nargs_pattern = '([-AO]*)'

        // allow one argument followed by any number of options or arguments
        } else if (nargs === PARSER) {
            nargs_pattern = '(-*A[-AO]*)'

        // suppress action, like nargs=0
        } else if (nargs === SUPPRESS) {
            nargs_pattern = '(-*-*)'

        // all others should be integers
        } else {
            nargs_pattern = sub('(-*%s-*)', 'A'.repeat(nargs).split('').join('-*'))
        }

        // if this is an optional action, -- is not allowed
        if (action.option_strings.length) {
            nargs_pattern = nargs_pattern.replace(/-\*/g, '')
            nargs_pattern = nargs_pattern.replace(/-/g, '')
        }

        // return the pattern
        return nargs_pattern
    }

    // ========================
    // Alt command line argument parsing, allowing free intermix
    // ========================

    parse_intermixed_args(args = undefined, namespace = undefined) {
        let argv
        [ args, argv ] = this.parse_known_intermixed_args(args, namespace)
        if (argv.length) {
            let msg = 'unrecognized arguments: %s'
            this.error(sub(msg, argv.join(' ')))
        }
        return args
    }

    parse_known_intermixed_args(args = undefined, namespace = undefined) {
        // returns a namespace and list of extras
        //
        // positional can be freely intermixed with optionals.  optionals are
        // first parsed with all positional arguments deactivated.  The 'extras'
        // are then parsed.  If the parser definition is incompatible with the
        // intermixed assumptions (e.g. use of REMAINDER, subparsers) a
        // TypeError is raised.
        //
        // positionals are 'deactivated' by setting nargs and default to
        // SUPPRESS.  This blocks the addition of that positional to the
        // namespace

        let extras
        let positionals = this._get_positional_actions()
        let a = positionals.filter(action => [ PARSER, REMAINDER ].includes(action.nargs))
        if (a.length) {
            throw new TypeError(sub('parse_intermixed_args: positional arg' +
                                    ' with nargs=%s', a[0].nargs))
        }

        for (let group of this._mutually_exclusive_groups) {
            for (let action of group._group_actions) {
                if (positionals.includes(action)) {
                    throw new TypeError('parse_intermixed_args: positional in' +
                                        ' mutuallyExclusiveGroup')
                }
            }
        }

        let save_usage
        try {
            save_usage = this.usage
            let remaining_args
            try {
                if (this.usage === undefined) {
                    // capture the full usage for use in error messages
                    this.usage = this.format_usage().slice(7)
                }
                for (let action of positionals) {
                    // deactivate positionals
                    action.save_nargs = action.nargs
                    // action.nargs = 0
                    action.nargs = SUPPRESS
                    action.save_default = action.default
                    action.default = SUPPRESS
                }
                [ namespace, remaining_args ] = this.parse_known_args(args,
                                                                      namespace)
                for (let action of positionals) {
                    // remove the empty positional values from namespace
                    let attr = getattr(namespace, action.dest)
                    if (Array.isArray(attr) && attr.length === 0) {
                        // eslint-disable-next-line no-console
                        console.warn(sub('Do not expect %s in %s', action.dest, namespace))
                        delattr(namespace, action.dest)
                    }
                }
            } finally {
                // restore nargs and usage before exiting
                for (let action of positionals) {
                    action.nargs = action.save_nargs
                    action.default = action.save_default
                }
            }
            let optionals = this._get_optional_actions()
            try {
                // parse positionals.  optionals aren't normally required, but
                // they could be, so make sure they aren't.
                for (let action of optionals) {
                    action.save_required = action.required
                    action.required = false
                }
                for (let group of this._mutually_exclusive_groups) {
                    group.save_required = group.required
                    group.required = false
                }
                [ namespace, extras ] = this.parse_known_args(remaining_args,
                                                              namespace)
            } finally {
                // restore parser values before exiting
                for (let action of optionals) {
                    action.required = action.save_required
                }
                for (let group of this._mutually_exclusive_groups) {
                    group.required = group.save_required
                }
            }
        } finally {
            this.usage = save_usage
        }
        return [ namespace, extras ]
    }

    // ========================
    // Value conversion methods
    // ========================
    _get_values(action, arg_strings) {
        // for everything but PARSER, REMAINDER args, strip out first '--'
        if (![PARSER, REMAINDER].includes(action.nargs)) {
            try {
                _array_remove(arg_strings, '--')
            } catch (err) {}
        }

        let value
        // optional argument produces a default when not present
        if (!arg_strings.length && action.nargs === OPTIONAL) {
            if (action.option_strings.length) {
                value = action.const
            } else {
                value = action.default
            }
            if (typeof value === 'string') {
                value = this._get_value(action, value)
                this._check_value(action, value)
            }

        // when nargs='*' on a positional, if there were no command-line
        // args, use the default if it is anything other than None
        } else if (!arg_strings.length && action.nargs === ZERO_OR_MORE &&
              !action.option_strings.length) {
            if (action.default !== undefined) {
                value = action.default
            } else {
                value = arg_strings
            }
            this._check_value(action, value)

        // single argument or optional argument produces a single value
        } else if (arg_strings.length === 1 && [undefined, OPTIONAL].includes(action.nargs)) {
            let arg_string = arg_strings[0]
            value = this._get_value(action, arg_string)
            this._check_value(action, value)

        // REMAINDER arguments convert all values, checking none
        } else if (action.nargs === REMAINDER) {
            value = arg_strings.map(v => this._get_value(action, v))

        // PARSER arguments convert all values, but check only the first
        } else if (action.nargs === PARSER) {
            value = arg_strings.map(v => this._get_value(action, v))
            this._check_value(action, value[0])

        // SUPPRESS argument does not put anything in the namespace
        } else if (action.nargs === SUPPRESS) {
            value = SUPPRESS

        // all other types of nargs produce a list
        } else {
            value = arg_strings.map(v => this._get_value(action, v))
            for (let v of value) {
                this._check_value(action, v)
            }
        }

        // return the converted value
        return value
    }

    _get_value(action, arg_string) {
        let type_func = this._registry_get('type', action.type, action.type)
        if (typeof type_func !== 'function') {
            let msg = '%r is not callable'
            throw new ArgumentError(action, sub(msg, type_func))
        }

        // convert the value to the appropriate type
        let result
        try {
            try {
                result = type_func(arg_string)
            } catch (err) {
                // Dear TC39, why would you ever consider making es6 classes not callable?
                // We had one universal interface, [[Call]], which worked for anything
                // (with familiar this-instanceof guard for classes). Now we have two.
                if (err instanceof TypeError &&
                    /Class constructor .* cannot be invoked without 'new'/.test(err.message)) {
                    // eslint-disable-next-line new-cap
                    result = new type_func(arg_string)
                } else {
                    throw err
                }
            }

        } catch (err) {
            // ArgumentTypeErrors indicate errors
            if (err instanceof ArgumentTypeError) {
                //let name = getattr(action.type, 'name', repr(action.type))
                let msg = err.message
                throw new ArgumentError(action, msg)

            // TypeErrors or ValueErrors also indicate errors
            } else if (err instanceof TypeError) {
                let name = getattr(action.type, 'name', repr(action.type))
                let args = {type: name, value: arg_string}
                let msg = 'invalid %(type)s value: %(value)r'
                throw new ArgumentError(action, sub(msg, args))
            } else {
                throw err
            }
        }

        // return the converted value
        return result
    }

    _check_value(action, value) {
        // converted value must be one of the choices (if specified)
        if (action.choices !== undefined && !_choices_to_array(action.choices).includes(value)) {
            let args = {value,
                        choices: _choices_to_array(action.choices).map(repr).join(', ')}
            let msg = 'invalid choice: %(value)r (choose from %(choices)s)'
            throw new ArgumentError(action, sub(msg, args))
        }
    }

    // =======================
    // Help-formatting methods
    // =======================
    format_usage() {
        let formatter = this._get_formatter()
        formatter.add_usage(this.usage, this._actions,
                            this._mutually_exclusive_groups)
        return formatter.format_help()
    }

    format_help() {
        let formatter = this._get_formatter()

        // usage
        formatter.add_usage(this.usage, this._actions,
                            this._mutually_exclusive_groups)

        // description
        formatter.add_text(this.description)

        // positionals, optionals and user-defined groups
        for (let action_group of this._action_groups) {
            formatter.start_section(action_group.title)
            formatter.add_text(action_group.description)
            formatter.add_arguments(action_group._group_actions)
            formatter.end_section()
        }

        // epilog
        formatter.add_text(this.epilog)

        // determine help from format above
        return formatter.format_help()
    }

    _get_formatter() {
        // eslint-disable-next-line new-cap
        return new this.formatter_class({ prog: this.prog })
    }

    // =====================
    // Help-printing methods
    // =====================
    print_usage(file = undefined) {
        if (file === undefined) file = process.stdout
        this._print_message(this.format_usage(), file)
    }

    print_help(file = undefined) {
        if (file === undefined) file = process.stdout
        this._print_message(this.format_help(), file)
    }

    _print_message(message, file = undefined) {
        if (message) {
            if (file === undefined) file = process.stderr
            file.write(message)
        }
    }

    // ===============
    // Exiting methods
    // ===============
    exit(status = 0, message = undefined) {
        if (message) {
            this._print_message(message, process.stderr)
        }
        process.exit(status)
    }

    error(message) {
        /*
         *  error(message: string)
         *
         *  Prints a usage message incorporating the message to stderr and
         *  exits.
         *
         *  If you override this in a subclass, it should not return -- it
         *  should either exit or raise an exception.
         */

        // LEGACY (v1 compatibility), debug mode
        if (this.debug === true) throw new Error(message)
        // end
        this.print_usage(process.stderr)
        let args = {prog: this.prog, message: message}
        this.exit(2, sub('%(prog)s: error: %(message)s\n', args))
    }
}))


module.exports = {
    ArgumentParser,
    ArgumentError,
    ArgumentTypeError,
    BooleanOptionalAction,
    FileType,
    HelpFormatter,
    ArgumentDefaultsHelpFormatter,
    RawDescriptionHelpFormatter,
    RawTextHelpFormatter,
    MetavarTypeHelpFormatter,
    Namespace,
    Action,
    ONE_OR_MORE,
    OPTIONAL,
    PARSER,
    REMAINDER,
    SUPPRESS,
    ZERO_OR_MORE
}

// LEGACY (v1 compatibility), Const alias
Object.defineProperty(module.exports, 'Const', {
    get() {
        let result = {}
        Object.entries({ ONE_OR_MORE, OPTIONAL, PARSER, REMAINDER, SUPPRESS, ZERO_OR_MORE }).forEach(([ n, v ]) => {
            Object.defineProperty(result, n, {
                get() {
                    deprecate(n, sub('use argparse.%s instead of argparse.Const.%s', n, n))
                    return v
                }
            })
        })
        Object.entries({ _UNRECOGNIZED_ARGS_ATTR }).forEach(([ n, v ]) => {
            Object.defineProperty(result, n, {
                get() {
                    deprecate(n, sub('argparse.Const.%s is an internal symbol and will no longer be available', n))
                    return v
                }
            })
        })
        return result
    },
    enumerable: false
})
// end
// Limited implementation of python % string operator, supports only %s and %r for now
// (other formats are not used here, but may appear in custom templates)

'use strict'

const { inspect } = require('util')


module.exports = function sub(pattern, ...values) {
    let regex = /%(?:(%)|(-)?(\*)?(?:\((\w+)\))?([A-Za-z]))/g

    let result = pattern.replace(regex, function (_, is_literal, is_left_align, is_padded, name, format) {
        if (is_literal) return '%'

        let padded_count = 0
        if (is_padded) {
            if (values.length === 0) throw new TypeError('not enough arguments for format string')
            padded_count = values.shift()
            if (!Number.isInteger(padded_count)) throw new TypeError('* wants int')
        }

        let str
        if (name !== undefined) {
            let dict = values[0]
            if (typeof dict !== 'object' || dict === null) throw new TypeError('format requires a mapping')
            if (!(name in dict)) throw new TypeError(`no such key: '${name}'`)
            str = dict[name]
        } else {
            if (values.length === 0) throw new TypeError('not enough arguments for format string')
            str = values.shift()
        }

        switch (format) {
            case 's':
                str = String(str)
                break
            case 'r':
                str = inspect(str)
                break
            case 'd':
            case 'i':
                if (typeof str !== 'number') {
                    throw new TypeError(`%${format} format: a number is required, not ${typeof str}`)
                }
                str = String(str.toFixed(0))
                break
            default:
                throw new TypeError(`unsupported format character '${format}'`)
        }

        if (padded_count > 0) {
            return is_left_align ? str.padEnd(padded_count) : str.padStart(padded_count)
        } else {
            return str
        }
    })

    if (values.length) {
        if (values.length === 1 && typeof values[0] === 'object' && values[0] !== null) {
            // mapping
        } else {
            throw new TypeError('not all arguments converted during string formatting')
        }
    }

    return result
}
// Partial port of python's argparse module, version 3.9.0 (only wrap and fill functions):
// https://github.com/python/cpython/blob/v3.9.0b4/Lib/textwrap.py

'use strict'

/*
 * Text wrapping and filling.
 */

// Copyright (C) 1999-2001 Gregory P. Ward.
// Copyright (C) 2002, 2003 Python Software Foundation.
// Copyright (C) 2020 argparse.js authors
// Originally written by Greg Ward <gward@python.net>

// Hardcode the recognized whitespace characters to the US-ASCII
// whitespace characters.  The main reason for doing this is that
// some Unicode spaces (like \u00a0) are non-breaking whitespaces.
//
// This less funky little regex just split on recognized spaces. E.g.
//   "Hello there -- you goof-ball, use the -b option!"
// splits into
//   Hello/ /there/ /--/ /you/ /goof-ball,/ /use/ /the/ /-b/ /option!/
const wordsep_simple_re = /([\t\n\x0b\x0c\r ]+)/

class TextWrapper {
    /*
     *  Object for wrapping/filling text.  The public interface consists of
     *  the wrap() and fill() methods; the other methods are just there for
     *  subclasses to override in order to tweak the default behaviour.
     *  If you want to completely replace the main wrapping algorithm,
     *  you'll probably have to override _wrap_chunks().
     *
     *  Several instance attributes control various aspects of wrapping:
     *    width (default: 70)
     *      the maximum width of wrapped lines (unless break_long_words
     *      is false)
     *    initial_indent (default: "")
     *      string that will be prepended to the first line of wrapped
     *      output.  Counts towards the line's width.
     *    subsequent_indent (default: "")
     *      string that will be prepended to all lines save the first
     *      of wrapped output; also counts towards each line's width.
     *    expand_tabs (default: true)
     *      Expand tabs in input text to spaces before further processing.
     *      Each tab will become 0 .. 'tabsize' spaces, depending on its position
     *      in its line.  If false, each tab is treated as a single character.
     *    tabsize (default: 8)
     *      Expand tabs in input text to 0 .. 'tabsize' spaces, unless
     *      'expand_tabs' is false.
     *    replace_whitespace (default: true)
     *      Replace all whitespace characters in the input text by spaces
     *      after tab expansion.  Note that if expand_tabs is false and
     *      replace_whitespace is true, every tab will be converted to a
     *      single space!
     *    fix_sentence_endings (default: false)
     *      Ensure that sentence-ending punctuation is always followed
     *      by two spaces.  Off by default because the algorithm is
     *      (unavoidably) imperfect.
     *    break_long_words (default: true)
     *      Break words longer than 'width'.  If false, those words will not
     *      be broken, and some lines might be longer than 'width'.
     *    break_on_hyphens (default: true)
     *      Allow breaking hyphenated words. If true, wrapping will occur
     *      preferably on whitespaces and right after hyphens part of
     *      compound words.
     *    drop_whitespace (default: true)
     *      Drop leading and trailing whitespace from lines.
     *    max_lines (default: None)
     *      Truncate wrapped lines.
     *    placeholder (default: ' [...]')
     *      Append to the last line of truncated text.
     */

    constructor(options = {}) {
        let {
            width = 70,
            initial_indent = '',
            subsequent_indent = '',
            expand_tabs = true,
            replace_whitespace = true,
            fix_sentence_endings = false,
            break_long_words = true,
            drop_whitespace = true,
            break_on_hyphens = true,
            tabsize = 8,
            max_lines = undefined,
            placeholder=' [...]'
        } = options

        this.width = width
        this.initial_indent = initial_indent
        this.subsequent_indent = subsequent_indent
        this.expand_tabs = expand_tabs
        this.replace_whitespace = replace_whitespace
        this.fix_sentence_endings = fix_sentence_endings
        this.break_long_words = break_long_words
        this.drop_whitespace = drop_whitespace
        this.break_on_hyphens = break_on_hyphens
        this.tabsize = tabsize
        this.max_lines = max_lines
        this.placeholder = placeholder
    }


    // -- Private methods -----------------------------------------------
    // (possibly useful for subclasses to override)

    _munge_whitespace(text) {
        /*
         *  _munge_whitespace(text : string) -> string
         *
         *  Munge whitespace in text: expand tabs and convert all other
         *  whitespace characters to spaces.  Eg. " foo\\tbar\\n\\nbaz"
         *  becomes " foo    bar  baz".
         */
        if (this.expand_tabs) {
            text = text.replace(/\t/g, ' '.repeat(this.tabsize)) // not strictly correct in js
        }
        if (this.replace_whitespace) {
            text = text.replace(/[\t\n\x0b\x0c\r]/g, ' ')
        }
        return text
    }

    _split(text) {
        /*
         *  _split(text : string) -> [string]
         *
         *  Split the text to wrap into indivisible chunks.  Chunks are
         *  not quite the same as words; see _wrap_chunks() for full
         *  details.  As an example, the text
         *    Look, goof-ball -- use the -b option!
         *  breaks into the following chunks:
         *    'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ',
         *    'use', ' ', 'the', ' ', '-b', ' ', 'option!'
         *  if break_on_hyphens is True, or in:
         *    'Look,', ' ', 'goof-ball', ' ', '--', ' ',
         *    'use', ' ', 'the', ' ', '-b', ' ', option!'
         *  otherwise.
         */
        let chunks = text.split(wordsep_simple_re)
        chunks = chunks.filter(Boolean)
        return chunks
    }

    _handle_long_word(reversed_chunks, cur_line, cur_len, width) {
        /*
         *  _handle_long_word(chunks : [string],
         *                    cur_line : [string],
         *                    cur_len : int, width : int)
         *
         *  Handle a chunk of text (most likely a word, not whitespace) that
         *  is too long to fit in any line.
         */
        // Figure out when indent is larger than the specified width, and make
        // sure at least one character is stripped off on every pass
        let space_left
        if (width < 1) {
            space_left = 1
        } else {
            space_left = width - cur_len
        }

        // If we're allowed to break long words, then do so: put as much
        // of the next chunk onto the current line as will fit.
        if (this.break_long_words) {
            cur_line.push(reversed_chunks[reversed_chunks.length - 1].slice(0, space_left))
            reversed_chunks[reversed_chunks.length - 1] = reversed_chunks[reversed_chunks.length - 1].slice(space_left)

        // Otherwise, we have to preserve the long word intact.  Only add
        // it to the current line if there's nothing already there --
        // that minimizes how much we violate the width constraint.
        } else if (!cur_line) {
            cur_line.push(...reversed_chunks.pop())
        }

        // If we're not allowed to break long words, and there's already
        // text on the current line, do nothing.  Next time through the
        // main loop of _wrap_chunks(), we'll wind up here again, but
        // cur_len will be zero, so the next line will be entirely
        // devoted to the long word that we can't handle right now.
    }

    _wrap_chunks(chunks) {
        /*
         *  _wrap_chunks(chunks : [string]) -> [string]
         *
         *  Wrap a sequence of text chunks and return a list of lines of
         *  length 'self.width' or less.  (If 'break_long_words' is false,
         *  some lines may be longer than this.)  Chunks correspond roughly
         *  to words and the whitespace between them: each chunk is
         *  indivisible (modulo 'break_long_words'), but a line break can
         *  come between any two chunks.  Chunks should not have internal
         *  whitespace; ie. a chunk is either all whitespace or a "word".
         *  Whitespace chunks will be removed from the beginning and end of
         *  lines, but apart from that whitespace is preserved.
         */
        let lines = []
        let indent
        if (this.width <= 0) {
            throw Error(`invalid width ${this.width} (must be > 0)`)
        }
        if (this.max_lines !== undefined) {
            if (this.max_lines > 1) {
                indent = this.subsequent_indent
            } else {
                indent = this.initial_indent
            }
            if (indent.length + this.placeholder.trimStart().length > this.width) {
                throw Error('placeholder too large for max width')
            }
        }

        // Arrange in reverse order so items can be efficiently popped
        // from a stack of chucks.
        chunks = chunks.reverse()

        while (chunks.length > 0) {

            // Start the list of chunks that will make up the current line.
            // cur_len is just the length of all the chunks in cur_line.
            let cur_line = []
            let cur_len = 0

            // Figure out which static string will prefix this line.
            let indent
            if (lines) {
                indent = this.subsequent_indent
            } else {
                indent = this.initial_indent
            }

            // Maximum width for this line.
            let width = this.width - indent.length

            // First chunk on line is whitespace -- drop it, unless this
            // is the very beginning of the text (ie. no lines started yet).
            if (this.drop_whitespace && chunks[chunks.length - 1].trim() === '' && lines.length > 0) {
                chunks.pop()
            }

            while (chunks.length > 0) {
                let l = chunks[chunks.length - 1].length

                // Can at least squeeze this chunk onto the current line.
                if (cur_len + l <= width) {
                    cur_line.push(chunks.pop())
                    cur_len += l

                // Nope, this line is full.
                } else {
                    break
                }
            }

            // The current line is full, and the next chunk is too big to
            // fit on *any* line (not just this one).
            if (chunks.length && chunks[chunks.length - 1].length > width) {
                this._handle_long_word(chunks, cur_line, cur_len, width)
                cur_len = cur_line.map(l => l.length).reduce((a, b) => a + b, 0)
            }

            // If the last chunk on this line is all whitespace, drop it.
            if (this.drop_whitespace && cur_line.length > 0 && cur_line[cur_line.length - 1].trim() === '') {
                cur_len -= cur_line[cur_line.length - 1].length
                cur_line.pop()
            }

            if (cur_line) {
                if (this.max_lines === undefined ||
                    lines.length + 1 < this.max_lines ||
                    (chunks.length === 0 ||
                     this.drop_whitespace &&
                     chunks.length === 1 &&
                     !chunks[0].trim()) && cur_len <= width) {
                    // Convert current line back to a string and store it in
                    // list of all lines (return value).
                    lines.push(indent + cur_line.join(''))
                } else {
                    let had_break = false
                    while (cur_line) {
                        if (cur_line[cur_line.length - 1].trim() &&
                            cur_len + this.placeholder.length <= width) {
                            cur_line.push(this.placeholder)
                            lines.push(indent + cur_line.join(''))
                            had_break = true
                            break
                        }
                        cur_len -= cur_line[-1].length
                        cur_line.pop()
                    }
                    if (!had_break) {
                        if (lines) {
                            let prev_line = lines[lines.length - 1].trimEnd()
                            if (prev_line.length + this.placeholder.length <=
                                    this.width) {
                                lines[lines.length - 1] = prev_line + this.placeholder
                                break
                            }
                        }
                        lines.push(indent + this.placeholder.lstrip())
                    }
                    break
                }
            }
        }

        return lines
    }

    _split_chunks(text) {
        text = this._munge_whitespace(text)
        return this._split(text)
    }

    // -- Public interface ----------------------------------------------

    wrap(text) {
        /*
         *  wrap(text : string) -> [string]
         *
         *  Reformat the single paragraph in 'text' so it fits in lines of
         *  no more than 'self.width' columns, and return a list of wrapped
         *  lines.  Tabs in 'text' are expanded with string.expandtabs(),
         *  and all other whitespace characters (including newline) are
         *  converted to space.
         */
        let chunks = this._split_chunks(text)
        // not implemented in js
        //if (this.fix_sentence_endings) {
        //    this._fix_sentence_endings(chunks)
        //}
        return this._wrap_chunks(chunks)
    }

    fill(text) {
        /*
         *  fill(text : string) -> string
         *
         *  Reformat the single paragraph in 'text' to fit in lines of no
         *  more than 'self.width' columns, and return a new string
         *  containing the entire wrapped paragraph.
         */
        return this.wrap(text).join('\n')
    }
}


// -- Convenience interface ---------------------------------------------

function wrap(text, options = {}) {
    /*
     *  Wrap a single paragraph of text, returning a list of wrapped lines.
     *
     *  Reformat the single paragraph in 'text' so it fits in lines of no
     *  more than 'width' columns, and return a list of wrapped lines.  By
     *  default, tabs in 'text' are expanded with string.expandtabs(), and
     *  all other whitespace characters (including newline) are converted to
     *  space.  See TextWrapper class for available keyword args to customize
     *  wrapping behaviour.
     */
    let { width = 70, ...kwargs } = options
    let w = new TextWrapper(Object.assign({ width }, kwargs))
    return w.wrap(text)
}

function fill(text, options = {}) {
    /*
     *  Fill a single paragraph of text, returning a new string.
     *
     *  Reformat the single paragraph in 'text' to fit in lines of no more
     *  than 'width' columns, and return a new string containing the entire
     *  wrapped paragraph.  As with wrap(), tabs are expanded and other
     *  whitespace characters converted to space.  See TextWrapper class for
     *  available keyword args to customize wrapping behaviour.
     */
    let { width = 70, ...kwargs } = options
    let w = new TextWrapper(Object.assign({ width }, kwargs))
    return w.fill(text)
}

// -- Loosely related functionality -------------------------------------

let _whitespace_only_re = /^[ \t]+$/mg
let _leading_whitespace_re = /(^[ \t]*)(?:[^ \t\n])/mg

function dedent(text) {
    /*
     *  Remove any common leading whitespace from every line in `text`.
     *
     *  This can be used to make triple-quoted strings line up with the left
     *  edge of the display, while still presenting them in the source code
     *  in indented form.
     *
     *  Note that tabs and spaces are both treated as whitespace, but they
     *  are not equal: the lines "  hello" and "\\thello" are
     *  considered to have no common leading whitespace.
     *
     *  Entirely blank lines are normalized to a newline character.
     */
    // Look for the longest leading string of spaces and tabs common to
    // all lines.
    let margin = undefined
    text = text.replace(_whitespace_only_re, '')
    let indents = text.match(_leading_whitespace_re) || []
    for (let indent of indents) {
        indent = indent.slice(0, -1)

        if (margin === undefined) {
            margin = indent

        // Current line more deeply indented than previous winner:
        // no change (previous winner is still on top).
        } else if (indent.startsWith(margin)) {
            // pass

        // Current line consistent with and no deeper than previous winner:
        // it's the new winner.
        } else if (margin.startsWith(indent)) {
            margin = indent

        // Find the largest common whitespace between current line and previous
        // winner.
        } else {
            for (let i = 0; i < margin.length && i < indent.length; i++) {
                if (margin[i] !== indent[i]) {
                    margin = margin.slice(0, i)
                    break
                }
            }
        }
    }

    if (margin) {
        text = text.replace(new RegExp('^' + margin, 'mg'), '')
    }
    return text
}

module.exports = { wrap, fill, dedent }
{
  "name": "argparse",
  "description": "CLI arguments parser. Native port of python's argparse.",
  "version": "2.0.1",
  "main": "argparse.js",
  "files": [
    "argparse.js",
    "lib/"
  ],
  "license": "Python-2.0",
  "repository": "nodeca/argparse",
  "devDependencies": {
    "@babel/eslint-parser": "^7.11.0",
    "@babel/plugin-syntax-class-properties": "^7.10.4",
    "eslint": "^7.5.0",
    "mocha": "^8.0.1",
    "nyc": "^15.1.0"
  }
}(The MIT License)

Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
Copyright (c) 2018-2021 Josh Junon

Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the 'Software'), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

{
  "name": "debug",
  "version": "4.4.3",
  "repository": {
    "type": "git",
    "url": "git://github.com/debug-js/debug.git"
  },
  "description": "Lightweight debugging utility for Node.js and the browser",
  "files": [
    "src",
    "LICENSE",
    "README.md"
  ],
  "author": "Josh Junon (https://github.com/qix-)",
  "license": "MIT",
  "dependencies": {
    "ms": "^2.1.3"
  },
  "devDependencies": {
    "brfs": "^2.0.1",
    "browserify": "^16.2.3",
    "coveralls": "^3.0.2",
    "karma": "^3.1.4",
    "karma-browserify": "^6.0.0",
    "karma-chrome-launcher": "^2.2.0",
    "karma-mocha": "^1.3.0",
    "mocha": "^5.2.0",
    "mocha-lcov-reporter": "^1.2.0",
    "sinon": "^14.0.0",
    "xo": "^0.23.0"
  },
  "peerDependenciesMeta": {
    "supports-color": {
      "optional": true
    }
  },
  "main": "./src/index.js",
  "browser": "./src/browser.js",
  "engines": {
    "node": ">=6.0"
  }
}/* eslint-env browser */

/**
 * This is the web browser implementation of `debug()`.
 */

exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.storage = localstorage();
exports.destroy = (() => {
	let warned = false;

	return () => {
		if (!warned) {
			warned = true;
			console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
		}
	};
})();

/**
 * Colors.
 */

exports.colors = [
	'#0000CC',
	'#0000FF',
	'#0033CC',
	'#0033FF',
	'#0066CC',
	'#0066FF',
	'#0099CC',
	'#0099FF',
	'#00CC00',
	'#00CC33',
	'#00CC66',
	'#00CC99',
	'#00CCCC',
	'#00CCFF',
	'#3300CC',
	'#3300FF',
	'#3333CC',
	'#3333FF',
	'#3366CC',
	'#3366FF',
	'#3399CC',
	'#3399FF',
	'#33CC00',
	'#33CC33',
	'#33CC66',
	'#33CC99',
	'#33CCCC',
	'#33CCFF',
	'#6600CC',
	'#6600FF',
	'#6633CC',
	'#6633FF',
	'#66CC00',
	'#66CC33',
	'#9900CC',
	'#9900FF',
	'#9933CC',
	'#9933FF',
	'#99CC00',
	'#99CC33',
	'#CC0000',
	'#CC0033',
	'#CC0066',
	'#CC0099',
	'#CC00CC',
	'#CC00FF',
	'#CC3300',
	'#CC3333',
	'#CC3366',
	'#CC3399',
	'#CC33CC',
	'#CC33FF',
	'#CC6600',
	'#CC6633',
	'#CC9900',
	'#CC9933',
	'#CCCC00',
	'#CCCC33',
	'#FF0000',
	'#FF0033',
	'#FF0066',
	'#FF0099',
	'#FF00CC',
	'#FF00FF',
	'#FF3300',
	'#FF3333',
	'#FF3366',
	'#FF3399',
	'#FF33CC',
	'#FF33FF',
	'#FF6600',
	'#FF6633',
	'#FF9900',
	'#FF9933',
	'#FFCC00',
	'#FFCC33'
];

/**
 * Currently only WebKit-based Web Inspectors, Firefox >= v31,
 * and the Firebug extension (any Firefox version) are known
 * to support "%c" CSS customizations.
 *
 * TODO: add a `localStorage` variable to explicitly enable/disable colors
 */

// eslint-disable-next-line complexity
function useColors() {
	// NB: In an Electron preload script, document will be defined but not fully
	// initialized. Since we know we're in Chrome, we'll just detect this case
	// explicitly
	if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
		return true;
	}

	// Internet Explorer and Edge do not support colors.
	if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
		return false;
	}

	let m;

	// Is webkit? http://stackoverflow.com/a/16459606/376773
	// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
	// eslint-disable-next-line no-return-assign
	return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
		// Is firebug? http://stackoverflow.com/a/398120/376773
		(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
		// Is firefox >= v31?
		// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
		(typeof navigator !== 'undefined' && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31) ||
		// Double check webkit in userAgent just in case we are in a worker
		(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
}

/**
 * Colorize log arguments if enabled.
 *
 * @api public
 */

function formatArgs(args) {
	args[0] = (this.useColors ? '%c' : '') +
		this.namespace +
		(this.useColors ? ' %c' : ' ') +
		args[0] +
		(this.useColors ? '%c ' : ' ') +
		'+' + module.exports.humanize(this.diff);

	if (!this.useColors) {
		return;
	}

	const c = 'color: ' + this.color;
	args.splice(1, 0, c, 'color: inherit');

	// The final "%c" is somewhat tricky, because there could be other
	// arguments passed either before or after the %c, so we need to
	// figure out the correct index to insert the CSS into
	let index = 0;
	let lastC = 0;
	args[0].replace(/%[a-zA-Z%]/g, match => {
		if (match === '%%') {
			return;
		}
		index++;
		if (match === '%c') {
			// We only are interested in the *last* %c
			// (the user may have provided their own)
			lastC = index;
		}
	});

	args.splice(lastC, 0, c);
}

/**
 * Invokes `console.debug()` when available.
 * No-op when `console.debug` is not a "function".
 * If `console.debug` is not available, falls back
 * to `console.log`.
 *
 * @api public
 */
exports.log = console.debug || console.log || (() => {});

/**
 * Save `namespaces`.
 *
 * @param {String} namespaces
 * @api private
 */
function save(namespaces) {
	try {
		if (namespaces) {
			exports.storage.setItem('debug', namespaces);
		} else {
			exports.storage.removeItem('debug');
		}
	} catch (error) {
		// Swallow
		// XXX (@Qix-) should we be logging these?
	}
}

/**
 * Load `namespaces`.
 *
 * @return {String} returns the previously persisted debug modes
 * @api private
 */
function load() {
	let r;
	try {
		r = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ;
	} catch (error) {
		// Swallow
		// XXX (@Qix-) should we be logging these?
	}

	// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
	if (!r && typeof process !== 'undefined' && 'env' in process) {
		r = process.env.DEBUG;
	}

	return r;
}

/**
 * Localstorage attempts to return the localstorage.
 *
 * This is necessary because safari throws
 * when a user disables cookies/localstorage
 * and you attempt to access it.
 *
 * @return {LocalStorage}
 * @api private
 */

function localstorage() {
	try {
		// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
		// The Browser also has localStorage in the global context.
		return localStorage;
	} catch (error) {
		// Swallow
		// XXX (@Qix-) should we be logging these?
	}
}

module.exports = require('./common')(exports);

const {formatters} = module.exports;

/**
 * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
 */

formatters.j = function (v) {
	try {
		return JSON.stringify(v);
	} catch (error) {
		return '[UnexpectedJSONParseError]: ' + error.message;
	}
};

/**
 * This is the common logic for both the Node.js and web browser
 * implementations of `debug()`.
 */

function setup(env) {
	createDebug.debug = createDebug;
	createDebug.default = createDebug;
	createDebug.coerce = coerce;
	createDebug.disable = disable;
	createDebug.enable = enable;
	createDebug.enabled = enabled;
	createDebug.humanize = require('ms');
	createDebug.destroy = destroy;

	Object.keys(env).forEach(key => {
		createDebug[key] = env[key];
	});

	/**
	* The currently active debug mode names, and names to skip.
	*/

	createDebug.names = [];
	createDebug.skips = [];

	/**
	* Map of special "%n" handling functions, for the debug "format" argument.
	*
	* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
	*/
	createDebug.formatters = {};

	/**
	* Selects a color for a debug namespace
	* @param {String} namespace The namespace string for the debug instance to be colored
	* @return {Number|String} An ANSI color code for the given namespace
	* @api private
	*/
	function selectColor(namespace) {
		let hash = 0;

		for (let i = 0; i < namespace.length; i++) {
			hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
			hash |= 0; // Convert to 32bit integer
		}

		return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
	}
	createDebug.selectColor = selectColor;

	/**
	* Create a debugger with the given `namespace`.
	*
	* @param {String} namespace
	* @return {Function}
	* @api public
	*/
	function createDebug(namespace) {
		let prevTime;
		let enableOverride = null;
		let namespacesCache;
		let enabledCache;

		function debug(...args) {
			// Disabled?
			if (!debug.enabled) {
				return;
			}

			const self = debug;

			// Set `diff` timestamp
			const curr = Number(new Date());
			const ms = curr - (prevTime || curr);
			self.diff = ms;
			self.prev = prevTime;
			self.curr = curr;
			prevTime = curr;

			args[0] = createDebug.coerce(args[0]);

			if (typeof args[0] !== 'string') {
				// Anything else let's inspect with %O
				args.unshift('%O');
			}

			// Apply any `formatters` transformations
			let index = 0;
			args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
				// If we encounter an escaped % then don't increase the array index
				if (match === '%%') {
					return '%';
				}
				index++;
				const formatter = createDebug.formatters[format];
				if (typeof formatter === 'function') {
					const val = args[index];
					match = formatter.call(self, val);

					// Now we need to remove `args[index]` since it's inlined in the `format`
					args.splice(index, 1);
					index--;
				}
				return match;
			});

			// Apply env-specific formatting (colors, etc.)
			createDebug.formatArgs.call(self, args);

			const logFn = self.log || createDebug.log;
			logFn.apply(self, args);
		}

		debug.namespace = namespace;
		debug.useColors = createDebug.useColors();
		debug.color = createDebug.selectColor(namespace);
		debug.extend = extend;
		debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.

		Object.defineProperty(debug, 'enabled', {
			enumerable: true,
			configurable: false,
			get: () => {
				if (enableOverride !== null) {
					return enableOverride;
				}
				if (namespacesCache !== createDebug.namespaces) {
					namespacesCache = createDebug.namespaces;
					enabledCache = createDebug.enabled(namespace);
				}

				return enabledCache;
			},
			set: v => {
				enableOverride = v;
			}
		});

		// Env-specific initialization logic for debug instances
		if (typeof createDebug.init === 'function') {
			createDebug.init(debug);
		}

		return debug;
	}

	function extend(namespace, delimiter) {
		const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
		newDebug.log = this.log;
		return newDebug;
	}

	/**
	* Enables a debug mode by namespaces. This can include modes
	* separated by a colon and wildcards.
	*
	* @param {String} namespaces
	* @api public
	*/
	function enable(namespaces) {
		createDebug.save(namespaces);
		createDebug.namespaces = namespaces;

		createDebug.names = [];
		createDebug.skips = [];

		const split = (typeof namespaces === 'string' ? namespaces : '')
			.trim()
			.replace(/\s+/g, ',')
			.split(',')
			.filter(Boolean);

		for (const ns of split) {
			if (ns[0] === '-') {
				createDebug.skips.push(ns.slice(1));
			} else {
				createDebug.names.push(ns);
			}
		}
	}

	/**
	 * Checks if the given string matches a namespace template, honoring
	 * asterisks as wildcards.
	 *
	 * @param {String} search
	 * @param {String} template
	 * @return {Boolean}
	 */
	function matchesTemplate(search, template) {
		let searchIndex = 0;
		let templateIndex = 0;
		let starIndex = -1;
		let matchIndex = 0;

		while (searchIndex < search.length) {
			if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) {
				// Match character or proceed with wildcard
				if (template[templateIndex] === '*') {
					starIndex = templateIndex;
					matchIndex = searchIndex;
					templateIndex++; // Skip the '*'
				} else {
					searchIndex++;
					templateIndex++;
				}
			} else if (starIndex !== -1) { // eslint-disable-line no-negated-condition
				// Backtrack to the last '*' and try to match more characters
				templateIndex = starIndex + 1;
				matchIndex++;
				searchIndex = matchIndex;
			} else {
				return false; // No match
			}
		}

		// Handle trailing '*' in template
		while (templateIndex < template.length && template[templateIndex] === '*') {
			templateIndex++;
		}

		return templateIndex === template.length;
	}

	/**
	* Disable debug output.
	*
	* @return {String} namespaces
	* @api public
	*/
	function disable() {
		const namespaces = [
			...createDebug.names,
			...createDebug.skips.map(namespace => '-' + namespace)
		].join(',');
		createDebug.enable('');
		return namespaces;
	}

	/**
	* Returns true if the given mode name is enabled, false otherwise.
	*
	* @param {String} name
	* @return {Boolean}
	* @api public
	*/
	function enabled(name) {
		for (const skip of createDebug.skips) {
			if (matchesTemplate(name, skip)) {
				return false;
			}
		}

		for (const ns of createDebug.names) {
			if (matchesTemplate(name, ns)) {
				return true;
			}
		}

		return false;
	}

	/**
	* Coerce `val`.
	*
	* @param {Mixed} val
	* @return {Mixed}
	* @api private
	*/
	function coerce(val) {
		if (val instanceof Error) {
			return val.stack || val.message;
		}
		return val;
	}

	/**
	* XXX DO NOT USE. This is a temporary stub function.
	* XXX It WILL be removed in the next major release.
	*/
	function destroy() {
		console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
	}

	createDebug.enable(createDebug.load());

	return createDebug;
}

module.exports = setup;
/**
 * Detect Electron renderer / nwjs process, which is node, but we should
 * treat as a browser.
 */

if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {
	module.exports = require('./browser.js');
} else {
	module.exports = require('./node.js');
}
/**
 * Module dependencies.
 */

const tty = require('tty');
const util = require('util');

/**
 * This is the Node.js implementation of `debug()`.
 */

exports.init = init;
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.destroy = util.deprecate(
	() => {},
	'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'
);

/**
 * Colors.
 */

exports.colors = [6, 2, 3, 4, 5, 1];

try {
	// Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
	// eslint-disable-next-line import/no-extraneous-dependencies
	const supportsColor = require('supports-color');

	if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
		exports.colors = [
			20,
			21,
			26,
			27,
			32,
			33,
			38,
			39,
			40,
			41,
			42,
			43,
			44,
			45,
			56,
			57,
			62,
			63,
			68,
			69,
			74,
			75,
			76,
			77,
			78,
			79,
			80,
			81,
			92,
			93,
			98,
			99,
			112,
			113,
			128,
			129,
			134,
			135,
			148,
			149,
			160,
			161,
			162,
			163,
			164,
			165,
			166,
			167,
			168,
			169,
			170,
			171,
			172,
			173,
			178,
			179,
			184,
			185,
			196,
			197,
			198,
			199,
			200,
			201,
			202,
			203,
			204,
			205,
			206,
			207,
			208,
			209,
			214,
			215,
			220,
			221
		];
	}
} catch (error) {
	// Swallow - we only care if `supports-color` is available; it doesn't have to be.
}

/**
 * Build up the default `inspectOpts` object from the environment variables.
 *
 *   $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
 */

exports.inspectOpts = Object.keys(process.env).filter(key => {
	return /^debug_/i.test(key);
}).reduce((obj, key) => {
	// Camel-case
	const prop = key
		.substring(6)
		.toLowerCase()
		.replace(/_([a-z])/g, (_, k) => {
			return k.toUpperCase();
		});

	// Coerce string value into JS value
	let val = process.env[key];
	if (/^(yes|on|true|enabled)$/i.test(val)) {
		val = true;
	} else if (/^(no|off|false|disabled)$/i.test(val)) {
		val = false;
	} else if (val === 'null') {
		val = null;
	} else {
		val = Number(val);
	}

	obj[prop] = val;
	return obj;
}, {});

/**
 * Is stdout a TTY? Colored output is enabled when `true`.
 */

function useColors() {
	return 'colors' in exports.inspectOpts ?
		Boolean(exports.inspectOpts.colors) :
		tty.isatty(process.stderr.fd);
}

/**
 * Adds ANSI color escape codes if enabled.
 *
 * @api public
 */

function formatArgs(args) {
	const {namespace: name, useColors} = this;

	if (useColors) {
		const c = this.color;
		const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c);
		const prefix = `  ${colorCode};1m${name} \u001B[0m`;

		args[0] = prefix + args[0].split('\n').join('\n' + prefix);
		args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m');
	} else {
		args[0] = getDate() + name + ' ' + args[0];
	}
}

function getDate() {
	if (exports.inspectOpts.hideDate) {
		return '';
	}
	return new Date().toISOString() + ' ';
}

/**
 * Invokes `util.formatWithOptions()` with the specified arguments and writes to stderr.
 */

function log(...args) {
	return process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + '\n');
}

/**
 * Save `namespaces`.
 *
 * @param {String} namespaces
 * @api private
 */
function save(namespaces) {
	if (namespaces) {
		process.env.DEBUG = namespaces;
	} else {
		// If you set a process.env field to null or undefined, it gets cast to the
		// string 'null' or 'undefined'. Just delete instead.
		delete process.env.DEBUG;
	}
}

/**
 * Load `namespaces`.
 *
 * @return {String} returns the previously persisted debug modes
 * @api private
 */

function load() {
	return process.env.DEBUG;
}

/**
 * Init logic for `debug` instances.
 *
 * Create a new `inspectOpts` object in case `useColors` is set
 * differently for a particular `debug` instance.
 */

function init(debug) {
	debug.inspectOpts = {};

	const keys = Object.keys(exports.inspectOpts);
	for (let i = 0; i < keys.length; i++) {
		debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
	}
}

module.exports = require('./common')(exports);

const {formatters} = module.exports;

/**
 * Map %o to `util.inspect()`, all on a single line.
 */

formatters.o = function (v) {
	this.inspectOpts.colors = this.useColors;
	return util.inspect(v, this.inspectOpts)
		.split('\n')
		.map(str => str.trim())
		.join(' ');
};

/**
 * Map %O to `util.inspect()`, allowing multiple lines if needed.
 */

formatters.O = function (v) {
	this.inspectOpts.colors = this.useColors;
	return util.inspect(v, this.inspectOpts);
};
The MIT License (MIT)

Copyright (c) 2016 Alexey Prokhorov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.'use strict';

const main = require('./src/main');

module.exports = main;
'use strict';

const node = require('./src/node');

module.exports = node;
{
  "name": "electron-log",
  "version": "5.4.3",
  "description": "Just a simple logging module for your Electron application",
  "main": "src/index.js",
  "browser": "src/renderer/index.js",
  "engines": {
    "node": ">= 14"
  },
  "typings": "src/index.d.ts",
  "repository": "megahertz/electron-log",
  "files": [
    "src/*",
    "!**/__specs__",
    "!**/.*",
    "main.js",
    "main.d.ts",
    "node.js",
    "node.d.ts",
    "preload.js",
    "renderer.js",
    "renderer.d.ts"
  ],
  "author": "Alexey Prokhorov",
  "license": "MIT",
  "homepage": "https://github.com/megahertz/electron-log#readme",
  "devDependencies": {
    "@types/node": "^20.10.6",
    "electron": "*",
    "eslint": "^8.56.0",
    "eslint-config-airbnb-base": "^15.0.0",
    "eslint-plugin-import": "^2.29.1",
    "humile": "^0.5.3",
    "nw": "^0.100.1",
    "typescript": "^5.3.3",
    "vite": "^4.5.9",
    "vite-plugin-electron": "^0.15.5",
    "vite-plugin-electron-renderer": "^0.14.5",
    "webpack": "^5.89.0",
    "webpack-cli": "^5.1.4"
  }
}'use strict';

const preload = require('./src/renderer/electron-log-preload');

module.exports = preload;
'use strict';

const renderer = require('./src/renderer');

module.exports = renderer;
'use strict';

class Buffering {
  constructor({ processMessage }) {
    this.processMessage = processMessage;
    this.buffer = [];
    this.enabled = false;

    this.begin = this.begin.bind(this);
    this.commit = this.commit.bind(this);
    this.reject = this.reject.bind(this);
  }

  addMessage(message) {
    this.buffer.push(message);
  }

  begin() {
    this.enabled = [];
  }

  commit() {
    this.enabled = false;
    this.buffer.forEach((item) => this.processMessage(item));
    this.buffer = [];
  }

  reject() {
    this.enabled = false;
    this.buffer = [];
  }
}

module.exports = Buffering;
'use strict';

const scopeFactory = require('./scope');
const Buffering = require('./Buffering');

/**
 * @property {Function} error
 * @property {Function} warn
 * @property {Function} info
 * @property {Function} verbose
 * @property {Function} debug
 * @property {Function} silly
 */
class Logger {
  static instances = {};

  dependencies = {};
  errorHandler = null;
  eventLogger = null;
  functions = {};
  hooks = [];
  isDev = false;
  levels = null;
  logId = null;
  scope = null;
  transports = {};
  variables = {};

  constructor({
    allowUnknownLevel = false,
    dependencies = {},
    errorHandler,
    eventLogger,
    initializeFn,
    isDev = false,
    levels = ['error', 'warn', 'info', 'verbose', 'debug', 'silly'],
    logId,
    transportFactories = {},
    variables,
  } = {}) {
    this.addLevel = this.addLevel.bind(this);
    this.create = this.create.bind(this);
    this.initialize = this.initialize.bind(this);
    this.logData = this.logData.bind(this);
    this.processMessage = this.processMessage.bind(this);

    this.allowUnknownLevel = allowUnknownLevel;
    this.buffering = new Buffering(this);
    this.dependencies = dependencies;
    this.initializeFn = initializeFn;
    this.isDev = isDev;
    this.levels = levels;
    this.logId = logId;
    this.scope = scopeFactory(this);
    this.transportFactories = transportFactories;
    this.variables = variables || {};

    for (const name of this.levels) {
      this.addLevel(name, false);
    }
    this.log = this.info;
    this.functions.log = this.log;

    this.errorHandler = errorHandler;
    errorHandler?.setOptions({ ...dependencies, logFn: this.error });

    this.eventLogger = eventLogger;
    eventLogger?.setOptions({ ...dependencies, logger: this });

    for (const [name, factory] of Object.entries(transportFactories)) {
      this.transports[name] = factory(this, dependencies);
    }

    Logger.instances[logId] = this;
  }

  static getInstance({ logId }) {
    return this.instances[logId] || this.instances.default;
  }

  addLevel(level, index = this.levels.length) {
    if (index !== false) {
      this.levels.splice(index, 0, level);
    }

    this[level] = (...args) => this.logData(args, { level });
    this.functions[level] = this[level];
  }

  catchErrors(options) {
    this.processMessage(
      {
        data: ['log.catchErrors is deprecated. Use log.errorHandler instead'],
        level: 'warn',
      },
      { transports: ['console'] },
    );
    return this.errorHandler.startCatching(options);
  }

  create(options) {
    if (typeof options === 'string') {
      options = { logId: options };
    }

    return new Logger({
      dependencies: this.dependencies,
      errorHandler: this.errorHandler,
      initializeFn: this.initializeFn,
      isDev: this.isDev,
      transportFactories: this.transportFactories,
      variables: { ...this.variables },
      ...options,
    });
  }

  compareLevels(passLevel, checkLevel, levels = this.levels) {
    const pass = levels.indexOf(passLevel);
    const check = levels.indexOf(checkLevel);

    if (check === -1 || pass === -1) {
      return true;
    }

    return check <= pass;
  }

  initialize(options = {}) {
    this.initializeFn({ logger: this, ...this.dependencies, ...options });
  }

  logData(data, options = {}) {
    if (this.buffering.enabled) {
      this.buffering.addMessage({ data, date: new Date(), ...options });
    } else {
      this.processMessage({ data, ...options });
    }
  }

  processMessage(message, { transports = this.transports } = {}) {
    if (message.cmd === 'errorHandler') {
      this.errorHandler.handle(message.error, {
        errorName: message.errorName,
        processType: 'renderer',
        showDialog: Boolean(message.showDialog),
      });
      return;
    }

    let level = message.level;
    if (!this.allowUnknownLevel) {
      level = this.levels.includes(message.level) ? message.level : 'info';
    }

    const normalizedMessage = {
      date: new Date(),
      logId: this.logId,
      ...message,
      level,
      variables: {
        ...this.variables,
        ...message.variables,
      },
    };

    for (const [transName, transFn] of this.transportEntries(transports)) {
      if (typeof transFn !== 'function' || transFn.level === false) {
        continue;
      }

      if (!this.compareLevels(transFn.level, message.level)) {
        continue;
      }

      try {
        // eslint-disable-next-line arrow-body-style
        const transformedMsg = this.hooks.reduce((msg, hook) => {
          return msg ? hook(msg, transFn, transName) : msg;
        }, normalizedMessage);

        if (transformedMsg) {
          transFn({ ...transformedMsg, data: [...transformedMsg.data] });
        }
      } catch (e) {
        this.processInternalErrorFn(e);
      }
    }
  }

  processInternalErrorFn(_e) {
    // Do nothing by default
  }

  transportEntries(transports = this.transports) {
    const transportArray = Array.isArray(transports)
      ? transports
      : Object.entries(transports);

    return transportArray
      .map((item) => {
        switch (typeof item) {
          case 'string':
            return this.transports[item] ? [item, this.transports[item]] : null;
          case 'function':
            return [item.name, item];
          default:
            return Array.isArray(item) ? item : null;
        }
      })
      .filter(Boolean);
  }
}

module.exports = Logger;
'use strict';

module.exports = scopeFactory;

function scopeFactory(logger) {
  return Object.defineProperties(scope, {
    defaultLabel: { value: '', writable: true },
    labelPadding: { value: true, writable: true },
    maxLabelLength: { value: 0, writable: true },
    labelLength: {
      get() {
        switch (typeof scope.labelPadding) {
          case 'boolean': return scope.labelPadding ? scope.maxLabelLength : 0;
          case 'number': return scope.labelPadding;
          default: return 0;
        }
      },
    },
  });

  function scope(label) {
    scope.maxLabelLength = Math.max(scope.maxLabelLength, label.length);

    const newScope = {};
    for (const level of logger.levels) {
      newScope[level] = (...d) => logger.logData(d, { level, scope: label });
    }
    newScope.log = newScope.info;
    return newScope;
  }
}
'use strict';

const { transform } = require('./transform');

module.exports = {
  concatFirstStringElements,
  formatScope,
  formatText,
  formatVariables,
  timeZoneFromOffset,

  format({ message, logger, transport, data = message?.data }) {
    switch (typeof transport.format) {
      case 'string': {
        return transform({
          message,
          logger,
          transforms: [formatVariables, formatScope, formatText],
          transport,
          initialData: [transport.format, ...data],
        });
      }

      case 'function': {
        return transport.format({
          data,
          level: message?.level || 'info',
          logger,
          message,
          transport,
        });
      }

      default: {
        return data;
      }
    }
  },
};

/**
 * The first argument of console.log may contain a template. In the library
 * the first element is a string related to transports.console.format. So
 * this function concatenates first two elements to make templates like %d
 * work
 * @param {*[]} data
 * @return {*[]}
 */
function concatFirstStringElements({ data }) {
  if (typeof data[0] !== 'string' || typeof data[1] !== 'string') {
    return data;
  }

  if (data[0].match(/%[1cdfiOos]/)) {
    return data;
  }

  return [`${data[0]} ${data[1]}`, ...data.slice(2)];
}

function timeZoneFromOffset(minutesOffset) {
  const minutesPositive = Math.abs(minutesOffset);
  const sign = minutesOffset > 0 ? '-' : '+';
  const hours = Math.floor(minutesPositive / 60).toString().padStart(2, '0');
  const minutes = (minutesPositive % 60).toString().padStart(2, '0');
  return `${sign}${hours}:${minutes}`;
}

function formatScope({ data, logger, message }) {
  const { defaultLabel, labelLength } = logger?.scope || {};
  const template = data[0];
  let label = message.scope;

  if (!label) {
    label = defaultLabel;
  }

  let scopeText;
  if (label === '') {
    scopeText = labelLength > 0 ? ''.padEnd(labelLength + 3) : '';
  } else if (typeof label === 'string') {
    scopeText = ` (${label})`.padEnd(labelLength + 3);
  } else {
    scopeText = '';
  }

  data[0] = template.replace('{scope}', scopeText);
  return data;
}

function formatVariables({ data, message }) {
  let template = data[0];
  if (typeof template !== 'string') {
    return data;
  }

  // Add additional space to the end of {level}] template to align messages
  template = template.replace('{level}]', `${message.level}]`.padEnd(6, ' '));

  const date = message.date || new Date();
  data[0] = template
    .replace(/\{(\w+)}/g, (substring, name) => {
      switch (name) {
        case 'level': return message.level || 'info';
        case 'logId': return message.logId;

        case 'y': return date.getFullYear().toString(10);
        case 'm': return (date.getMonth() + 1).toString(10).padStart(2, '0');
        case 'd': return date.getDate().toString(10).padStart(2, '0');
        case 'h': return date.getHours().toString(10).padStart(2, '0');
        case 'i': return date.getMinutes().toString(10).padStart(2, '0');
        case 's': return date.getSeconds().toString(10).padStart(2, '0');
        case 'ms': return date.getMilliseconds().toString(10).padStart(3, '0');
        case 'z': return timeZoneFromOffset(date.getTimezoneOffset());
        case 'iso': return date.toISOString();

        default: {
          return message.variables?.[name] || substring;
        }
      }
    })
    .trim();

  return data;
}

function formatText({ data }) {
  const template = data[0];
  if (typeof template !== 'string') {
    return data;
  }

  const textTplPosition = template.lastIndexOf('{text}');
  if (textTplPosition === template.length - 6) {
    data[0] = template.replace(/\s?{text}/, '');
    if (data[0] === '') {
      data.shift();
    }

    return data;
  }

  const templatePieces = template.split('{text}');
  let result = [];

  if (templatePieces[0] !== '') {
    result.push(templatePieces[0]);
  }

  result = result.concat(data.slice(1));

  if (templatePieces[1] !== '') {
    result.push(templatePieces[1]);
  }

  return result;
}
'use strict';

module.exports = {
  transformStyles,

  applyAnsiStyles({ data }) {
    return transformStyles(data, styleToAnsi, resetAnsiStyle);
  },

  removeStyles({ data }) {
    return transformStyles(data, () => '');
  },
};

const ANSI_COLORS = {
  unset: '\x1b[0m',
  black: '\x1b[30m',
  red: '\x1b[31m',
  green: '\x1b[32m',
  yellow: '\x1b[33m',
  blue: '\x1b[34m',
  magenta: '\x1b[35m',
  cyan: '\x1b[36m',
  white: '\x1b[37m',
  gray: '\x1b[90m',
};

function styleToAnsi(style) {
  const color = style.replace(/color:\s*(\w+).*/, '$1').toLowerCase();
  return ANSI_COLORS[color] || '';
}

function resetAnsiStyle(string) {
  return string + ANSI_COLORS.unset;
}

function transformStyles(data, onStyleFound, onStyleApplied) {
  const foundStyles = {};

  return data.reduce((result, item, index, array) => {
    if (foundStyles[index]) {
      return result;
    }

    if (typeof item === 'string') {
      let valueIndex = index;
      let styleApplied = false;

      item = item.replace(/%[1cdfiOos]/g, (match) => {
        valueIndex += 1;

        if (match !== '%c') {
          return match;
        }

        const style = array[valueIndex];
        if (typeof style === 'string') {
          foundStyles[valueIndex] = true;
          styleApplied = true;
          return onStyleFound(style, item);
        }

        return match;
      });

      if (styleApplied && onStyleApplied) {
        item = onStyleApplied(item);
      }
    }

    result.push(item);
    return result;
  }, []);
}
'use strict';

module.exports = { transform };

function transform({
  logger,
  message,
  transport,

  initialData = message?.data || [],
  transforms = transport?.transforms,
}) {
  return transforms.reduce((data, trans) => {
    if (typeof trans === 'function') {
      return trans({ data, logger, message, transport });
    }

    return data;
  }, initialData);
}
'use strict';

/* eslint-disable global-require */

const isRenderer = typeof process === 'undefined'
  || (process.type === 'renderer' || process.type === 'worker');

const isMain = typeof process === 'object' && process.type === 'browser';

if (isRenderer) {
  // Makes sense when contextIsolation/sandbox disabled
  require('./renderer/electron-log-preload');
  module.exports = require('./renderer');
} else if (isMain) {
  module.exports = require('./main');
} else {
  module.exports = require('./node');
}
'use strict';

const path = require('path');
const NodeExternalApi = require('../node/NodeExternalApi');

class ElectronExternalApi extends NodeExternalApi {
  /**
   * @type {typeof Electron}
   */
  electron = undefined;

  /**
   * @param {object} options
   * @param {typeof Electron} [options.electron]
   */
  constructor({ electron } = {}) {
    super();
    this.electron = electron;
  }

  getAppName() {
    let appName;
    try {
      appName = this.appName
        || this.electron.app?.name
        || this.electron.app?.getName();
    } catch {
      // fallback to default value below
    }
    return appName || super.getAppName();
  }

  getAppUserDataPath(appName) {
    return this.getPath('userData') || super.getAppUserDataPath(appName);
  }

  getAppVersion() {
    let appVersion;
    try {
      appVersion = this.electron.app?.getVersion();
    } catch {
      // fallback to default value below
    }
    return appVersion || super.getAppVersion();
  }

  getElectronLogPath() {
    return this.getPath('logs') || super.getElectronLogPath();
  }

  /**
   * @private
   * @param {any} name
   * @returns {string|undefined}
   */
  getPath(name) {
    try {
      return this.electron.app?.getPath(name);
    } catch {
      return undefined;
    }
  }

  getVersions() {
    return {
      app: `${this.getAppName()} ${this.getAppVersion()}`,
      electron: `Electron ${process.versions.electron}`,
      os: this.getOsVersion(),
    };
  }

  getSystemPathAppData() {
    return this.getPath('appData') || super.getSystemPathAppData();
  }

  isDev() {
    if (this.electron.app?.isPackaged !== undefined) {
      return !this.electron.app.isPackaged;
    }

    if (typeof process.execPath === 'string') {
      const execFileName = path.basename(process.execPath).toLowerCase();
      return execFileName.startsWith('electron');
    }

    return super.isDev();
  }

  onAppEvent(eventName, handler) {
    this.electron.app?.on(eventName, handler);

    return () => {
      this.electron.app?.off(eventName, handler);
    };
  }

  onAppReady(handler) {
    if (this.electron.app?.isReady()) {
      handler();
    } else if (this.electron.app?.once) {
      this.electron.app?.once('ready', handler);
    } else {
      handler();
    }
  }

  onEveryWebContentsEvent(eventName, handler) {
    this.electron.webContents?.getAllWebContents()?.forEach((webContents) => {
      webContents.on(eventName, handler);
    });

    this.electron.app?.on('web-contents-created', onWebContentsCreated);

    return () => {
      this.electron.webContents?.getAllWebContents().forEach((webContents) => {
        webContents.off(eventName, handler);
      });

      this.electron.app?.off('web-contents-created', onWebContentsCreated);
    };

    function onWebContentsCreated(_, webContents) {
      webContents.on(eventName, handler);
    }
  }

  /**
   * Listen to async messages sent from opposite process
   * @param {string} channel
   * @param {function} listener
   */
  onIpc(channel, listener) {
    this.electron.ipcMain?.on(channel, listener);
  }

  onIpcInvoke(channel, listener) {
    this.electron.ipcMain?.handle?.(channel, listener);
  }

  /**
   * @param {string} url
   * @param {Function} [logFunction]
   */
  openUrl(url, logFunction = console.error) { // eslint-disable-line no-console
    this.electron.shell?.openExternal(url).catch(logFunction);
  }

  setPreloadFileForSessions({
    filePath,
    includeFutureSession = true,
    getSessions = () => [this.electron.session?.defaultSession],
  }) {
    for (const session of getSessions().filter(Boolean)) {
      setPreload(session);
    }

    if (includeFutureSession) {
      this.onAppEvent('session-created', (session) => {
        setPreload(session);
      });
    }

    /**
     * @param {Session} session
     */
    function setPreload(session) {
      if (typeof session.registerPreloadScript === 'function') {
        session.registerPreloadScript({
          filePath,
          id: 'electron-log-preload',
          type: 'frame',
        });
      } else {
        session.setPreloads([...session.getPreloads(), filePath]);
      }
    }
  }

  /**
   * Sent a message to opposite process
   * @param {string} channel
   * @param {any} message
   */
  sendIpc(channel, message) {
    this.electron.BrowserWindow?.getAllWindows()?.forEach((wnd) => {
      if (
        wnd.webContents?.isDestroyed() === false
        && wnd.webContents?.isCrashed() === false
      ) {
        wnd.webContents.send(channel, message);
      }
    });
  }

  showErrorBox(title, message) {
    this.electron.dialog?.showErrorBox(title, message);
  }
}

module.exports = ElectronExternalApi;
'use strict';

const electron = require('electron');
const ElectronExternalApi = require('./ElectronExternalApi');
const { initialize } = require('./initialize');
const createDefaultLogger = require('../node/createDefaultLogger');

const externalApi = new ElectronExternalApi({ electron });
const defaultLogger = createDefaultLogger({
  dependencies: { externalApi },
  initializeFn: initialize,
});

module.exports = defaultLogger;

externalApi.onIpc('__ELECTRON_LOG__', (_, message) => {
  if (message.scope) {
    defaultLogger.Logger.getInstance(message).scope(message.scope);
  }

  const date = new Date(message.date);
  processMessage({
    ...message,
    date: date.getTime() ? date : new Date(),
  });
});

externalApi.onIpcInvoke('__ELECTRON_LOG__', (_, { cmd = '', logId }) => {
  switch (cmd) {
    case 'getOptions': {
      const logger = defaultLogger.Logger.getInstance({ logId });
      return {
        levels: logger.levels,
        logId,
      };
    }

    default: {
      processMessage({ data: [`Unknown cmd '${cmd}'`], level: 'error' });
      return {};
    }
  }
});

function processMessage(message) {
  defaultLogger.Logger.getInstance(message)?.processMessage(message);
}
'use strict';

const fs = require('fs');
const os = require('os');
const path = require('path');
const preloadInitializeFn = require('../renderer/electron-log-preload');

let preloadInitialized = false;
let spyConsoleInitialized = false;

module.exports = {
  initialize({
    externalApi,
    getSessions,
    includeFutureSession,
    logger,
    preload = true,
    spyRendererConsole = false,
  }) {
    externalApi.onAppReady(() => {
      try {
        if (preload) {
          initializePreload({
            externalApi,
            getSessions,
            includeFutureSession,
            logger,
            preloadOption: preload,
          });
        }

        if (spyRendererConsole) {
          initializeSpyRendererConsole({ externalApi, logger });
        }
      } catch (err) {
        logger.warn(err);
      }
    });
  },
};

function initializePreload({
  externalApi,
  getSessions,
  includeFutureSession,
  logger,
  preloadOption,
}) {
  let preloadPath = typeof preloadOption === 'string'
    ? preloadOption
    : undefined;

  if (preloadInitialized) {
    logger.warn(new Error('log.initialize({ preload }) already called').stack);
    return;
  }

  preloadInitialized = true;

  try {
    preloadPath = path.resolve(
      __dirname,
      '../renderer/electron-log-preload.js',
    );
  } catch {
    // Ignore, the file is bundled to ESM
  }

  if (!preloadPath || !fs.existsSync(preloadPath)) {
    preloadPath = path.join(
      externalApi.getAppUserDataPath() || os.tmpdir(),
      'electron-log-preload.js',
    );
    const preloadCode = `
      try {
        (${preloadInitializeFn.toString()})(require('electron'));
      } catch(e) {
        console.error(e);
      }
    `;
    fs.writeFileSync(preloadPath, preloadCode, 'utf8');
  }

  externalApi.setPreloadFileForSessions({
    filePath: preloadPath,
    includeFutureSession,
    getSessions,
  });
}

function initializeSpyRendererConsole({ externalApi, logger }) {
  if (spyConsoleInitialized) {
    logger.warn(
      new Error('log.initialize({ spyRendererConsole }) already called').stack,
    );
    return;
  }

  spyConsoleInitialized = true;

  const levels = ['debug', 'info', 'warn', 'error'];
  externalApi.onEveryWebContentsEvent(
    'console-message',
    (event, level, message) => {
      logger.processMessage({
        data: [message],
        level: levels[level],
        variables: { processType: 'renderer' },
      });
    },
  );
}
'use strict';

class ErrorHandler {
  externalApi = undefined;
  isActive = false;
  logFn = undefined;
  onError = undefined;
  showDialog = true;

  constructor({
    externalApi,
    logFn = undefined,
    onError = undefined,
    showDialog = undefined,
  } = {}) {
    this.createIssue = this.createIssue.bind(this);
    this.handleError = this.handleError.bind(this);
    this.handleRejection = this.handleRejection.bind(this);
    this.setOptions({ externalApi, logFn, onError, showDialog });
    this.startCatching = this.startCatching.bind(this);
    this.stopCatching = this.stopCatching.bind(this);
  }

  handle(error, {
    logFn = this.logFn,
    onError = this.onError,
    processType = 'browser',
    showDialog = this.showDialog,
    errorName = '',
  } = {}) {
    error = normalizeError(error);

    try {
      if (typeof onError === 'function') {
        const versions = this.externalApi?.getVersions() || {};
        const createIssue = this.createIssue;
        const result = onError({
          createIssue,
          error,
          errorName,
          processType,
          versions,
        });
        if (result === false) {
          return;
        }
      }

      errorName ? logFn(errorName, error) : logFn(error);

      if (showDialog && !errorName.includes('rejection') && this.externalApi) {
        this.externalApi.showErrorBox(
          `A JavaScript error occurred in the ${processType} process`,
          error.stack,
        );
      }
    } catch {
      console.error(error); // eslint-disable-line no-console
    }
  }

  setOptions({ externalApi, logFn, onError, showDialog }) {
    if (typeof externalApi === 'object') {
      this.externalApi = externalApi;
    }

    if (typeof logFn === 'function') {
      this.logFn = logFn;
    }

    if (typeof onError === 'function') {
      this.onError = onError;
    }

    if (typeof showDialog === 'boolean') {
      this.showDialog = showDialog;
    }
  }

  startCatching({ onError, showDialog } = {}) {
    if (this.isActive) {
      return;
    }

    this.isActive = true;
    this.setOptions({ onError, showDialog });
    process.on('uncaughtException', this.handleError);
    process.on('unhandledRejection', this.handleRejection);
  }

  stopCatching() {
    this.isActive = false;
    process.removeListener('uncaughtException', this.handleError);
    process.removeListener('unhandledRejection', this.handleRejection);
  }

  createIssue(pageUrl, queryParams) {
    this.externalApi?.openUrl(
      `${pageUrl}?${new URLSearchParams(queryParams).toString()}`,
    );
  }

  handleError(error) {
    this.handle(error, { errorName: 'Unhandled' });
  }

  handleRejection(reason) {
    const error = reason instanceof Error
      ? reason
      : new Error(JSON.stringify(reason));
    this.handle(error, { errorName: 'Unhandled rejection' });
  }
}

function normalizeError(e) {
  if (e instanceof Error) {
    return e;
  }

  if (e && typeof e === 'object') {
    if (e.message) {
      return Object.assign(new Error(e.message), e);
    }
    try {
      return new Error(JSON.stringify(e));
    } catch (serErr) {
      return new Error(`Couldn't normalize error ${String(e)}: ${serErr}`);
    }
  }

  return new Error(`Can't normalize error ${String(e)}`);
}

module.exports = ErrorHandler;
'use strict';

class EventLogger {
  disposers = [];
  format = '{eventSource}#{eventName}:';
  formatters = {
    app: {
      'certificate-error': ({ args }) => {
        return this.arrayToObject(args.slice(1, 4), [
          'url',
          'error',
          'certificate',
        ]);
      },
      'child-process-gone': ({ args }) => {
        return args.length === 1 ? args[0] : args;
      },
      'render-process-gone': ({ args: [webContents, details] }) => {
        return details && typeof details === 'object'
          ? { ...details, ...this.getWebContentsDetails(webContents) }
          : [];
      },
    },

    webContents: {
      'console-message': ({ args: [level, message, line, sourceId] }) => {
        // 0: debug, 1: info, 2: warning, 3: error
        if (level < 3) {
          return undefined;
        }

        return { message, source: `${sourceId}:${line}` };
      },
      'did-fail-load': ({ args }) => {
        return this.arrayToObject(args, [
          'errorCode',
          'errorDescription',
          'validatedURL',
          'isMainFrame',
          'frameProcessId',
          'frameRoutingId',
        ]);
      },
      'did-fail-provisional-load': ({ args }) => {
        return this.arrayToObject(args, [
          'errorCode',
          'errorDescription',
          'validatedURL',
          'isMainFrame',
          'frameProcessId',
          'frameRoutingId',
        ]);
      },
      'plugin-crashed': ({ args }) => {
        return this.arrayToObject(args, ['name', 'version']);
      },
      'preload-error': ({ args }) => {
        return this.arrayToObject(args, ['preloadPath', 'error']);
      },
    },
  };

  events = {
    app: {
      'certificate-error': true,
      'child-process-gone': true,
      'render-process-gone': true,
    },

    webContents: {
      // 'console-message': true,
      'did-fail-load': true,
      'did-fail-provisional-load': true,
      'plugin-crashed': true,
      'preload-error': true,
      'unresponsive': true,
    },
  };

  externalApi = undefined;
  level = 'error';
  scope = '';

  constructor(options = {}) {
    this.setOptions(options);
  }

  setOptions({
    events,
    externalApi,
    level,
    logger,
    format,
    formatters,
    scope,
  }) {
    if (typeof events === 'object') {
      this.events = events;
    }

    if (typeof externalApi === 'object') {
      this.externalApi = externalApi;
    }

    if (typeof level === 'string') {
      this.level = level;
    }

    if (typeof logger === 'object') {
      this.logger = logger;
    }

    if (typeof format === 'string' || typeof format === 'function') {
      this.format = format;
    }

    if (typeof formatters === 'object') {
      this.formatters = formatters;
    }

    if (typeof scope === 'string') {
      this.scope = scope;
    }
  }

  startLogging(options = {}) {
    this.setOptions(options);

    this.disposeListeners();

    for (const eventName of this.getEventNames(this.events.app)) {
      this.disposers.push(
        this.externalApi.onAppEvent(eventName, (...handlerArgs) => {
          this.handleEvent({ eventSource: 'app', eventName, handlerArgs });
        }),
      );
    }

    for (const eventName of this.getEventNames(this.events.webContents)) {
      this.disposers.push(
        this.externalApi.onEveryWebContentsEvent(
          eventName,
          (...handlerArgs) => {
            this.handleEvent(
              { eventSource: 'webContents', eventName, handlerArgs },
            );
          },
        ),
      );
    }
  }

  stopLogging() {
    this.disposeListeners();
  }

  arrayToObject(array, fieldNames) {
    const obj = {};

    fieldNames.forEach((fieldName, index) => {
      obj[fieldName] = array[index];
    });

    if (array.length > fieldNames.length) {
      obj.unknownArgs = array.slice(fieldNames.length);
    }

    return obj;
  }

  disposeListeners() {
    this.disposers.forEach((disposer) => disposer());
    this.disposers = [];
  }

  formatEventLog({ eventName, eventSource, handlerArgs }) {
    const [event, ...args] = handlerArgs;
    if (typeof this.format === 'function') {
      return this.format({ args, event, eventName, eventSource });
    }

    const formatter = this.formatters[eventSource]?.[eventName];
    let formattedArgs = args;
    if (typeof formatter === 'function') {
      formattedArgs = formatter({ args, event, eventName, eventSource });
    }

    if (!formattedArgs) {
      return undefined;
    }

    const eventData = {};

    if (Array.isArray(formattedArgs)) {
      eventData.args = formattedArgs;
    } else if (typeof formattedArgs === 'object') {
      Object.assign(eventData, formattedArgs);
    }

    if (eventSource === 'webContents') {
      Object.assign(eventData, this.getWebContentsDetails(event?.sender));
    }

    const title = this.format
      .replace('{eventSource}', eventSource === 'app' ? 'App' : 'WebContents')
      .replace('{eventName}', eventName);

    return [title, eventData];
  }

  getEventNames(eventMap) {
    if (!eventMap || typeof eventMap !== 'object') {
      return [];
    }

    return Object.entries(eventMap)
      .filter(([_, listen]) => listen)
      .map(([eventName]) => eventName);
  }

  getWebContentsDetails(webContents) {
    if (!webContents?.loadURL) {
      return {};
    }

    try {
      return {
        webContents: {
          id: webContents.id,
          url: webContents.getURL(),
        },
      };
    } catch {
      return {};
    }
  }

  handleEvent({ eventName, eventSource, handlerArgs }) {
    const log = this.formatEventLog({ eventName, eventSource, handlerArgs });
    if (log) {
      const logFns = this.scope ? this.logger.scope(this.scope) : this.logger;
      logFns?.[this.level]?.(...log);
    }
  }
}

module.exports = EventLogger;
'use strict';

/* eslint-disable no-unused-vars */

const childProcess = require('child_process');
const os = require('os');
const path = require('path');
const packageJson = require('./packageJson');

class NodeExternalApi {
  appName = undefined;
  appPackageJson = undefined;
  platform = process.platform;

  getAppLogPath(appName = this.getAppName()) {
    if (this.platform === 'darwin') {
      return path.join(this.getSystemPathHome(), 'Library/Logs', appName);
    }

    return path.join(this.getAppUserDataPath(appName), 'logs');
  }

  getAppName() {
    const appName = this.appName || this.getAppPackageJson()?.name;
    if (!appName) {
      throw new Error(
        'electron-log can\'t determine the app name. It tried these methods:\n'
        + '1. Use `electron.app.name`\n'
        + '2. Use productName or name from the nearest package.json`\n'
        + 'You can also set it through log.transports.file.setAppName()',
      );
    }

    return appName;
  }

  /**
   * @private
   * @returns {undefined}
   */
  getAppPackageJson() {
    if (typeof this.appPackageJson !== 'object') {
      this.appPackageJson = packageJson.findAndReadPackageJson();
    }

    return this.appPackageJson;
  }

  getAppUserDataPath(appName = this.getAppName()) {
    return appName
      ? path.join(this.getSystemPathAppData(), appName)
      : undefined;
  }

  getAppVersion() {
    return this.getAppPackageJson()?.version;
  }

  getElectronLogPath() {
    return this.getAppLogPath();
  }

  getMacOsVersion() {
    const release = Number(os.release().split('.')[0]);
    if (release <= 19) {
      return `10.${release - 4}`;
    }

    return release - 9;
  }

  /**
   * @protected
   * @returns {string}
   */
  getOsVersion() {
    let osName = os.type().replace('_', ' ');
    let osVersion = os.release();

    if (osName === 'Darwin') {
      osName = 'macOS';
      osVersion = this.getMacOsVersion();
    }

    return `${osName} ${osVersion}`;
  }

  /**
   * @return {PathVariables}
   */
  getPathVariables() {
    const appName = this.getAppName();
    const appVersion = this.getAppVersion();

    const self = this;

    return {
      appData: this.getSystemPathAppData(),
      appName,
      appVersion,
      get electronDefaultDir() {
        return self.getElectronLogPath();
      },
      home: this.getSystemPathHome(),
      libraryDefaultDir: this.getAppLogPath(appName),
      libraryTemplate: this.getAppLogPath('{appName}'),
      temp: this.getSystemPathTemp(),
      userData: this.getAppUserDataPath(appName),
    };
  }

  getSystemPathAppData() {
    const home = this.getSystemPathHome();

    switch (this.platform) {
      case 'darwin': {
        return path.join(home, 'Library/Application Support');
      }

      case 'win32': {
        return process.env.APPDATA || path.join(home, 'AppData/Roaming');
      }

      default: {
        return process.env.XDG_CONFIG_HOME || path.join(home, '.config');
      }
    }
  }

  getSystemPathHome() {
    return os.homedir?.() || process.env.HOME;
  }

  getSystemPathTemp() {
    return os.tmpdir();
  }

  getVersions() {
    return {
      app: `${this.getAppName()} ${this.getAppVersion()}`,
      electron: undefined,
      os: this.getOsVersion(),
    };
  }

  isDev() {
    return process.env.NODE_ENV === 'development'
      || process.env.ELECTRON_IS_DEV === '1';
  }

  isElectron() {
    return Boolean(process.versions.electron);
  }

  onAppEvent(_eventName, _handler) {
    // Ignored in node.js
  }

  onAppReady(handler) {
    handler();
  }

  onEveryWebContentsEvent(eventName, handler) {
    // Ignored in node.js
  }

  /**
   * Listen to async messages sent from opposite process
   * @param {string} channel
   * @param {function} listener
   */
  onIpc(channel, listener) {
    // Ignored in node.js
  }

  onIpcInvoke(channel, listener) {
    // Ignored in node.js
  }

  /**
   * @param {string} url
   * @param {Function} [logFunction]
   */
  openUrl(url, logFunction = console.error) { // eslint-disable-line no-console
    const startMap = { darwin: 'open', win32: 'start', linux: 'xdg-open' };
    const start = startMap[process.platform] || 'xdg-open';
    childProcess.exec(`${start} ${url}`, {}, (err) => {
      if (err) {
        logFunction(err);
      }
    });
  }

  setAppName(appName) {
    this.appName = appName;
  }

  setPlatform(platform) {
    this.platform = platform;
  }

  setPreloadFileForSessions({
    filePath, // eslint-disable-line no-unused-vars
    includeFutureSession = true, // eslint-disable-line no-unused-vars
    getSessions = () => [], // eslint-disable-line no-unused-vars
  }) {
    // Ignored in node.js
  }

  /**
   * Sent a message to opposite process
   * @param {string} channel
   * @param {any} message
   */
  sendIpc(channel, message) {
    // Ignored in node.js
  }

  showErrorBox(title, message) {
    // Ignored in node.js
  }
}

module.exports = NodeExternalApi;
'use strict';

const Logger = require('../core/Logger');
const ErrorHandler = require('./ErrorHandler');
const EventLogger = require('./EventLogger');
const transportConsole = require('./transports/console');
const transportFile = require('./transports/file');
const transportIpc = require('./transports/ipc');
const transportRemote = require('./transports/remote');

module.exports = createDefaultLogger;

function createDefaultLogger({ dependencies, initializeFn }) {
  const defaultLogger = new Logger({
    dependencies,
    errorHandler: new ErrorHandler(),
    eventLogger: new EventLogger(),
    initializeFn,
    isDev: dependencies.externalApi?.isDev(),
    logId: 'default',
    transportFactories: {
      console: transportConsole,
      file: transportFile,
      ipc: transportIpc,
      remote: transportRemote,
    },
    variables: {
      processType: 'main',
    },
  });

  defaultLogger.default = defaultLogger;
  defaultLogger.Logger = Logger;

  defaultLogger.processInternalErrorFn = (e) => {
    defaultLogger.transports.console.writeFn({
      message: {
        data: ['Unhandled electron-log error', e],
        level: 'error',
      },
    });
  };

  return defaultLogger;
}
'use strict';

const NodeExternalApi = require('./NodeExternalApi');
const createDefaultLogger = require('./createDefaultLogger');

const externalApi = new NodeExternalApi();

const defaultLogger = createDefaultLogger({
  dependencies: { externalApi },
});

module.exports = defaultLogger;
'use strict';

const fs = require('fs');
const path = require('path');

module.exports = {
  findAndReadPackageJson,
  tryReadJsonAt,
};

/**
 * @return {{ name?: string, version?: string}}
 */
function findAndReadPackageJson() {
  return tryReadJsonAt(getMainModulePath())
    || tryReadJsonAt(extractPathFromArgs())
    || tryReadJsonAt(process.resourcesPath, 'app.asar')
    || tryReadJsonAt(process.resourcesPath, 'app')
    || tryReadJsonAt(process.cwd())
    || { name: undefined, version: undefined };
}

/**
 * @param {...string} searchPaths
 * @return {{ name?: string, version?: string } | undefined}
 */
function tryReadJsonAt(...searchPaths) {
  if (!searchPaths[0]) {
    return undefined;
  }

  try {
    const searchPath = path.join(...searchPaths);
    const fileName = findUp('package.json', searchPath);
    if (!fileName) {
      return undefined;
    }

    const json = JSON.parse(fs.readFileSync(fileName, 'utf8'));
    const name = json?.productName || json?.name;
    if (!name || name.toLowerCase() === 'electron') {
      return undefined;
    }

    if (name) {
      return { name, version: json?.version };
    }

    return undefined;
  } catch (e) {
    return undefined;
  }
}

/**
 * @param {string} fileName
 * @param {string} [cwd]
 * @return {string | null}
 */
function findUp(fileName, cwd) {
  let currentPath = cwd;
  // eslint-disable-next-line no-constant-condition
  while (true) {
    const parsedPath = path.parse(currentPath);
    const root = parsedPath.root;
    const dir = parsedPath.dir;

    if (fs.existsSync(path.join(currentPath, fileName))) {
      return path.resolve(path.join(currentPath, fileName));
    }

    if (currentPath === root) {
      return null;
    }

    currentPath = dir;
  }
}

/**
 * Get app path from --user-data-dir cmd arg, passed to a renderer process
 * @return {string|null}
 */
function extractPathFromArgs() {
  const matchedArgs = process.argv.filter((arg) => {
    return arg.indexOf('--user-data-dir=') === 0;
  });

  if (matchedArgs.length === 0 || typeof matchedArgs[0] !== 'string') {
    return null;
  }

  const userDataDir = matchedArgs[0];
  return userDataDir.replace('--user-data-dir=', '');
}

function getMainModulePath() {
  try {
    // Requires isn't available in ESM
    return require.main?.filename;
  } catch {
    return undefined;
  }
}
'use strict';

const util = require('util');

module.exports = {
  serialize,

  maxDepth({ data, transport, depth = transport?.depth ?? 6 }) {
    if (!data) {
      return data;
    }

    if (depth < 1) {
      if (Array.isArray(data)) return '[array]';
      if (typeof data === 'object' && data) return '[object]';

      return data;
    }

    if (Array.isArray(data)) {
      return data.map((child) => module.exports.maxDepth({
        data: child,
        depth: depth - 1,
      }));
    }

    if (typeof data !== 'object') {
      return data;
    }

    if (data && typeof data.toISOString === 'function') {
      return data;
    }

    // noinspection PointlessBooleanExpressionJS
    if (data === null) {
      return null;
    }

    if (data instanceof Error) {
      return data;
    }

    const newJson = {};
    for (const i in data) {
      if (!Object.prototype.hasOwnProperty.call(data, i)) continue;
      newJson[i] = module.exports.maxDepth({
        data: data[i],
        depth: depth - 1,
      });
    }

    return newJson;
  },

  toJSON({ data }) {
    return JSON.parse(JSON.stringify(data, createSerializer()));
  },

  toString({ data, transport }) {
    const inspectOptions = transport?.inspectOptions || {};

    const simplifiedData = data.map((item) => {
      if (item === undefined) {
        return undefined;
      }

      try {
        const str = JSON.stringify(item, createSerializer(), '  ');
        return str === undefined ? undefined : JSON.parse(str);
      } catch (e) {
        // There are some rare cases when an item can't be simplified.
        // In that case, it's fine to pass it to util.format directly.
        return item;
      }
    });

    return util.formatWithOptions(inspectOptions, ...simplifiedData);
  },
};

/**
 * @param {object} options?
 * @param {boolean} options.serializeMapAndSet?
 * @return {function}
 */
function createSerializer(options = {}) {
  const seen = new WeakSet();

  return function (key, value) {
    if (typeof value === 'object' && value !== null) {
      if (seen.has(value)) {
        return undefined;
      }

      seen.add(value);
    }

    return serialize(key, value, options);
  };
}

/**
 * @param {string} key
 * @param {any} value
 * @param {object} options?
 * @return {any}
 */
function serialize(key, value, options = {}) {
  const serializeMapAndSet = options?.serializeMapAndSet !== false;

  if (value instanceof Error) {
    return value.stack;
  }

  if (!value) {
    return value;
  }

  if (typeof value === 'function') {
    return `[function] ${value.toString()}`;
  }

  if (value instanceof Date) {
    return value.toISOString();
  }

  if (serializeMapAndSet && value instanceof Map && Object.fromEntries) {
    return Object.fromEntries(value);
  }

  if (serializeMapAndSet && value instanceof Set && Array.from) {
    return Array.from(value);
  }

  return value;
}
'use strict';

/* eslint-disable no-console */

const {
  concatFirstStringElements,
  format,
} = require('../../core/transforms/format');
const { maxDepth, toJSON } = require('../transforms/object');
const {
  applyAnsiStyles,
  removeStyles,
} = require('../../core/transforms/style');
const { transform } = require('../../core/transforms/transform');

const consoleMethods = {
  error: console.error,
  warn: console.warn,
  info: console.info,
  verbose: console.info,
  debug: console.debug,
  silly: console.debug,
  log: console.log,
};

module.exports = consoleTransportFactory;

const separator = process.platform === 'win32' ? '>' : '›';
const DEFAULT_FORMAT = `%c{h}:{i}:{s}.{ms}{scope}%c ${separator} {text}`;

Object.assign(consoleTransportFactory, {
  DEFAULT_FORMAT,
});

function consoleTransportFactory(logger) {
  return Object.assign(transport, {
    colorMap: {
      error: 'red',
      warn: 'yellow',
      info: 'cyan',
      verbose: 'unset',
      debug: 'gray',
      silly: 'gray',
      default: 'unset',
    },
    format: DEFAULT_FORMAT,
    level: 'silly',
    transforms: [
      addTemplateColors,
      format,
      formatStyles,
      concatFirstStringElements,
      maxDepth,
      toJSON,
    ],
    useStyles: process.env.FORCE_STYLES,

    writeFn({ message }) {
      const consoleLogFn = consoleMethods[message.level] || consoleMethods.info;
      consoleLogFn(...message.data);
    },
  });

  function transport(message) {
    const data = transform({ logger, message, transport });
    transport.writeFn({
      message: { ...message, data },
    });
  }
}

function addTemplateColors({ data, message, transport }) {
  if (
    typeof transport.format !== 'string'
    || !transport.format.includes('%c')
  ) {
    return data;
  }

  return [
    `color:${levelToStyle(message.level, transport)}`,
    'color:unset',
    ...data,
  ];
}

function canUseStyles(useStyleValue, level) {
  if (typeof useStyleValue === 'boolean') {
    return useStyleValue;
  }

  const useStderr = level === 'error' || level === 'warn';
  const stream = useStderr ? process.stderr : process.stdout;
  return stream && stream.isTTY;
}

function formatStyles(args) {
  const { message, transport } = args;
  const useStyles = canUseStyles(transport.useStyles, message.level);
  const nextTransform = useStyles ? applyAnsiStyles : removeStyles;
  return nextTransform(args);
}

function levelToStyle(level, transport) {
  return transport.colorMap[level] || transport.colorMap.default;
}
'use strict';

const EventEmitter = require('events');
const fs = require('fs');
const os = require('os');

class File extends EventEmitter {
  asyncWriteQueue = [];
  bytesWritten = 0;
  hasActiveAsyncWriting = false;
  path = null;
  initialSize = undefined;
  writeOptions = null;
  writeAsync = false;

  constructor({
    path,
    writeOptions = { encoding: 'utf8', flag: 'a', mode: 0o666 },
    writeAsync = false,
  }) {
    super();

    this.path = path;
    this.writeOptions = writeOptions;
    this.writeAsync = writeAsync;
  }

  get size() {
    return this.getSize();
  }

  clear() {
    try {
      fs.writeFileSync(this.path, '', {
        mode: this.writeOptions.mode,
        flag: 'w',
      });
      this.reset();
      return true;
    } catch (e) {
      if (e.code === 'ENOENT') {
        return true;
      }

      this.emit('error', e, this);
      return false;
    }
  }

  crop(bytesAfter) {
    try {
      const content = readFileSyncFromEnd(this.path, bytesAfter || 4096);
      this.clear();
      this.writeLine(`[log cropped]${os.EOL}${content}`);
    } catch (e) {
      this.emit(
        'error',
        new Error(`Couldn't crop file ${this.path}. ${e.message}`),
        this,
      );
    }
  }

  getSize() {
    if (this.initialSize === undefined) {
      try {
        const stats = fs.statSync(this.path);
        this.initialSize = stats.size;
      } catch (e) {
        this.initialSize = 0;
      }
    }

    return this.initialSize + this.bytesWritten;
  }

  increaseBytesWrittenCounter(text) {
    this.bytesWritten += Buffer.byteLength(text, this.writeOptions.encoding);
  }

  isNull() {
    return false;
  }

  nextAsyncWrite() {
    const file = this;

    if (this.hasActiveAsyncWriting || this.asyncWriteQueue.length === 0) {
      return;
    }

    const text = this.asyncWriteQueue.join('');
    this.asyncWriteQueue = [];
    this.hasActiveAsyncWriting = true;

    fs.writeFile(this.path, text, this.writeOptions, (e) => {
      file.hasActiveAsyncWriting = false;

      if (e) {
        file.emit(
          'error',
          new Error(`Couldn't write to ${file.path}. ${e.message}`),
          this,
        );
      } else {
        file.increaseBytesWrittenCounter(text);
      }

      file.nextAsyncWrite();
    });
  }

  reset() {
    this.initialSize = undefined;
    this.bytesWritten = 0;
  }

  toString() {
    return this.path;
  }

  writeLine(text) {
    text += os.EOL;

    if (this.writeAsync) {
      this.asyncWriteQueue.push(text);
      this.nextAsyncWrite();
      return;
    }

    try {
      fs.writeFileSync(this.path, text, this.writeOptions);
      this.increaseBytesWrittenCounter(text);
    } catch (e) {
      this.emit(
        'error',
        new Error(`Couldn't write to ${this.path}. ${e.message}`),
        this,
      );
    }
  }
}

module.exports = File;

function readFileSyncFromEnd(filePath, bytesCount) {
  const buffer = Buffer.alloc(bytesCount);
  const stats = fs.statSync(filePath);

  const readLength = Math.min(stats.size, bytesCount);
  const offset = Math.max(0, stats.size - bytesCount);

  const fd = fs.openSync(filePath, 'r');
  const totalBytes = fs.readSync(fd, buffer, 0, readLength, offset);
  fs.closeSync(fd);

  return buffer.toString('utf8', 0, totalBytes);
}
'use strict';

const EventEmitter = require('events');
const fs = require('fs');
const path = require('path');
const File = require('./File');
const NullFile = require('./NullFile');

class FileRegistry extends EventEmitter {
  store = {};

  constructor() {
    super();
    this.emitError = this.emitError.bind(this);
  }

  /**
   * Provide a File object corresponding to the filePath
   * @param {string} filePath
   * @param {WriteOptions} [writeOptions]
   * @param {boolean} [writeAsync]
   * @return {File}
   */
  provide({ filePath, writeOptions = {}, writeAsync = false }) {
    let file;
    try {
      filePath = path.resolve(filePath);

      if (this.store[filePath]) {
        return this.store[filePath];
      }

      file = this.createFile({ filePath, writeOptions, writeAsync });
    } catch (e) {
      file = new NullFile({ path: filePath });
      this.emitError(e, file);
    }

    file.on('error', this.emitError);
    this.store[filePath] = file;
    return file;
  }

  /**
   * @param {string} filePath
   * @param {WriteOptions} writeOptions
   * @param {boolean} async
   * @return {File}
   * @private
   */
  createFile({ filePath, writeOptions, writeAsync }) {
    this.testFileWriting({ filePath, writeOptions });
    return new File({ path: filePath, writeOptions, writeAsync });
  }

  /**
   * @param {Error} error
   * @param {File} file
   * @private
   */
  emitError(error, file) {
    this.emit('error', error, file);
  }

  /**
   * @param {string} filePath
   * @param {WriteOptions} writeOptions
   * @private
   */
  testFileWriting({ filePath, writeOptions }) {
    fs.mkdirSync(path.dirname(filePath), { recursive: true });
    fs.writeFileSync(filePath, '', { flag: 'a', mode: writeOptions.mode });
  }
}

module.exports = FileRegistry;
'use strict';

const File = require('./File');

class NullFile extends File {
  clear() {

  }

  crop() {

  }

  getSize() {
    return 0;
  }

  isNull() {
    return true;
  }

  writeLine() {

  }
}

module.exports = NullFile;
'use strict';

const fs = require('fs');
const os = require('os');
const path = require('path');
const FileRegistry = require('./FileRegistry');
const { transform } = require('../../../core/transforms/transform');
const { removeStyles } = require('../../../core/transforms/style');
const {
  format,
  concatFirstStringElements,
} = require('../../../core/transforms/format');
const { toString } = require('../../transforms/object');

module.exports = fileTransportFactory;

// Shared between multiple file transport instances
const globalRegistry = new FileRegistry();

function fileTransportFactory(
  logger,
  { registry = globalRegistry, externalApi } = {},
) {
  /** @type {PathVariables} */
  let pathVariables;

  if (registry.listenerCount('error') < 1) {
    registry.on('error', (e, file) => {
      logConsole(`Can't write to ${file}`, e);
    });
  }

  return Object.assign(transport, {
    fileName: getDefaultFileName(logger.variables.processType),
    format: '[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}]{scope} {text}',
    getFile,
    inspectOptions: { depth: 5 },
    level: 'silly',
    maxSize: 1024 ** 2,
    readAllLogs,
    sync: true,
    transforms: [removeStyles, format, concatFirstStringElements, toString],
    writeOptions: { flag: 'a', mode: 0o666, encoding: 'utf8' },

    archiveLogFn(file) {
      const oldPath = file.toString();
      const inf = path.parse(oldPath);
      try {
        fs.renameSync(oldPath, path.join(inf.dir, `${inf.name}.old${inf.ext}`));
      } catch (e) {
        logConsole('Could not rotate log', e);
        const quarterOfMaxSize = Math.round(transport.maxSize / 4);
        file.crop(Math.min(quarterOfMaxSize, 256 * 1024));
      }
    },

    resolvePathFn(vars) {
      return path.join(vars.libraryDefaultDir, vars.fileName);
    },

    setAppName(name) {
      logger.dependencies.externalApi.setAppName(name);
    },
  });

  function transport(message) {
    const file = getFile(message);

    const needLogRotation = transport.maxSize > 0
      && file.size > transport.maxSize;

    if (needLogRotation) {
      transport.archiveLogFn(file);
      file.reset();
    }

    const content = transform({ logger, message, transport });
    file.writeLine(content);
  }

  function initializeOnFirstAccess() {
    if (pathVariables) {
      return;
    }

    // Make a shallow copy of pathVariables to keep getters intact
    pathVariables = Object.create(
      Object.prototype,
      {
        ...Object.getOwnPropertyDescriptors(
          externalApi.getPathVariables(),
        ),
        fileName: {
          get() {
            return transport.fileName;
          },
          enumerable: true,
        },
      },
    );

    if (typeof transport.archiveLog === 'function') {
      transport.archiveLogFn = transport.archiveLog;
      logConsole('archiveLog is deprecated. Use archiveLogFn instead');
    }

    if (typeof transport.resolvePath === 'function') {
      transport.resolvePathFn = transport.resolvePath;
      logConsole('resolvePath is deprecated. Use resolvePathFn instead');
    }
  }

  function logConsole(message, error = null, level = 'error') {
    const data = [`electron-log.transports.file: ${message}`];

    if (error) {
      data.push(error);
    }

    logger.transports.console({ data, date: new Date(), level });
  }

  function getFile(msg) {
    initializeOnFirstAccess();

    const filePath = transport.resolvePathFn(pathVariables, msg);
    return registry.provide({
      filePath,
      writeAsync: !transport.sync,
      writeOptions: transport.writeOptions,
    });
  }

  function readAllLogs({ fileFilter = (f) => f.endsWith('.log') } = {}) {
    initializeOnFirstAccess();
    const logsPath = path.dirname(transport.resolvePathFn(pathVariables));

    if (!fs.existsSync(logsPath)) {
      return [];
    }

    return fs.readdirSync(logsPath)
      .map((fileName) => path.join(logsPath, fileName))
      .filter(fileFilter)
      .map((logPath) => {
        try {
          return {
            path: logPath,
            lines: fs.readFileSync(logPath, 'utf8').split(os.EOL),
          };
        } catch {
          return null;
        }
      })
      .filter(Boolean);
  }
}

function getDefaultFileName(processType = process.type) {
  switch (processType) {
    case 'renderer': return 'renderer.log';
    case 'worker': return 'worker.log';
    default: return 'main.log';
  }
}
'use strict';

const { maxDepth, toJSON } = require('../transforms/object');
const { transform } = require('../../core/transforms/transform');

module.exports = ipcTransportFactory;

/**
 * @param logger
 * @param {ElectronExternalApi} externalApi
 * @returns {transport|null}
 */
function ipcTransportFactory(logger, { externalApi }) {
  Object.assign(transport, {
    depth: 3,
    eventId: '__ELECTRON_LOG_IPC__',
    level: logger.isDev ? 'silly' : false,
    transforms: [toJSON, maxDepth],
  });

  return externalApi?.isElectron() ? transport : undefined;

  function transport(message) {
    if (message?.variables?.processType === 'renderer') {
      return;
    }

    externalApi?.sendIpc(transport.eventId, {
      ...message,
      data: transform({ logger, message, transport }),
    });
  }
}
'use strict';

const http = require('http');
const https = require('https');
const { transform } = require('../../core/transforms/transform');
const { removeStyles } = require('../../core/transforms/style');
const { toJSON, maxDepth } = require('../transforms/object');

module.exports = remoteTransportFactory;

function remoteTransportFactory(logger) {
  return Object.assign(transport, {
    client: { name: 'electron-application' },
    depth: 6,
    level: false,
    requestOptions: {},
    transforms: [removeStyles, toJSON, maxDepth],

    makeBodyFn({ message }) {
      return JSON.stringify({
        client: transport.client,
        data: message.data,
        date: message.date.getTime(),
        level: message.level,
        scope: message.scope,
        variables: message.variables,
      });
    },

    processErrorFn({ error }) {
      logger.processMessage(
        {
          data: [`electron-log: can't POST ${transport.url}`, error],
          level: 'warn',
        },
        { transports: ['console', 'file'] },
      );
    },

    sendRequestFn({ serverUrl, requestOptions, body }) {
      const httpTransport = serverUrl.startsWith('https:') ? https : http;

      const request = httpTransport.request(serverUrl, {
        method: 'POST',
        ...requestOptions,
        headers: {
          'Content-Type': 'application/json',
          'Content-Length': body.length,
          ...requestOptions.headers,
        },
      });

      request.write(body);
      request.end();

      return request;
    },
  });

  function transport(message) {
    if (!transport.url) {
      return;
    }

    const body = transport.makeBodyFn({
      logger,
      message: { ...message, data: transform({ logger, message, transport }) },
      transport,
    });

    const request = transport.sendRequestFn({
      serverUrl: transport.url,
      requestOptions: transport.requestOptions,
      body: Buffer.from(body, 'utf8'),
    });

    request.on('error', (error) => transport.processErrorFn({
      error,
      logger,
      message,
      request,
      transport,
    }));
  }
}
'use strict';

let electron = {};

try {
  // eslint-disable-next-line global-require,import/no-extraneous-dependencies
  electron = require('electron');
} catch (e) {
  // require isn't available, not from a preload script
}

if (electron.ipcRenderer) {
  initialize(electron);
}

if (typeof module === 'object') {
  module.exports = initialize;
}

/**
 * @param {Electron.ContextBridge} contextBridge
 * @param {Electron.IpcRenderer} ipcRenderer
 */
function initialize({ contextBridge, ipcRenderer }) {
  if (!ipcRenderer) {
    return;
  }

  ipcRenderer.on('__ELECTRON_LOG_IPC__', (_, message) => {
    window.postMessage({ cmd: 'message', ...message });
  });

  ipcRenderer
    .invoke('__ELECTRON_LOG__', { cmd: 'getOptions' })
    // eslint-disable-next-line no-console
    .catch((e) => console.error(new Error(
      'electron-log isn\'t initialized in the main process. '
      + `Please call log.initialize() before. ${e.message}`,
    )));

  const electronLog = {
    sendToMain(message) {
      try {
        ipcRenderer.send('__ELECTRON_LOG__', message);
      } catch (e) {
        // eslint-disable-next-line no-console
        console.error('electronLog.sendToMain ', e, 'data:', message);

        ipcRenderer.send('__ELECTRON_LOG__', {
          cmd: 'errorHandler',
          error: { message: e?.message, stack: e?.stack },
          errorName: 'sendToMain',
        });
      }
    },

    log(...data) {
      electronLog.sendToMain({ data, level: 'info' });
    },
  };

  for (const level of ['error', 'warn', 'info', 'verbose', 'debug', 'silly']) {
    electronLog[level] = (...data) => electronLog.sendToMain({
      data,
      level,
    });
  }

  if (contextBridge && process.contextIsolated) {
    try {
      contextBridge.exposeInMainWorld('__electronLog', electronLog);
    } catch {
      // Sometimes this files can be included twice
    }
  }

  if (typeof window === 'object') {
    window.__electronLog = electronLog;
  } else {
    // noinspection JSConstantReassignment
    __electronLog = electronLog;
  }
}
'use strict';

const Logger = require('../core/Logger');
const RendererErrorHandler = require('./lib/RendererErrorHandler');
const transportConsole = require('./lib/transports/console');
const transportIpc = require('./lib/transports/ipc');

if (typeof process === 'object' && process.type === 'browser') {
  // eslint-disable-next-line no-console
  console.warn(
    'electron-log/renderer is loaded in the main process. '
    + 'It could cause unexpected behaviour.',
  );
}

module.exports = createLogger();
module.exports.Logger = Logger;
module.exports.default = module.exports;

function createLogger() {
  const logger = new Logger({
    allowUnknownLevel: true,
    errorHandler: new RendererErrorHandler(),
    initializeFn: () => {},
    logId: 'default',
    transportFactories: {
      console: transportConsole,
      ipc: transportIpc,
    },
    variables: {
      processType: 'renderer',
    },
  });

  logger.errorHandler.setOptions({
    logFn({ error, errorName, showDialog }) {
      logger.transports.console({
        data: [errorName, error].filter(Boolean),
        level: 'error',
      });
      logger.transports.ipc({
        cmd: 'errorHandler',
        error: {
          cause: error?.cause,
          code: error?.code,
          name: error?.name,
          message: error?.message,
          stack: error?.stack,
        },
        errorName,
        logId: logger.logId,
        showDialog,
      });
    },
  });

  if (typeof window === 'object') {
    window.addEventListener('message', (event) => {
      const { cmd, logId, ...message } = event.data || {};
      const instance = Logger.getInstance({ logId });

      if (cmd === 'message') {
        instance.processMessage(message, { transports: ['console'] });
      }
    });
  }

  // To support custom levels
  return new Proxy(logger, {
    get(target, prop) {
      if (typeof target[prop] !== 'undefined') {
        return target[prop];
      }

      return (...data) => logger.logData(data, { level: prop });
    },
  });
}
'use strict';

// eslint-disable-next-line no-console
const consoleError = console.error;

class RendererErrorHandler {
  logFn = null;
  onError = null;
  showDialog = false;
  preventDefault = true;

  constructor({ logFn = null } = {}) {
    this.handleError = this.handleError.bind(this);
    this.handleRejection = this.handleRejection.bind(this);
    this.startCatching = this.startCatching.bind(this);
    this.logFn = logFn;
  }

  handle(error, {
    logFn = this.logFn,
    errorName = '',
    onError = this.onError,
    showDialog = this.showDialog,
  } = {}) {
    try {
      if (onError?.({ error, errorName, processType: 'renderer' }) !== false) {
        logFn({ error, errorName, showDialog });
      }
    } catch {
      consoleError(error);
    }
  }

  setOptions({ logFn, onError, preventDefault, showDialog }) {
    if (typeof logFn === 'function') {
      this.logFn = logFn;
    }

    if (typeof onError === 'function') {
      this.onError = onError;
    }

    if (typeof preventDefault === 'boolean') {
      this.preventDefault = preventDefault;
    }

    if (typeof showDialog === 'boolean') {
      this.showDialog = showDialog;
    }
  }

  startCatching({ onError, showDialog } = {}) {
    if (this.isActive) {
      return;
    }

    this.isActive = true;
    this.setOptions({ onError, showDialog });

    window.addEventListener('error', (event) => {
      this.preventDefault && event.preventDefault?.();
      this.handleError(event.error || event);
    });
    window.addEventListener('unhandledrejection', (event) => {
      this.preventDefault && event.preventDefault?.();
      this.handleRejection(event.reason || event);
    });
  }

  handleError(error) {
    this.handle(error, { errorName: 'Unhandled' });
  }

  handleRejection(reason) {
    const error = reason instanceof Error
      ? reason
      : new Error(JSON.stringify(reason));
    this.handle(error, { errorName: 'Unhandled rejection' });
  }
}

module.exports = RendererErrorHandler;
'use strict';

/* eslint-disable no-console */

const { transform } = require('../../../core/transforms/transform');

module.exports = consoleTransportRendererFactory;

const consoleMethods = {
  error: console.error,
  warn: console.warn,
  info: console.info,
  verbose: console.info,
  debug: console.debug,
  silly: console.debug,
  log: console.log,
};

function consoleTransportRendererFactory(logger) {
  return Object.assign(transport, {
    format: '{h}:{i}:{s}.{ms}{scope} › {text}',
    transforms: [formatDataFn],

    writeFn({ message: { level, data } }) {
      const consoleLogFn = consoleMethods[level] || consoleMethods.info;

      // make an empty call stack
      setTimeout(() => consoleLogFn(...data));
    },
  });

  function transport(message) {
    transport.writeFn({
      message: { ...message, data: transform({ logger, message, transport }) },
    });
  }
}

function formatDataFn({
  data = [],
  logger = {},
  message = {},
  transport = {},
}) {
  if (typeof transport.format === 'function') {
    return transport.format({
      data,
      level: message?.level || 'info',
      logger,
      message,
      transport,
    });
  }

  if (typeof transport.format !== 'string') {
    return data;
  }

  data.unshift(transport.format);

  // Concatenate the first two data items to support printf-like templates
  if (typeof data[1] === 'string' && data[1].match(/%[1cdfiOos]/)) {
    data = [`${data[0]}${data[1]}`, ...data.slice(2)];
  }

  const date = message.date || new Date();
  data[0] = data[0]
    .replace(/\{(\w+)}/g, (substring, name) => {
      switch (name) {
        case 'level': return message.level;
        case 'logId': return message.logId;
        case 'scope': {
          const scope = message.scope || logger.scope?.defaultLabel;
          return scope ? ` (${scope})` : '';
        }
        case 'text': return '';

        case 'y': return date.getFullYear().toString(10);
        case 'm': return (date.getMonth() + 1).toString(10)
          .padStart(2, '0');
        case 'd': return date.getDate().toString(10).padStart(2, '0');
        case 'h': return date.getHours().toString(10).padStart(2, '0');
        case 'i': return date.getMinutes().toString(10).padStart(2, '0');
        case 's': return date.getSeconds().toString(10).padStart(2, '0');
        case 'ms': return date.getMilliseconds().toString(10)
          .padStart(3, '0');
        case 'iso': return date.toISOString();

        default: return message.variables?.[name] || substring;
      }
    })
    .trim();

  return data;
}
'use strict';

const { transform } = require('../../../core/transforms/transform');

module.exports = ipcTransportRendererFactory;

const RESTRICTED_TYPES = new Set([Promise, WeakMap, WeakSet]);

function ipcTransportRendererFactory(logger) {
  return Object.assign(transport, {
    depth: 5,
    transforms: [serializeFn],
  });

  function transport(message) {
    if (!window.__electronLog) {
      logger.processMessage(
        {
          data: ['electron-log: logger isn\'t initialized in the main process'],
          level: 'error',
        },
        { transports: ['console'] },
      );
      return;
    }

    try {
      const serialized = transform({
        initialData: message,
        logger,
        message,
        transport,
      });

      __electronLog.sendToMain(serialized);
    } catch (e) {
      logger.transports.console({
        data: ['electronLog.transports.ipc', e, 'data:', message.data],
        level: 'error',
      });
    }
  }
}

/**
 * Is type primitive, including null and undefined
 * @param {any} value
 * @returns {boolean}
 */
function isPrimitive(value) {
  return Object(value) !== value;
}

function serializeFn({
  data,
  depth,
  seen = new WeakSet(),
  transport = {},
} = {}) {
  const actualDepth = depth || transport.depth || 5;

  if (seen.has(data)) {
    return '[Circular]';
  }

  if (actualDepth < 1) {
    if (isPrimitive(data)) {
      return data;
    }

    if (Array.isArray(data)) {
      return '[Array]';
    }

    return `[${typeof data}]`;
  }

  if (['function', 'symbol'].includes(typeof data)) {
    return data.toString();
  }

  if (isPrimitive(data)) {
    return data;
  }

  // Object types

  if (RESTRICTED_TYPES.has(data.constructor)) {
    return `[${data.constructor.name}]`;
  }

  if (Array.isArray(data)) {
    return data.map((item) => serializeFn({
      data: item,
      depth: actualDepth - 1,
      seen,
    }));
  }

  if (data instanceof Date) {
    return data.toISOString();
  }

  if (data instanceof Error) {
    return data.stack;
  }

  if (data instanceof Map) {
    return new Map(
      Array
        .from(data)
        .map(([key, value]) => [
          serializeFn({ data: key, depth: actualDepth - 1, seen }),
          serializeFn({ data: value, depth: actualDepth - 1, seen }),
        ]),
    );
  }

  if (data instanceof Set) {
    return new Set(
      Array.from(data).map(
        (val) => serializeFn({ data: val, depth: actualDepth - 1, seen }),
      ),
    );
  }

  seen.add(data);

  return Object.fromEntries(
    Object.entries(data).map(
      ([key, value]) => [
        key,
        serializeFn({ data: value, depth: actualDepth - 1, seen }),
      ],
    ),
  );
}
The MIT License (MIT)

Copyright (c) 2015 Loopline Systems

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAppCacheDir = getAppCacheDir;
const path = require("path");
const os_1 = require("os");
function getAppCacheDir() {
    const homedir = (0, os_1.homedir)();
    // https://github.com/electron/electron/issues/1404#issuecomment-194391247
    let result;
    if (process.platform === "win32") {
        result = process.env["LOCALAPPDATA"] || path.join(homedir, "AppData", "Local");
    }
    else if (process.platform === "darwin") {
        result = path.join(homedir, "Library", "Caches");
    }
    else {
        result = process.env["XDG_CACHE_HOME"] || path.join(homedir, ".cache");
    }
    return result;
}
//# sourceMappingURL=AppAdapter.js.map{"version":3,"file":"AppAdapter.js","sourceRoot":"","sources":["../src/AppAdapter.ts"],"names":[],"mappings":";;AAiCA,wCAYC;AA7CD,6BAA4B;AAC5B,2BAA0C;AAgC1C,SAAgB,cAAc;IAC5B,MAAM,OAAO,GAAG,IAAA,YAAU,GAAE,CAAA;IAC5B,0EAA0E;IAC1E,IAAI,MAAc,CAAA;IAClB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;IAChF,CAAC;SAAM,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACzC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;IAClD,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IACxE,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["import * as path from \"path\"\nimport { homedir as getHomedir } from \"os\"\n\nexport interface AppAdapter {\n  readonly version: string\n  readonly name: string\n\n  readonly isPackaged: boolean\n\n  /**\n   * Path to update metadata file.\n   */\n  readonly appUpdateConfigPath: string\n\n  /**\n   * Path to user data directory.\n   */\n  readonly userDataPath: string\n\n  /**\n   * Path to cache directory.\n   */\n  readonly baseCachePath: string\n\n  whenReady(): Promise<void>\n\n  relaunch(): void\n\n  quit(): void\n\n  onQuit(handler: (exitCode: number) => void): void\n}\n\nexport function getAppCacheDir() {\n  const homedir = getHomedir()\n  // https://github.com/electron/electron/issues/1404#issuecomment-194391247\n  let result: string\n  if (process.platform === \"win32\") {\n    result = process.env[\"LOCALAPPDATA\"] || path.join(homedir, \"AppData\", \"Local\")\n  } else if (process.platform === \"darwin\") {\n    result = path.join(homedir, \"Library\", \"Caches\")\n  } else {\n    result = process.env[\"XDG_CACHE_HOME\"] || path.join(homedir, \".cache\")\n  }\n  return result\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppImageUpdater = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const child_process_1 = require("child_process");
const fs_extra_1 = require("fs-extra");
const fs_1 = require("fs");
const path = require("path");
const BaseUpdater_1 = require("./BaseUpdater");
const FileWithEmbeddedBlockMapDifferentialDownloader_1 = require("./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader");
const Provider_1 = require("./providers/Provider");
const types_1 = require("./types");
class AppImageUpdater extends BaseUpdater_1.BaseUpdater {
    constructor(options, app) {
        super(options, app);
    }
    isUpdaterActive() {
        if (process.env["APPIMAGE"] == null) {
            if (process.env["SNAP"] == null) {
                this._logger.warn("APPIMAGE env is not defined, current application is not an AppImage");
            }
            else {
                this._logger.info("SNAP env is defined, updater is disabled");
            }
            return false;
        }
        return super.isUpdaterActive();
    }
    /*** @private */
    doDownloadUpdate(downloadUpdateOptions) {
        const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
        const fileInfo = (0, Provider_1.findFile)(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), "AppImage", ["rpm", "deb", "pacman"]);
        return this.executeDownload({
            fileExtension: "AppImage",
            fileInfo,
            downloadUpdateOptions,
            task: async (updateFile, downloadOptions) => {
                const oldFile = process.env["APPIMAGE"];
                if (oldFile == null) {
                    throw (0, builder_util_runtime_1.newError)("APPIMAGE env is not defined", "ERR_UPDATER_OLD_FILE_NOT_FOUND");
                }
                if (downloadUpdateOptions.disableDifferentialDownload || (await this.downloadDifferential(fileInfo, oldFile, updateFile, provider, downloadUpdateOptions))) {
                    await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions);
                }
                await (0, fs_extra_1.chmod)(updateFile, 0o755);
            },
        });
    }
    async downloadDifferential(fileInfo, oldFile, updateFile, provider, downloadUpdateOptions) {
        try {
            const downloadOptions = {
                newUrl: fileInfo.url,
                oldFile,
                logger: this._logger,
                newFile: updateFile,
                isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,
                requestHeaders: downloadUpdateOptions.requestHeaders,
                cancellationToken: downloadUpdateOptions.cancellationToken,
            };
            if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
                downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
            }
            await new FileWithEmbeddedBlockMapDifferentialDownloader_1.FileWithEmbeddedBlockMapDifferentialDownloader(fileInfo.info, this.httpExecutor, downloadOptions).download();
            return false;
        }
        catch (e) {
            this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`);
            // during test (developer machine mac) we must throw error
            return process.platform === "linux";
        }
    }
    doInstall(options) {
        const appImageFile = process.env["APPIMAGE"];
        if (appImageFile == null) {
            throw (0, builder_util_runtime_1.newError)("APPIMAGE env is not defined", "ERR_UPDATER_OLD_FILE_NOT_FOUND");
        }
        // https://stackoverflow.com/a/1712051/1910191
        (0, fs_1.unlinkSync)(appImageFile);
        let destination;
        const existingBaseName = path.basename(appImageFile);
        const installerPath = this.installerPath;
        if (installerPath == null) {
            this.dispatchError(new Error("No valid update available, can't quit and install"));
            return false;
        }
        // https://github.com/electron-userland/electron-builder/issues/2964
        // if no version in existing file name, it means that user wants to preserve current custom name
        if (path.basename(installerPath) === existingBaseName || !/\d+\.\d+\.\d+/.test(existingBaseName)) {
            // no version in the file name, overwrite existing
            destination = appImageFile;
        }
        else {
            destination = path.join(path.dirname(appImageFile), path.basename(installerPath));
        }
        (0, child_process_1.execFileSync)("mv", ["-f", installerPath, destination]);
        if (destination !== appImageFile) {
            this.emit("appimage-filename-updated", destination);
        }
        const env = {
            ...process.env,
            APPIMAGE_SILENT_INSTALL: "true",
        };
        if (options.isForceRunAfter) {
            // eslint-disable-next-line @typescript-eslint/no-floating-promises
            this.spawnLog(destination, [], env);
        }
        else {
            env.APPIMAGE_EXIT_AFTER_INSTALL = "true";
            (0, child_process_1.execFileSync)(destination, [], { env });
        }
        return true;
    }
}
exports.AppImageUpdater = AppImageUpdater;
//# sourceMappingURL=AppImageUpdater.js.map{"version":3,"file":"AppImageUpdater.js","sourceRoot":"","sources":["../src/AppImageUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllPublishOptions, newError } from \"builder-util-runtime\"\nimport { execFileSync } from \"child_process\"\nimport { chmod } from \"fs-extra\"\nimport { unlinkSync } from \"fs\"\nimport * as path from \"path\"\nimport { DownloadUpdateOptions } from \"./AppUpdater\"\nimport { BaseUpdater, InstallOptions } from \"./BaseUpdater\"\nimport { DifferentialDownloaderOptions } from \"./differentialDownloader/DifferentialDownloader\"\nimport { FileWithEmbeddedBlockMapDifferentialDownloader } from \"./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader\"\nimport { findFile, Provider } from \"./providers/Provider\"\nimport { DOWNLOAD_PROGRESS, ResolvedUpdateFileInfo } from \"./types\"\n\nexport class AppImageUpdater extends BaseUpdater {\n  constructor(options?: AllPublishOptions | null, app?: any) {\n    super(options, app)\n  }\n\n  public isUpdaterActive(): boolean {\n    if (process.env[\"APPIMAGE\"] == null) {\n      if (process.env[\"SNAP\"] == null) {\n        this._logger.warn(\"APPIMAGE env is not defined, current application is not an AppImage\")\n      } else {\n        this._logger.info(\"SNAP env is defined, updater is disabled\")\n      }\n      return false\n    }\n    return super.isUpdaterActive()\n  }\n\n  /*** @private */\n  protected doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n    const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n    const fileInfo = findFile(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), \"AppImage\", [\"rpm\", \"deb\", \"pacman\"])!\n    return this.executeDownload({\n      fileExtension: \"AppImage\",\n      fileInfo,\n      downloadUpdateOptions,\n      task: async (updateFile, downloadOptions) => {\n        const oldFile = process.env[\"APPIMAGE\"]!\n        if (oldFile == null) {\n          throw newError(\"APPIMAGE env is not defined\", \"ERR_UPDATER_OLD_FILE_NOT_FOUND\")\n        }\n\n        if (downloadUpdateOptions.disableDifferentialDownload || (await this.downloadDifferential(fileInfo, oldFile, updateFile, provider, downloadUpdateOptions))) {\n          await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions)\n        }\n\n        await chmod(updateFile, 0o755)\n      },\n    })\n  }\n\n  private async downloadDifferential(fileInfo: ResolvedUpdateFileInfo, oldFile: string, updateFile: string, provider: Provider<any>, downloadUpdateOptions: DownloadUpdateOptions) {\n    try {\n      const downloadOptions: DifferentialDownloaderOptions = {\n        newUrl: fileInfo.url,\n        oldFile,\n        logger: this._logger,\n        newFile: updateFile,\n        isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,\n        requestHeaders: downloadUpdateOptions.requestHeaders,\n        cancellationToken: downloadUpdateOptions.cancellationToken,\n      }\n\n      if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n        downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n      }\n\n      await new FileWithEmbeddedBlockMapDifferentialDownloader(fileInfo.info, this.httpExecutor, downloadOptions).download()\n      return false\n    } catch (e: any) {\n      this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`)\n      // during test (developer machine mac) we must throw error\n      return process.platform === \"linux\"\n    }\n  }\n\n  protected doInstall(options: InstallOptions): boolean {\n    const appImageFile = process.env[\"APPIMAGE\"]!\n    if (appImageFile == null) {\n      throw newError(\"APPIMAGE env is not defined\", \"ERR_UPDATER_OLD_FILE_NOT_FOUND\")\n    }\n\n    // https://stackoverflow.com/a/1712051/1910191\n    unlinkSync(appImageFile)\n\n    let destination: string\n    const existingBaseName = path.basename(appImageFile)\n    const installerPath = this.installerPath\n    if (installerPath == null) {\n      this.dispatchError(new Error(\"No valid update available, can't quit and install\"))\n      return false\n    }\n    // https://github.com/electron-userland/electron-builder/issues/2964\n    // if no version in existing file name, it means that user wants to preserve current custom name\n    if (path.basename(installerPath) === existingBaseName || !/\\d+\\.\\d+\\.\\d+/.test(existingBaseName)) {\n      // no version in the file name, overwrite existing\n      destination = appImageFile\n    } else {\n      destination = path.join(path.dirname(appImageFile), path.basename(installerPath))\n    }\n\n    execFileSync(\"mv\", [\"-f\", installerPath, destination])\n    if (destination !== appImageFile) {\n      this.emit(\"appimage-filename-updated\", destination)\n    }\n\n    const env: NodeJS.ProcessEnv = {\n      ...process.env,\n      APPIMAGE_SILENT_INSTALL: \"true\",\n    }\n\n    if (options.isForceRunAfter) {\n      // eslint-disable-next-line @typescript-eslint/no-floating-promises\n      this.spawnLog(destination, [], env)\n    } else {\n      env.APPIMAGE_EXIT_AFTER_INSTALL = \"true\"\n      execFileSync(destination, [], { env })\n    }\n    return true\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NoOpLogger = exports.AppUpdater = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const crypto_1 = require("crypto");
const os_1 = require("os");
const events_1 = require("events");
const fs_extra_1 = require("fs-extra");
const js_yaml_1 = require("js-yaml");
const lazy_val_1 = require("lazy-val");
const path = require("path");
const semver_1 = require("semver");
const DownloadedUpdateHelper_1 = require("./DownloadedUpdateHelper");
const ElectronAppAdapter_1 = require("./ElectronAppAdapter");
const electronHttpExecutor_1 = require("./electronHttpExecutor");
const GenericProvider_1 = require("./providers/GenericProvider");
const providerFactory_1 = require("./providerFactory");
const zlib_1 = require("zlib");
const util_1 = require("./util");
const GenericDifferentialDownloader_1 = require("./differentialDownloader/GenericDifferentialDownloader");
const types_1 = require("./types");
class AppUpdater extends events_1.EventEmitter {
    /**
     * Get the update channel. Doesn't return `channel` from the update configuration, only if was previously set.
     */
    get channel() {
        return this._channel;
    }
    /**
     * Set the update channel. Overrides `channel` in the update configuration.
     *
     * `allowDowngrade` will be automatically set to `true`. If this behavior is not suitable for you, simple set `allowDowngrade` explicitly after.
     */
    set channel(value) {
        if (this._channel != null) {
            // noinspection SuspiciousTypeOfGuard
            if (typeof value !== "string") {
                throw (0, builder_util_runtime_1.newError)(`Channel must be a string, but got: ${value}`, "ERR_UPDATER_INVALID_CHANNEL");
            }
            else if (value.length === 0) {
                throw (0, builder_util_runtime_1.newError)(`Channel must be not an empty string`, "ERR_UPDATER_INVALID_CHANNEL");
            }
        }
        this._channel = value;
        this.allowDowngrade = true;
    }
    /**
     *  Shortcut for explicitly adding auth tokens to request headers
     */
    addAuthHeader(token) {
        this.requestHeaders = Object.assign({}, this.requestHeaders, {
            authorization: token,
        });
    }
    // noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols
    get netSession() {
        return (0, electronHttpExecutor_1.getNetSession)();
    }
    /**
     * The logger. You can pass [electron-log](https://github.com/megahertz/electron-log), [winston](https://github.com/winstonjs/winston) or another logger with the following interface: `{ info(), warn(), error() }`.
     * Set it to `null` if you would like to disable a logging feature.
     */
    get logger() {
        return this._logger;
    }
    set logger(value) {
        this._logger = value == null ? new NoOpLogger() : value;
    }
    // noinspection JSUnusedGlobalSymbols
    /**
     * test only
     * @private
     */
    set updateConfigPath(value) {
        this.clientPromise = null;
        this._appUpdateConfigPath = value;
        this.configOnDisk = new lazy_val_1.Lazy(() => this.loadUpdateConfig());
    }
    /**
     * Allows developer to override default logic for determining if an update is supported.
     * The default logic compares the `UpdateInfo` minimum system version against the `os.release()` with `semver` package
     */
    get isUpdateSupported() {
        return this._isUpdateSupported;
    }
    set isUpdateSupported(value) {
        if (value) {
            this._isUpdateSupported = value;
        }
    }
    constructor(options, app) {
        super();
        /**
         * Whether to automatically download an update when it is found.
         * @default true
         */
        this.autoDownload = true;
        /**
         * Whether to automatically install a downloaded update on app quit (if `quitAndInstall` was not called before).
         * @default true
         */
        this.autoInstallOnAppQuit = true;
        /**
         * Whether to run the app after finish install when run the installer is NOT in silent mode.
         * @default true
         */
        this.autoRunAppAfterInstall = true;
        /**
         * *GitHub provider only.* Whether to allow update to pre-release versions. Defaults to `true` if application version contains prerelease components (e.g. `0.12.1-alpha.1`, here `alpha` is a prerelease component), otherwise `false`.
         *
         * If `true`, downgrade will be allowed (`allowDowngrade` will be set to `true`).
         */
        this.allowPrerelease = false;
        /**
         * *GitHub provider only.* Get all release notes (from current version to latest), not just the latest.
         * @default false
         */
        this.fullChangelog = false;
        /**
         * Whether to allow version downgrade (when a user from the beta channel wants to go back to the stable channel).
         *
         * Taken in account only if channel differs (pre-release version component in terms of semantic versioning).
         *
         * @default false
         */
        this.allowDowngrade = false;
        /**
         * Web installer files might not have signature verification, this switch prevents to load them unless it is needed.
         *
         * Currently false to prevent breaking the current API, but it should be changed to default true at some point that
         * breaking changes are allowed.
         *
         * @default false
         */
        this.disableWebInstaller = false;
        /**
         * *NSIS only* Disable differential downloads and always perform full download of installer.
         *
         * @default false
         */
        this.disableDifferentialDownload = false;
        /**
         * Allows developer to force the updater to work in "dev" mode, looking for "dev-app-update.yml" instead of "app-update.yml"
         * Dev: `path.join(this.app.getAppPath(), "dev-app-update.yml")`
         * Prod: `path.join(process.resourcesPath!, "app-update.yml")`
         *
         * @default false
         */
        this.forceDevUpdateConfig = false;
        this._channel = null;
        this.downloadedUpdateHelper = null;
        /**
         *  The request headers.
         */
        this.requestHeaders = null;
        this._logger = console;
        // noinspection JSUnusedGlobalSymbols
        /**
         * For type safety you can use signals, e.g. `autoUpdater.signals.updateDownloaded(() => {})` instead of `autoUpdater.on('update-available', () => {})`
         */
        this.signals = new types_1.UpdaterSignal(this);
        this._appUpdateConfigPath = null;
        this._isUpdateSupported = (updateInfo) => this.checkIfUpdateSupported(updateInfo);
        this.clientPromise = null;
        this.stagingUserIdPromise = new lazy_val_1.Lazy(() => this.getOrCreateStagingUserId());
        // public, allow to read old config for anyone
        /** @internal */
        this.configOnDisk = new lazy_val_1.Lazy(() => this.loadUpdateConfig());
        this.checkForUpdatesPromise = null;
        this.downloadPromise = null;
        this.updateInfoAndProvider = null;
        /**
         * @private
         * @internal
         */
        this._testOnlyOptions = null;
        this.on("error", (error) => {
            this._logger.error(`Error: ${error.stack || error.message}`);
        });
        if (app == null) {
            this.app = new ElectronAppAdapter_1.ElectronAppAdapter();
            this.httpExecutor = new electronHttpExecutor_1.ElectronHttpExecutor((authInfo, callback) => this.emit("login", authInfo, callback));
        }
        else {
            this.app = app;
            this.httpExecutor = null;
        }
        const currentVersionString = this.app.version;
        const currentVersion = (0, semver_1.parse)(currentVersionString);
        if (currentVersion == null) {
            throw (0, builder_util_runtime_1.newError)(`App version is not a valid semver version: "${currentVersionString}"`, "ERR_UPDATER_INVALID_VERSION");
        }
        this.currentVersion = currentVersion;
        this.allowPrerelease = hasPrereleaseComponents(currentVersion);
        if (options != null) {
            this.setFeedURL(options);
            if (typeof options !== "string" && options.requestHeaders) {
                this.requestHeaders = options.requestHeaders;
            }
        }
    }
    //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols
    getFeedURL() {
        return "Deprecated. Do not use it.";
    }
    /**
     * Configure update provider. If value is `string`, [GenericServerOptions](./publish.md#genericserveroptions) will be set with value as `url`.
     * @param options If you want to override configuration in the `app-update.yml`.
     */
    setFeedURL(options) {
        const runtimeOptions = this.createProviderRuntimeOptions();
        // https://github.com/electron-userland/electron-builder/issues/1105
        let provider;
        if (typeof options === "string") {
            provider = new GenericProvider_1.GenericProvider({ provider: "generic", url: options }, this, {
                ...runtimeOptions,
                isUseMultipleRangeRequest: (0, providerFactory_1.isUrlProbablySupportMultiRangeRequests)(options),
            });
        }
        else {
            provider = (0, providerFactory_1.createClient)(options, this, runtimeOptions);
        }
        this.clientPromise = Promise.resolve(provider);
    }
    /**
     * Asks the server whether there is an update.
     * @returns null if the updater is disabled, otherwise info about the latest version
     */
    checkForUpdates() {
        if (!this.isUpdaterActive()) {
            return Promise.resolve(null);
        }
        let checkForUpdatesPromise = this.checkForUpdatesPromise;
        if (checkForUpdatesPromise != null) {
            this._logger.info("Checking for update (already in progress)");
            return checkForUpdatesPromise;
        }
        const nullizePromise = () => (this.checkForUpdatesPromise = null);
        this._logger.info("Checking for update");
        checkForUpdatesPromise = this.doCheckForUpdates()
            .then(it => {
            nullizePromise();
            return it;
        })
            .catch((e) => {
            nullizePromise();
            this.emit("error", e, `Cannot check for updates: ${(e.stack || e).toString()}`);
            throw e;
        });
        this.checkForUpdatesPromise = checkForUpdatesPromise;
        return checkForUpdatesPromise;
    }
    isUpdaterActive() {
        const isEnabled = this.app.isPackaged || this.forceDevUpdateConfig;
        if (!isEnabled) {
            this._logger.info("Skip checkForUpdates because application is not packed and dev update config is not forced");
            return false;
        }
        return true;
    }
    // noinspection JSUnusedGlobalSymbols
    checkForUpdatesAndNotify(downloadNotification) {
        return this.checkForUpdates().then(it => {
            if (!(it === null || it === void 0 ? void 0 : it.downloadPromise)) {
                if (this._logger.debug != null) {
                    this._logger.debug("checkForUpdatesAndNotify called, downloadPromise is null");
                }
                return it;
            }
            void it.downloadPromise.then(() => {
                const notificationContent = AppUpdater.formatDownloadNotification(it.updateInfo.version, this.app.name, downloadNotification);
                new (require("electron").Notification)(notificationContent).show();
            });
            return it;
        });
    }
    static formatDownloadNotification(version, appName, downloadNotification) {
        if (downloadNotification == null) {
            downloadNotification = {
                title: "A new update is ready to install",
                body: `{appName} version {version} has been downloaded and will be automatically installed on exit`,
            };
        }
        downloadNotification = {
            title: downloadNotification.title.replace("{appName}", appName).replace("{version}", version),
            body: downloadNotification.body.replace("{appName}", appName).replace("{version}", version),
        };
        return downloadNotification;
    }
    async isStagingMatch(updateInfo) {
        const rawStagingPercentage = updateInfo.stagingPercentage;
        let stagingPercentage = rawStagingPercentage;
        if (stagingPercentage == null) {
            return true;
        }
        stagingPercentage = parseInt(stagingPercentage, 10);
        if (isNaN(stagingPercentage)) {
            this._logger.warn(`Staging percentage is NaN: ${rawStagingPercentage}`);
            return true;
        }
        // convert from user 0-100 to internal 0-1
        stagingPercentage = stagingPercentage / 100;
        const stagingUserId = await this.stagingUserIdPromise.value;
        const val = builder_util_runtime_1.UUID.parse(stagingUserId).readUInt32BE(12);
        const percentage = val / 0xffffffff;
        this._logger.info(`Staging percentage: ${stagingPercentage}, percentage: ${percentage}, user id: ${stagingUserId}`);
        return percentage < stagingPercentage;
    }
    computeFinalHeaders(headers) {
        if (this.requestHeaders != null) {
            Object.assign(headers, this.requestHeaders);
        }
        return headers;
    }
    async isUpdateAvailable(updateInfo) {
        const latestVersion = (0, semver_1.parse)(updateInfo.version);
        if (latestVersion == null) {
            throw (0, builder_util_runtime_1.newError)(`This file could not be downloaded, or the latest version (from update server) does not have a valid semver version: "${updateInfo.version}"`, "ERR_UPDATER_INVALID_VERSION");
        }
        const currentVersion = this.currentVersion;
        if ((0, semver_1.eq)(latestVersion, currentVersion)) {
            return false;
        }
        if (!(await Promise.resolve(this.isUpdateSupported(updateInfo)))) {
            return false;
        }
        const isStagingMatch = await this.isStagingMatch(updateInfo);
        if (!isStagingMatch) {
            return false;
        }
        // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405033227
        // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405030797
        const isLatestVersionNewer = (0, semver_1.gt)(latestVersion, currentVersion);
        const isLatestVersionOlder = (0, semver_1.lt)(latestVersion, currentVersion);
        if (isLatestVersionNewer) {
            return true;
        }
        return this.allowDowngrade && isLatestVersionOlder;
    }
    checkIfUpdateSupported(updateInfo) {
        const minimumSystemVersion = updateInfo === null || updateInfo === void 0 ? void 0 : updateInfo.minimumSystemVersion;
        const currentOSVersion = (0, os_1.release)();
        if (minimumSystemVersion) {
            try {
                if ((0, semver_1.lt)(currentOSVersion, minimumSystemVersion)) {
                    this._logger.info(`Current OS version ${currentOSVersion} is less than the minimum OS version required ${minimumSystemVersion} for version ${currentOSVersion}`);
                    return false;
                }
            }
            catch (e) {
                this._logger.warn(`Failed to compare current OS version(${currentOSVersion}) with minimum OS version(${minimumSystemVersion}): ${(e.message || e).toString()}`);
            }
        }
        return true;
    }
    async getUpdateInfoAndProvider() {
        await this.app.whenReady();
        if (this.clientPromise == null) {
            this.clientPromise = this.configOnDisk.value.then(it => (0, providerFactory_1.createClient)(it, this, this.createProviderRuntimeOptions()));
        }
        const client = await this.clientPromise;
        const stagingUserId = await this.stagingUserIdPromise.value;
        client.setRequestHeaders(this.computeFinalHeaders({ "x-user-staging-id": stagingUserId }));
        return {
            info: await client.getLatestVersion(),
            provider: client,
        };
    }
    createProviderRuntimeOptions() {
        return {
            isUseMultipleRangeRequest: true,
            platform: this._testOnlyOptions == null ? process.platform : this._testOnlyOptions.platform,
            executor: this.httpExecutor,
        };
    }
    async doCheckForUpdates() {
        this.emit("checking-for-update");
        const result = await this.getUpdateInfoAndProvider();
        const updateInfo = result.info;
        if (!(await this.isUpdateAvailable(updateInfo))) {
            this._logger.info(`Update for version ${this.currentVersion.format()} is not available (latest version: ${updateInfo.version}, downgrade is ${this.allowDowngrade ? "allowed" : "disallowed"}).`);
            this.emit("update-not-available", updateInfo);
            return {
                isUpdateAvailable: false,
                versionInfo: updateInfo,
                updateInfo,
            };
        }
        this.updateInfoAndProvider = result;
        this.onUpdateAvailable(updateInfo);
        const cancellationToken = new builder_util_runtime_1.CancellationToken();
        //noinspection ES6MissingAwait
        return {
            isUpdateAvailable: true,
            versionInfo: updateInfo,
            updateInfo,
            cancellationToken,
            downloadPromise: this.autoDownload ? this.downloadUpdate(cancellationToken) : null,
        };
    }
    onUpdateAvailable(updateInfo) {
        this._logger.info(`Found version ${updateInfo.version} (url: ${(0, builder_util_runtime_1.asArray)(updateInfo.files)
            .map(it => it.url)
            .join(", ")})`);
        this.emit("update-available", updateInfo);
    }
    /**
     * Start downloading update manually. You can use this method if `autoDownload` option is set to `false`.
     * @returns {Promise<Array<string>>} Paths to downloaded files.
     */
    downloadUpdate(cancellationToken = new builder_util_runtime_1.CancellationToken()) {
        const updateInfoAndProvider = this.updateInfoAndProvider;
        if (updateInfoAndProvider == null) {
            const error = new Error("Please check update first");
            this.dispatchError(error);
            return Promise.reject(error);
        }
        if (this.downloadPromise != null) {
            this._logger.info("Downloading update (already in progress)");
            return this.downloadPromise;
        }
        this._logger.info(`Downloading update from ${(0, builder_util_runtime_1.asArray)(updateInfoAndProvider.info.files)
            .map(it => it.url)
            .join(", ")}`);
        const errorHandler = (e) => {
            // https://github.com/electron-userland/electron-builder/issues/1150#issuecomment-436891159
            if (!(e instanceof builder_util_runtime_1.CancellationError)) {
                try {
                    this.dispatchError(e);
                }
                catch (nestedError) {
                    this._logger.warn(`Cannot dispatch error event: ${nestedError.stack || nestedError}`);
                }
            }
            return e;
        };
        this.downloadPromise = this.doDownloadUpdate({
            updateInfoAndProvider,
            requestHeaders: this.computeRequestHeaders(updateInfoAndProvider.provider),
            cancellationToken,
            disableWebInstaller: this.disableWebInstaller,
            disableDifferentialDownload: this.disableDifferentialDownload,
        })
            .catch((e) => {
            throw errorHandler(e);
        })
            .finally(() => {
            this.downloadPromise = null;
        });
        return this.downloadPromise;
    }
    dispatchError(e) {
        this.emit("error", e, (e.stack || e).toString());
    }
    dispatchUpdateDownloaded(event) {
        this.emit(types_1.UPDATE_DOWNLOADED, event);
    }
    async loadUpdateConfig() {
        if (this._appUpdateConfigPath == null) {
            this._appUpdateConfigPath = this.app.appUpdateConfigPath;
        }
        return (0, js_yaml_1.load)(await (0, fs_extra_1.readFile)(this._appUpdateConfigPath, "utf-8"));
    }
    computeRequestHeaders(provider) {
        const fileExtraDownloadHeaders = provider.fileExtraDownloadHeaders;
        if (fileExtraDownloadHeaders != null) {
            const requestHeaders = this.requestHeaders;
            return requestHeaders == null
                ? fileExtraDownloadHeaders
                : {
                    ...fileExtraDownloadHeaders,
                    ...requestHeaders,
                };
        }
        return this.computeFinalHeaders({ accept: "*/*" });
    }
    async getOrCreateStagingUserId() {
        const file = path.join(this.app.userDataPath, ".updaterId");
        try {
            const id = await (0, fs_extra_1.readFile)(file, "utf-8");
            if (builder_util_runtime_1.UUID.check(id)) {
                return id;
            }
            else {
                this._logger.warn(`Staging user id file exists, but content was invalid: ${id}`);
            }
        }
        catch (e) {
            if (e.code !== "ENOENT") {
                this._logger.warn(`Couldn't read staging user ID, creating a blank one: ${e}`);
            }
        }
        const id = builder_util_runtime_1.UUID.v5((0, crypto_1.randomBytes)(4096), builder_util_runtime_1.UUID.OID);
        this._logger.info(`Generated new staging user ID: ${id}`);
        try {
            await (0, fs_extra_1.outputFile)(file, id);
        }
        catch (e) {
            this._logger.warn(`Couldn't write out staging user ID: ${e}`);
        }
        return id;
    }
    /** @internal */
    get isAddNoCacheQuery() {
        const headers = this.requestHeaders;
        // https://github.com/electron-userland/electron-builder/issues/3021
        if (headers == null) {
            return true;
        }
        for (const headerName of Object.keys(headers)) {
            const s = headerName.toLowerCase();
            if (s === "authorization" || s === "private-token") {
                return false;
            }
        }
        return true;
    }
    async getOrCreateDownloadHelper() {
        let result = this.downloadedUpdateHelper;
        if (result == null) {
            const dirName = (await this.configOnDisk.value).updaterCacheDirName;
            const logger = this._logger;
            if (dirName == null) {
                logger.error("updaterCacheDirName is not specified in app-update.yml Was app build using at least electron-builder 20.34.0?");
            }
            const cacheDir = path.join(this.app.baseCachePath, dirName || this.app.name);
            if (logger.debug != null) {
                logger.debug(`updater cache dir: ${cacheDir}`);
            }
            result = new DownloadedUpdateHelper_1.DownloadedUpdateHelper(cacheDir);
            this.downloadedUpdateHelper = result;
        }
        return result;
    }
    async executeDownload(taskOptions) {
        const fileInfo = taskOptions.fileInfo;
        const downloadOptions = {
            headers: taskOptions.downloadUpdateOptions.requestHeaders,
            cancellationToken: taskOptions.downloadUpdateOptions.cancellationToken,
            sha2: fileInfo.info.sha2,
            sha512: fileInfo.info.sha512,
        };
        if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
            downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
        }
        const updateInfo = taskOptions.downloadUpdateOptions.updateInfoAndProvider.info;
        const version = updateInfo.version;
        const packageInfo = fileInfo.packageInfo;
        function getCacheUpdateFileName() {
            // NodeJS URL doesn't decode automatically
            const urlPath = decodeURIComponent(taskOptions.fileInfo.url.pathname);
            if (urlPath.endsWith(`.${taskOptions.fileExtension}`)) {
                return path.basename(urlPath);
            }
            else {
                // url like /latest, generate name
                return taskOptions.fileInfo.info.url;
            }
        }
        const downloadedUpdateHelper = await this.getOrCreateDownloadHelper();
        const cacheDir = downloadedUpdateHelper.cacheDirForPendingUpdate;
        await (0, fs_extra_1.mkdir)(cacheDir, { recursive: true });
        const updateFileName = getCacheUpdateFileName();
        let updateFile = path.join(cacheDir, updateFileName);
        const packageFile = packageInfo == null ? null : path.join(cacheDir, `package-${version}${path.extname(packageInfo.path) || ".7z"}`);
        const done = async (isSaveCache) => {
            await downloadedUpdateHelper.setDownloadedFile(updateFile, packageFile, updateInfo, fileInfo, updateFileName, isSaveCache);
            await taskOptions.done({
                ...updateInfo,
                downloadedFile: updateFile,
            });
            return packageFile == null ? [updateFile] : [updateFile, packageFile];
        };
        const log = this._logger;
        const cachedUpdateFile = await downloadedUpdateHelper.validateDownloadedPath(updateFile, updateInfo, fileInfo, log);
        if (cachedUpdateFile != null) {
            updateFile = cachedUpdateFile;
            return await done(false);
        }
        const removeFileIfAny = async () => {
            await downloadedUpdateHelper.clear().catch(() => {
                // ignore
            });
            return await (0, fs_extra_1.unlink)(updateFile).catch(() => {
                // ignore
            });
        };
        const tempUpdateFile = await (0, DownloadedUpdateHelper_1.createTempUpdateFile)(`temp-${updateFileName}`, cacheDir, log);
        try {
            await taskOptions.task(tempUpdateFile, downloadOptions, packageFile, removeFileIfAny);
            await (0, builder_util_runtime_1.retry)(() => (0, fs_extra_1.rename)(tempUpdateFile, updateFile), 60, 500, 0, 0, error => error instanceof Error && /^EBUSY:/.test(error.message));
        }
        catch (e) {
            await removeFileIfAny();
            if (e instanceof builder_util_runtime_1.CancellationError) {
                log.info("cancelled");
                this.emit("update-cancelled", updateInfo);
            }
            throw e;
        }
        log.info(`New version ${version} has been downloaded to ${updateFile}`);
        return await done(true);
    }
    async differentialDownloadInstaller(fileInfo, downloadUpdateOptions, installerPath, provider, oldInstallerFileName) {
        try {
            if (this._testOnlyOptions != null && !this._testOnlyOptions.isUseDifferentialDownload) {
                return true;
            }
            const blockmapFileUrls = (0, util_1.blockmapFiles)(fileInfo.url, this.app.version, downloadUpdateOptions.updateInfoAndProvider.info.version);
            this._logger.info(`Download block maps (old: "${blockmapFileUrls[0]}", new: ${blockmapFileUrls[1]})`);
            const downloadBlockMap = async (url) => {
                const data = await this.httpExecutor.downloadToBuffer(url, {
                    headers: downloadUpdateOptions.requestHeaders,
                    cancellationToken: downloadUpdateOptions.cancellationToken,
                });
                if (data == null || data.length === 0) {
                    throw new Error(`Blockmap "${url.href}" is empty`);
                }
                try {
                    return JSON.parse((0, zlib_1.gunzipSync)(data).toString());
                }
                catch (e) {
                    throw new Error(`Cannot parse blockmap "${url.href}", error: ${e}`);
                }
            };
            const downloadOptions = {
                newUrl: fileInfo.url,
                oldFile: path.join(this.downloadedUpdateHelper.cacheDir, oldInstallerFileName),
                logger: this._logger,
                newFile: installerPath,
                isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,
                requestHeaders: downloadUpdateOptions.requestHeaders,
                cancellationToken: downloadUpdateOptions.cancellationToken,
            };
            if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
                downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
            }
            const blockMapDataList = await Promise.all(blockmapFileUrls.map(u => downloadBlockMap(u)));
            await new GenericDifferentialDownloader_1.GenericDifferentialDownloader(fileInfo.info, this.httpExecutor, downloadOptions).download(blockMapDataList[0], blockMapDataList[1]);
            return false;
        }
        catch (e) {
            this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`);
            if (this._testOnlyOptions != null) {
                // test mode
                throw e;
            }
            return true;
        }
    }
}
exports.AppUpdater = AppUpdater;
function hasPrereleaseComponents(version) {
    const versionPrereleaseComponent = (0, semver_1.prerelease)(version);
    return versionPrereleaseComponent != null && versionPrereleaseComponent.length > 0;
}
/** @private */
class NoOpLogger {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    info(message) {
        // ignore
    }
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    warn(message) {
        // ignore
    }
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    error(message) {
        // ignore
    }
}
exports.NoOpLogger = NoOpLogger;
//# sourceMappingURL=AppUpdater.js.map{"version":3,"file":"AppUpdater.js","sourceRoot":"","sources":["../src/AppUpdater.ts"],"names":[],"mappings":";;;AAAA,+DAa6B;AAC7B,mCAAoC;AACpC,2BAA4B;AAC5B,mCAAqC;AACrC,uCAAsE;AAEtE,qCAA8B;AAC9B,uCAA+B;AAC/B,6BAA4B;AAC5B,mCAA8K;AAE9K,qEAAuF;AACvF,6DAAyD;AACzD,iEAA2F;AAC3F,iEAA6D;AAC7D,uDAAwF;AAKxF,+BAAiC;AACjC,iCAAsC;AAEtC,0GAAsG;AACtG,mCAAuJ;AAevJ,MAAsB,UAAW,SAAS,qBAAyD;IA4EjG;;OAEG;IACH,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED;;;;OAIG;IACH,IAAI,OAAO,CAAC,KAAoB;QAC9B,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;YAC1B,qCAAqC;YACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,MAAM,IAAA,+BAAQ,EAAC,sCAAsC,KAAK,EAAE,EAAE,6BAA6B,CAAC,CAAA;YAC9F,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,MAAM,IAAA,+BAAQ,EAAC,qCAAqC,EAAE,6BAA6B,CAAC,CAAA;YACtF,CAAC;QACH,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAA;QACrB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;IAC5B,CAAC;IAOD;;OAEG;IACH,aAAa,CAAC,KAAa;QACzB,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,cAAc,EAAE;YAC3D,aAAa,EAAE,KAAK;SACrB,CAAC,CAAA;IACJ,CAAC;IAID,yDAAyD;IACzD,IAAI,UAAU;QACZ,OAAO,IAAA,oCAAa,GAAE,CAAA;IACxB,CAAC;IAED;;;OAGG;IACH,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,IAAI,MAAM,CAAC,KAAoB;QAC7B,IAAI,CAAC,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,KAAK,CAAA;IACzD,CAAC;IAUD,qCAAqC;IACrC;;;OAGG;IACH,IAAI,gBAAgB,CAAC,KAAoB;QACvC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAA;QACzB,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAA;QACjC,IAAI,CAAC,YAAY,GAAG,IAAI,eAAI,CAAM,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAA;IAClE,CAAC;IAID;;;OAGG;IACH,IAAI,iBAAiB;QACnB,OAAO,IAAI,CAAC,kBAAkB,CAAA;IAChC,CAAC;IAED,IAAI,iBAAiB,CAAC,KAA0B;QAC9C,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAA;QACjC,CAAC;IACH,CAAC;IAoBD,YAAsB,OAA6C,EAAE,GAAgB;QACnF,KAAK,EAAE,CAAA;QA5LT;;;WAGG;QACH,iBAAY,GAAG,IAAI,CAAA;QAEnB;;;WAGG;QACH,yBAAoB,GAAG,IAAI,CAAA;QAE3B;;;WAGG;QACH,2BAAsB,GAAG,IAAI,CAAA;QAE7B;;;;WAIG;QACH,oBAAe,GAAG,KAAK,CAAA;QAEvB;;;WAGG;QACH,kBAAa,GAAG,KAAK,CAAA;QAErB;;;;;;WAMG;QACH,mBAAc,GAAG,KAAK,CAAA;QAEtB;;;;;;;WAOG;QACH,wBAAmB,GAAG,KAAK,CAAA;QAE3B;;;;WAIG;QACH,gCAA2B,GAAG,KAAK,CAAA;QAEnC;;;;;;WAMG;QACH,yBAAoB,GAAG,KAAK,CAAA;QAOpB,aAAQ,GAAkB,IAAI,CAAA;QAE5B,2BAAsB,GAAkC,IAAI,CAAA;QA4BtE;;WAEG;QACH,mBAAc,GAA+B,IAAI,CAAA;QAWvC,YAAO,GAAW,OAAO,CAAA;QAmBnC,qCAAqC;QACrC;;WAEG;QACM,YAAO,GAAG,IAAI,qBAAa,CAAC,IAAI,CAAC,CAAA;QAElC,yBAAoB,GAAkB,IAAI,CAAA;QAaxC,uBAAkB,GAAwB,CAAC,UAAsB,EAA8B,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAA;QAgB3I,kBAAa,GAAkC,IAAI,CAAA;QAExC,yBAAoB,GAAG,IAAI,eAAI,CAAS,GAAG,EAAE,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC,CAAA;QAEjG,8CAA8C;QAC9C,gBAAgB;QAChB,iBAAY,GAAG,IAAI,eAAI,CAAM,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAA;QAEnD,2BAAsB,GAAsC,IAAI,CAAA;QAChE,oBAAe,GAAkC,IAAI,CAAA;QAInD,0BAAqB,GAAiC,IAAI,CAAA;QAoapE;;;WAGG;QACH,qBAAgB,GAAkC,IAAI,CAAA;QAhapD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE;YAChC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAC9D,CAAC,CAAC,CAAA;QAEF,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;YAChB,IAAI,CAAC,GAAG,GAAG,IAAI,uCAAkB,EAAE,CAAA;YACnC,IAAI,CAAC,YAAY,GAAG,IAAI,2CAAoB,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAA;QAC9G,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;YACd,IAAI,CAAC,YAAY,GAAG,IAAW,CAAA;QACjC,CAAC;QAED,MAAM,oBAAoB,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAA;QAC7C,MAAM,cAAc,GAAG,IAAA,cAAY,EAAC,oBAAoB,CAAC,CAAA;QACzD,IAAI,cAAc,IAAI,IAAI,EAAE,CAAC;YAC3B,MAAM,IAAA,+BAAQ,EAAC,+CAA+C,oBAAoB,GAAG,EAAE,6BAA6B,CAAC,CAAA;QACvH,CAAC;QACD,IAAI,CAAC,cAAc,GAAG,cAAc,CAAA;QACpC,IAAI,CAAC,eAAe,GAAG,uBAAuB,CAAC,cAAc,CAAC,CAAA;QAE9D,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACpB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;YAExB,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;gBAC1D,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAA;YAC9C,CAAC;QACH,CAAC;IACH,CAAC;IAED,wDAAwD;IACxD,UAAU;QACR,OAAO,4BAA4B,CAAA;IACrC,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,OAA0D;QACnE,MAAM,cAAc,GAAG,IAAI,CAAC,4BAA4B,EAAE,CAAA;QAC1D,oEAAoE;QACpE,IAAI,QAAuB,CAAA;QAC3B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,QAAQ,GAAG,IAAI,iCAAe,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE;gBAC1E,GAAG,cAAc;gBACjB,yBAAyB,EAAE,IAAA,wDAAsC,EAAC,OAAO,CAAC;aAC3E,CAAC,CAAA;QACJ,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,IAAA,8BAAY,EAAC,OAAO,EAAE,IAAI,EAAE,cAAc,CAAC,CAAA;QACxD,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAChD,CAAC;IAED;;;OAGG;IACH,eAAe;QACb,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YAC5B,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC9B,CAAC;QAED,IAAI,sBAAsB,GAAG,IAAI,CAAC,sBAAsB,CAAA;QACxD,IAAI,sBAAsB,IAAI,IAAI,EAAE,CAAC;YACnC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAA;YAC9D,OAAO,sBAAsB,CAAA;QAC/B,CAAC;QAED,MAAM,cAAc,GAAG,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAA;QAEjE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;QACxC,sBAAsB,GAAG,IAAI,CAAC,iBAAiB,EAAE;aAC9C,IAAI,CAAC,EAAE,CAAC,EAAE;YACT,cAAc,EAAE,CAAA;YAChB,OAAO,EAAE,CAAA;QACX,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,CAAM,EAAE,EAAE;YAChB,cAAc,EAAE,CAAA;YAChB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,6BAA6B,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;YAC/E,MAAM,CAAC,CAAA;QACT,CAAC,CAAC,CAAA;QAEJ,IAAI,CAAC,sBAAsB,GAAG,sBAAsB,CAAA;QACpD,OAAO,sBAAsB,CAAA;IAC/B,CAAC;IAEM,eAAe;QACpB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,oBAAoB,CAAA;QAClE,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,4FAA4F,CAAC,CAAA;YAC/G,OAAO,KAAK,CAAA;QACd,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,qCAAqC;IACrC,wBAAwB,CAAC,oBAA2C;QAClE,OAAO,IAAI,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;YACtC,IAAI,CAAC,CAAA,EAAE,aAAF,EAAE,uBAAF,EAAE,CAAE,eAAe,CAAA,EAAE,CAAC;gBACzB,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;oBAC/B,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAA;gBAChF,CAAC;gBACD,OAAO,EAAE,CAAA;YACX,CAAC;YAED,KAAK,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE;gBAChC,MAAM,mBAAmB,GAAG,UAAU,CAAC,0BAA0B,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAA;gBAC7H,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,mBAAmB,CAAC,CAAC,IAAI,EAAE,CAAA;YACpE,CAAC,CAAC,CAAA;YAEF,OAAO,EAAE,CAAA;QACX,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,MAAM,CAAC,0BAA0B,CAAC,OAAe,EAAE,OAAe,EAAE,oBAA2C;QACrH,IAAI,oBAAoB,IAAI,IAAI,EAAE,CAAC;YACjC,oBAAoB,GAAG;gBACrB,KAAK,EAAE,kCAAkC;gBACzC,IAAI,EAAE,6FAA6F;aACpG,CAAA;QACH,CAAC;QACD,oBAAoB,GAAG;YACrB,KAAK,EAAE,oBAAoB,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC;YAC7F,IAAI,EAAE,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC;SAC5F,CAAA;QACD,OAAO,oBAAoB,CAAA;IAC7B,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,UAAsB;QACjD,MAAM,oBAAoB,GAAG,UAAU,CAAC,iBAAiB,CAAA;QACzD,IAAI,iBAAiB,GAAG,oBAAoB,CAAA;QAC5C,IAAI,iBAAiB,IAAI,IAAI,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAA;QACb,CAAC;QAED,iBAAiB,GAAG,QAAQ,CAAC,iBAAwB,EAAE,EAAE,CAAC,CAAA;QAC1D,IAAI,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,8BAA8B,oBAAoB,EAAE,CAAC,CAAA;YACvE,OAAO,IAAI,CAAA;QACb,CAAC;QAED,0CAA0C;QAC1C,iBAAiB,GAAG,iBAAiB,GAAG,GAAG,CAAA;QAE3C,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAA;QAC3D,MAAM,GAAG,GAAG,2BAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;QACtD,MAAM,UAAU,GAAG,GAAG,GAAG,UAAU,CAAA;QACnC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,uBAAuB,iBAAiB,iBAAiB,UAAU,cAAc,aAAa,EAAE,CAAC,CAAA;QACnH,OAAO,UAAU,GAAG,iBAAiB,CAAA;IACvC,CAAC;IAEO,mBAAmB,CAAC,OAA4B;QACtD,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;YAChC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,CAAA;QAC7C,CAAC;QACD,OAAO,OAAO,CAAA;IAChB,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,UAAsB;QACpD,MAAM,aAAa,GAAG,IAAA,cAAY,EAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QACtD,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;YAC1B,MAAM,IAAA,+BAAQ,EACZ,wHAAwH,UAAU,CAAC,OAAO,GAAG,EAC7I,6BAA6B,CAC9B,CAAA;QACH,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAA;QAC1C,IAAI,IAAA,WAAe,EAAC,aAAa,EAAE,cAAc,CAAC,EAAE,CAAC;YACnD,OAAO,KAAK,CAAA;QACd,CAAC;QAED,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YACjE,OAAO,KAAK,CAAA;QACd,CAAC;QAED,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAA;QAC5D,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,OAAO,KAAK,CAAA;QACd,CAAC;QAED,yFAAyF;QACzF,yFAAyF;QACzF,MAAM,oBAAoB,GAAG,IAAA,WAAoB,EAAC,aAAa,EAAE,cAAc,CAAC,CAAA;QAChF,MAAM,oBAAoB,GAAG,IAAA,WAAiB,EAAC,aAAa,EAAE,cAAc,CAAC,CAAA;QAE7E,IAAI,oBAAoB,EAAE,CAAC;YACzB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,IAAI,oBAAoB,CAAA;IACpD,CAAC;IAEO,sBAAsB,CAAC,UAAsB;QACnD,MAAM,oBAAoB,GAAG,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,oBAAoB,CAAA;QAC7D,MAAM,gBAAgB,GAAG,IAAA,YAAO,GAAE,CAAA;QAClC,IAAI,oBAAoB,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,IAAI,IAAA,WAAiB,EAAC,gBAAgB,EAAE,oBAAoB,CAAC,EAAE,CAAC;oBAC9D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,sBAAsB,gBAAgB,iDAAiD,oBAAoB,gBAAgB,gBAAgB,EAAE,CAAC,CAAA;oBAChK,OAAO,KAAK,CAAA;gBACd,CAAC;YACH,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,wCAAwC,gBAAgB,6BAA6B,oBAAoB,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;YACjK,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAES,KAAK,CAAC,wBAAwB;QACtC,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAA;QAE1B,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,EAAE,CAAC;YAC/B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAA,8BAAY,EAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,4BAA4B,EAAE,CAAC,CAAC,CAAA;QACtH,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAA;QACvC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAA;QAC3D,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,aAAa,EAAE,CAAC,CAAC,CAAA;QAC1F,OAAO;YACL,IAAI,EAAE,MAAM,MAAM,CAAC,gBAAgB,EAAE;YACrC,QAAQ,EAAE,MAAM;SACjB,CAAA;IACH,CAAC;IAEO,4BAA4B;QAClC,OAAO;YACL,yBAAyB,EAAE,IAAI;YAC/B,QAAQ,EAAE,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAE,OAAO,CAAC,QAA6B,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ;YACjH,QAAQ,EAAE,IAAI,CAAC,YAAY;SAC5B,CAAA;IACH,CAAC;IAEO,KAAK,CAAC,iBAAiB;QAC7B,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;QAEhC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,wBAAwB,EAAE,CAAA;QACpD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAA;QAC9B,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC,OAAO,CAAC,IAAI,CACf,sBAAsB,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,sCAAsC,UAAU,CAAC,OAAO,kBACxG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YACpC,IAAI,CACL,CAAA;YACD,IAAI,CAAC,IAAI,CAAC,sBAAsB,EAAE,UAAU,CAAC,CAAA;YAC7C,OAAO;gBACL,iBAAiB,EAAE,KAAK;gBACxB,WAAW,EAAE,UAAU;gBACvB,UAAU;aACX,CAAA;QACH,CAAC;QAED,IAAI,CAAC,qBAAqB,GAAG,MAAM,CAAA;QACnC,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAA;QAElC,MAAM,iBAAiB,GAAG,IAAI,wCAAiB,EAAE,CAAA;QACjD,8BAA8B;QAC9B,OAAO;YACL,iBAAiB,EAAE,IAAI;YACvB,WAAW,EAAE,UAAU;YACvB,UAAU;YACV,iBAAiB;YACjB,eAAe,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI;SACnF,CAAA;IACH,CAAC;IAES,iBAAiB,CAAC,UAAsB;QAChD,IAAI,CAAC,OAAO,CAAC,IAAI,CACf,iBAAiB,UAAU,CAAC,OAAO,UAAU,IAAA,8BAAO,EAAC,UAAU,CAAC,KAAK,CAAC;aACnE,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC;aACjB,IAAI,CAAC,IAAI,CAAC,GAAG,CACjB,CAAA;QACD,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAA;IAC3C,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,oBAAuC,IAAI,wCAAiB,EAAE;QAC3E,MAAM,qBAAqB,GAAG,IAAI,CAAC,qBAAqB,CAAA;QACxD,IAAI,qBAAqB,IAAI,IAAI,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;YACpD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;YACzB,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC9B,CAAC;QAED,IAAI,IAAI,CAAC,eAAe,IAAI,IAAI,EAAE,CAAC;YACjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAA;YAC7D,OAAO,IAAI,CAAC,eAAe,CAAA;QAC7B,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,IAAI,CACf,2BAA2B,IAAA,8BAAO,EAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC;aACjE,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC;aACjB,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAA;QACD,MAAM,YAAY,GAAG,CAAC,CAAQ,EAAS,EAAE;YACvC,2FAA2F;YAC3F,IAAI,CAAC,CAAC,CAAC,YAAY,wCAAiB,CAAC,EAAE,CAAC;gBACtC,IAAI,CAAC;oBACH,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAA;gBACvB,CAAC;gBAAC,OAAO,WAAgB,EAAE,CAAC;oBAC1B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,gCAAgC,WAAW,CAAC,KAAK,IAAI,WAAW,EAAE,CAAC,CAAA;gBACvF,CAAC;YACH,CAAC;YAED,OAAO,CAAC,CAAA;QACV,CAAC,CAAA;QAED,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,gBAAgB,CAAC;YAC3C,qBAAqB;YACrB,cAAc,EAAE,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,QAAQ,CAAC;YAC1E,iBAAiB;YACjB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;YAC7C,2BAA2B,EAAE,IAAI,CAAC,2BAA2B;SAC9D,CAAC;aACC,KAAK,CAAC,CAAC,CAAM,EAAE,EAAE;YAChB,MAAM,YAAY,CAAC,CAAC,CAAC,CAAA;QACvB,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,IAAI,CAAC,eAAe,GAAG,IAAI,CAAA;QAC7B,CAAC,CAAC,CAAA;QAEJ,OAAO,IAAI,CAAC,eAAe,CAAA;IAC7B,CAAC;IAES,aAAa,CAAC,CAAQ;QAC9B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;IAClD,CAAC;IAES,wBAAwB,CAAC,KAA4B;QAC7D,IAAI,CAAC,IAAI,CAAC,yBAAiB,EAAE,KAAK,CAAC,CAAA;IACrC,CAAC;IAiBO,KAAK,CAAC,gBAAgB;QAC5B,IAAI,IAAI,CAAC,oBAAoB,IAAI,IAAI,EAAE,CAAC;YACtC,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAA;QAC1D,CAAC;QACD,OAAO,IAAA,cAAI,EAAC,MAAM,IAAA,mBAAQ,EAAC,IAAI,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAAA;IACjE,CAAC;IAEO,qBAAqB,CAAC,QAAuB;QACnD,MAAM,wBAAwB,GAAG,QAAQ,CAAC,wBAAwB,CAAA;QAClE,IAAI,wBAAwB,IAAI,IAAI,EAAE,CAAC;YACrC,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAA;YAC1C,OAAO,cAAc,IAAI,IAAI;gBAC3B,CAAC,CAAC,wBAAwB;gBAC1B,CAAC,CAAC;oBACE,GAAG,wBAAwB;oBAC3B,GAAG,cAAc;iBAClB,CAAA;QACP,CAAC;QACD,OAAO,IAAI,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;IACpD,CAAC;IAEO,KAAK,CAAC,wBAAwB;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,YAAY,CAAC,CAAA;QAC3D,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YACxC,IAAI,2BAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;gBACnB,OAAO,EAAE,CAAA;YACX,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,yDAAyD,EAAE,EAAE,CAAC,CAAA;YAClF,CAAC;QACH,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACxB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,wDAAwD,CAAC,EAAE,CAAC,CAAA;YAChF,CAAC;QACH,CAAC;QAED,MAAM,EAAE,GAAG,2BAAI,CAAC,EAAE,CAAC,IAAA,oBAAW,EAAC,IAAI,CAAC,EAAE,2BAAI,CAAC,GAAG,CAAC,CAAA;QAC/C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,kCAAkC,EAAE,EAAE,CAAC,CAAA;QACzD,IAAI,CAAC;YACH,MAAM,IAAA,qBAAU,EAAC,IAAI,EAAE,EAAE,CAAC,CAAA;QAC5B,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,uCAAuC,CAAC,EAAE,CAAC,CAAA;QAC/D,CAAC;QACD,OAAO,EAAE,CAAA;IACX,CAAC;IAED,gBAAgB;IAChB,IAAI,iBAAiB;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAA;QACnC,oEAAoE;QACpE,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACpB,OAAO,IAAI,CAAA;QACb,CAAC;QAED,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9C,MAAM,CAAC,GAAG,UAAU,CAAC,WAAW,EAAE,CAAA;YAClC,IAAI,CAAC,KAAK,eAAe,IAAI,CAAC,KAAK,eAAe,EAAE,CAAC;gBACnD,OAAO,KAAK,CAAA;YACd,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAQO,KAAK,CAAC,yBAAyB;QACrC,IAAI,MAAM,GAAG,IAAI,CAAC,sBAAsB,CAAA;QACxC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,mBAAmB,CAAA;YACnE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAA;YAC3B,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;gBACpB,MAAM,CAAC,KAAK,CAAC,+GAA+G,CAAC,CAAA;YAC/H,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YAC5E,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;gBACzB,MAAM,CAAC,KAAK,CAAC,sBAAsB,QAAQ,EAAE,CAAC,CAAA;YAChD,CAAC;YAED,MAAM,GAAG,IAAI,+CAAsB,CAAC,QAAQ,CAAC,CAAA;YAC7C,IAAI,CAAC,sBAAsB,GAAG,MAAM,CAAA;QACtC,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAES,KAAK,CAAC,eAAe,CAAC,WAAiC;QAC/D,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAA;QACrC,MAAM,eAAe,GAAoB;YACvC,OAAO,EAAE,WAAW,CAAC,qBAAqB,CAAC,cAAc;YACzD,iBAAiB,EAAE,WAAW,CAAC,qBAAqB,CAAC,iBAAiB;YACtE,IAAI,EAAG,QAAQ,CAAC,IAAY,CAAC,IAAI;YACjC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM;SAC7B,CAAA;QAED,IAAI,IAAI,CAAC,aAAa,CAAC,yBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9C,eAAe,CAAC,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAiB,EAAE,EAAE,CAAC,CAAA;QACrE,CAAC;QAED,MAAM,UAAU,GAAG,WAAW,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,IAAI,CAAA;QAC/E,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAA;QAClC,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAA;QAExC,SAAS,sBAAsB;YAC7B,0CAA0C;YAC1C,MAAM,OAAO,GAAG,kBAAkB,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YACrE,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC;gBACtD,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;YAC/B,CAAC;iBAAM,CAAC;gBACN,kCAAkC;gBAClC,OAAO,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAA;YACtC,CAAC;QACH,CAAC;QAED,MAAM,sBAAsB,GAAG,MAAM,IAAI,CAAC,yBAAyB,EAAE,CAAA;QACrE,MAAM,QAAQ,GAAG,sBAAsB,CAAC,wBAAwB,CAAA;QAChE,MAAM,IAAA,gBAAK,EAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC1C,MAAM,cAAc,GAAG,sBAAsB,EAAE,CAAA;QAC/C,IAAI,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;QACpD,MAAM,WAAW,GAAG,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC,CAAA;QAEpI,MAAM,IAAI,GAAG,KAAK,EAAE,WAAoB,EAAE,EAAE;YAC1C,MAAM,sBAAsB,CAAC,iBAAiB,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,CAAC,CAAA;YAC1H,MAAM,WAAW,CAAC,IAAK,CAAC;gBACtB,GAAG,UAAU;gBACb,cAAc,EAAE,UAAU;aAC3B,CAAC,CAAA;YACF,OAAO,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;QACvE,CAAC,CAAA;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAA;QACxB,MAAM,gBAAgB,GAAG,MAAM,sBAAsB,CAAC,sBAAsB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAA;QACnH,IAAI,gBAAgB,IAAI,IAAI,EAAE,CAAC;YAC7B,UAAU,GAAG,gBAAgB,CAAA;YAC7B,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,CAAA;QAC1B,CAAC;QAED,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE;YACjC,MAAM,sBAAsB,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;gBAC9C,SAAS;YACX,CAAC,CAAC,CAAA;YACF,OAAO,MAAM,IAAA,iBAAM,EAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;gBACzC,SAAS;YACX,CAAC,CAAC,CAAA;QACJ,CAAC,CAAA;QAED,MAAM,cAAc,GAAG,MAAM,IAAA,6CAAoB,EAAC,QAAQ,cAAc,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAA;QAC1F,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,IAAI,CAAC,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,CAAC,CAAA;YACrF,MAAM,IAAA,4BAAK,EACT,GAAG,EAAE,CAAC,IAAA,iBAAM,EAAC,cAAc,EAAE,UAAU,CAAC,EACxC,EAAE,EACF,GAAG,EACH,CAAC,EACD,CAAC,EACD,KAAK,CAAC,EAAE,CAAC,KAAK,YAAY,KAAK,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CACjE,CAAA;QACH,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,MAAM,eAAe,EAAE,CAAA;YAEvB,IAAI,CAAC,YAAY,wCAAiB,EAAE,CAAC;gBACnC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;gBACrB,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAA;YAC3C,CAAC;YACD,MAAM,CAAC,CAAA;QACT,CAAC;QAED,GAAG,CAAC,IAAI,CAAC,eAAe,OAAO,2BAA2B,UAAU,EAAE,CAAC,CAAA;QACvE,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IACS,KAAK,CAAC,6BAA6B,CAC3C,QAAgC,EAChC,qBAA4C,EAC5C,aAAqB,EACrB,QAAuB,EACvB,oBAA4B;QAE5B,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,gBAAgB,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,yBAAyB,EAAE,CAAC;gBACtF,OAAO,IAAI,CAAA;YACb,CAAC;YACD,MAAM,gBAAgB,GAAG,IAAA,oBAAa,EAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,qBAAqB,CAAC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YAChI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,8BAA8B,gBAAgB,CAAC,CAAC,CAAC,WAAW,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;YAErG,MAAM,gBAAgB,GAAG,KAAK,EAAE,GAAQ,EAAqB,EAAE;gBAC7D,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,GAAG,EAAE;oBACzD,OAAO,EAAE,qBAAqB,CAAC,cAAc;oBAC7C,iBAAiB,EAAE,qBAAqB,CAAC,iBAAiB;iBAC3D,CAAC,CAAA;gBAEF,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACtC,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,IAAI,YAAY,CAAC,CAAA;gBACpD,CAAC;gBAED,IAAI,CAAC;oBACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAU,EAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;gBAChD,CAAC;gBAAC,OAAO,CAAM,EAAE,CAAC;oBAChB,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,CAAC,IAAI,aAAa,CAAC,EAAE,CAAC,CAAA;gBACrE,CAAC;YACH,CAAC,CAAA;YAED,MAAM,eAAe,GAAkC;gBACrD,MAAM,EAAE,QAAQ,CAAC,GAAG;gBACpB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAuB,CAAC,QAAQ,EAAE,oBAAoB,CAAC;gBAC/E,MAAM,EAAE,IAAI,CAAC,OAAO;gBACpB,OAAO,EAAE,aAAa;gBACtB,yBAAyB,EAAE,QAAQ,CAAC,yBAAyB;gBAC7D,cAAc,EAAE,qBAAqB,CAAC,cAAc;gBACpD,iBAAiB,EAAE,qBAAqB,CAAC,iBAAiB;aAC3D,CAAA;YAED,IAAI,IAAI,CAAC,aAAa,CAAC,yBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC9C,eAAe,CAAC,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAiB,EAAE,EAAE,CAAC,CAAA;YACrE,CAAC;YAED,MAAM,gBAAgB,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;YAC1F,MAAM,IAAI,6DAA6B,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAA;YAC7I,OAAO,KAAK,CAAA;QACd,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,8DAA8D,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC,CAAA;YAChG,IAAI,IAAI,CAAC,gBAAgB,IAAI,IAAI,EAAE,CAAC;gBAClC,YAAY;gBACZ,MAAM,CAAC,CAAA;YACT,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;CACF;AAjwBD,gCAiwBC;AAUD,SAAS,uBAAuB,CAAC,OAAe;IAC9C,MAAM,0BAA0B,GAAG,IAAA,mBAA4B,EAAC,OAAO,CAAC,CAAA;IACxE,OAAO,0BAA0B,IAAI,IAAI,IAAI,0BAA0B,CAAC,MAAM,GAAG,CAAC,CAAA;AACpF,CAAC;AAED,eAAe;AACf,MAAa,UAAU;IACrB,6DAA6D;IAC7D,IAAI,CAAC,OAAa;QAChB,SAAS;IACX,CAAC;IAED,6DAA6D;IAC7D,IAAI,CAAC,OAAa;QAChB,SAAS;IACX,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,OAAa;QACjB,SAAS;IACX,CAAC;CACF;AAfD,gCAeC","sourcesContent":["import {\n  AllPublishOptions,\n  asArray,\n  CancellationToken,\n  newError,\n  PublishConfiguration,\n  UpdateInfo,\n  UUID,\n  DownloadOptions,\n  CancellationError,\n  ProgressInfo,\n  BlockMap,\n  retry,\n} from \"builder-util-runtime\"\nimport { randomBytes } from \"crypto\"\nimport { release } from \"os\"\nimport { EventEmitter } from \"events\"\nimport { mkdir, outputFile, readFile, rename, unlink } from \"fs-extra\"\nimport { OutgoingHttpHeaders } from \"http\"\nimport { load } from \"js-yaml\"\nimport { Lazy } from \"lazy-val\"\nimport * as path from \"path\"\nimport { eq as isVersionsEqual, gt as isVersionGreaterThan, lt as isVersionLessThan, parse as parseVersion, prerelease as getVersionPreleaseComponents, SemVer } from \"semver\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { createTempUpdateFile, DownloadedUpdateHelper } from \"./DownloadedUpdateHelper\"\nimport { ElectronAppAdapter } from \"./ElectronAppAdapter\"\nimport { ElectronHttpExecutor, getNetSession, LoginCallback } from \"./electronHttpExecutor\"\nimport { GenericProvider } from \"./providers/GenericProvider\"\nimport { createClient, isUrlProbablySupportMultiRangeRequests } from \"./providerFactory\"\nimport { Provider, ProviderPlatform } from \"./providers/Provider\"\nimport type { TypedEmitter } from \"tiny-typed-emitter\"\nimport Session = Electron.Session\nimport type { AuthInfo } from \"electron\"\nimport { gunzipSync } from \"zlib\"\nimport { blockmapFiles } from \"./util\"\nimport { DifferentialDownloaderOptions } from \"./differentialDownloader/DifferentialDownloader\"\nimport { GenericDifferentialDownloader } from \"./differentialDownloader/GenericDifferentialDownloader\"\nimport { DOWNLOAD_PROGRESS, Logger, ResolvedUpdateFileInfo, UPDATE_DOWNLOADED, UpdateCheckResult, UpdateDownloadedEvent, UpdaterSignal } from \"./types\"\nimport { VerifyUpdateSupport } from \"./main\"\n\nexport type AppUpdaterEvents = {\n  error: (error: Error, message?: string) => void\n  login: (info: AuthInfo, callback: LoginCallback) => void\n  \"checking-for-update\": () => void\n  \"update-not-available\": (info: UpdateInfo) => void\n  \"update-available\": (info: UpdateInfo) => void\n  \"update-downloaded\": (event: UpdateDownloadedEvent) => void\n  \"download-progress\": (info: ProgressInfo) => void\n  \"update-cancelled\": (info: UpdateInfo) => void\n  \"appimage-filename-updated\": (path: string) => void\n}\n\nexport abstract class AppUpdater extends (EventEmitter as new () => TypedEmitter<AppUpdaterEvents>) {\n  /**\n   * Whether to automatically download an update when it is found.\n   * @default true\n   */\n  autoDownload = true\n\n  /**\n   * Whether to automatically install a downloaded update on app quit (if `quitAndInstall` was not called before).\n   * @default true\n   */\n  autoInstallOnAppQuit = true\n\n  /**\n   * Whether to run the app after finish install when run the installer is NOT in silent mode.\n   * @default true\n   */\n  autoRunAppAfterInstall = true\n\n  /**\n   * *GitHub provider only.* Whether to allow update to pre-release versions. Defaults to `true` if application version contains prerelease components (e.g. `0.12.1-alpha.1`, here `alpha` is a prerelease component), otherwise `false`.\n   *\n   * If `true`, downgrade will be allowed (`allowDowngrade` will be set to `true`).\n   */\n  allowPrerelease = false\n\n  /**\n   * *GitHub provider only.* Get all release notes (from current version to latest), not just the latest.\n   * @default false\n   */\n  fullChangelog = false\n\n  /**\n   * Whether to allow version downgrade (when a user from the beta channel wants to go back to the stable channel).\n   *\n   * Taken in account only if channel differs (pre-release version component in terms of semantic versioning).\n   *\n   * @default false\n   */\n  allowDowngrade = false\n\n  /**\n   * Web installer files might not have signature verification, this switch prevents to load them unless it is needed.\n   *\n   * Currently false to prevent breaking the current API, but it should be changed to default true at some point that\n   * breaking changes are allowed.\n   *\n   * @default false\n   */\n  disableWebInstaller = false\n\n  /**\n   * *NSIS only* Disable differential downloads and always perform full download of installer.\n   *\n   * @default false\n   */\n  disableDifferentialDownload = false\n\n  /**\n   * Allows developer to force the updater to work in \"dev\" mode, looking for \"dev-app-update.yml\" instead of \"app-update.yml\"\n   * Dev: `path.join(this.app.getAppPath(), \"dev-app-update.yml\")`\n   * Prod: `path.join(process.resourcesPath!, \"app-update.yml\")`\n   *\n   * @default false\n   */\n  forceDevUpdateConfig = false\n\n  /**\n   * The current application version.\n   */\n  readonly currentVersion: SemVer\n\n  private _channel: string | null = null\n\n  protected downloadedUpdateHelper: DownloadedUpdateHelper | null = null\n\n  /**\n   * Get the update channel. Doesn't return `channel` from the update configuration, only if was previously set.\n   */\n  get channel(): string | null {\n    return this._channel\n  }\n\n  /**\n   * Set the update channel. Overrides `channel` in the update configuration.\n   *\n   * `allowDowngrade` will be automatically set to `true`. If this behavior is not suitable for you, simple set `allowDowngrade` explicitly after.\n   */\n  set channel(value: string | null) {\n    if (this._channel != null) {\n      // noinspection SuspiciousTypeOfGuard\n      if (typeof value !== \"string\") {\n        throw newError(`Channel must be a string, but got: ${value}`, \"ERR_UPDATER_INVALID_CHANNEL\")\n      } else if (value.length === 0) {\n        throw newError(`Channel must be not an empty string`, \"ERR_UPDATER_INVALID_CHANNEL\")\n      }\n    }\n\n    this._channel = value\n    this.allowDowngrade = true\n  }\n\n  /**\n   *  The request headers.\n   */\n  requestHeaders: OutgoingHttpHeaders | null = null\n\n  /**\n   *  Shortcut for explicitly adding auth tokens to request headers\n   */\n  addAuthHeader(token: string) {\n    this.requestHeaders = Object.assign({}, this.requestHeaders, {\n      authorization: token,\n    })\n  }\n\n  protected _logger: Logger = console\n\n  // noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n  get netSession(): Session {\n    return getNetSession()\n  }\n\n  /**\n   * The logger. You can pass [electron-log](https://github.com/megahertz/electron-log), [winston](https://github.com/winstonjs/winston) or another logger with the following interface: `{ info(), warn(), error() }`.\n   * Set it to `null` if you would like to disable a logging feature.\n   */\n  get logger(): Logger | null {\n    return this._logger\n  }\n\n  set logger(value: Logger | null) {\n    this._logger = value == null ? new NoOpLogger() : value\n  }\n\n  // noinspection JSUnusedGlobalSymbols\n  /**\n   * For type safety you can use signals, e.g. `autoUpdater.signals.updateDownloaded(() => {})` instead of `autoUpdater.on('update-available', () => {})`\n   */\n  readonly signals = new UpdaterSignal(this)\n\n  private _appUpdateConfigPath: string | null = null\n\n  // noinspection JSUnusedGlobalSymbols\n  /**\n   * test only\n   * @private\n   */\n  set updateConfigPath(value: string | null) {\n    this.clientPromise = null\n    this._appUpdateConfigPath = value\n    this.configOnDisk = new Lazy<any>(() => this.loadUpdateConfig())\n  }\n\n  protected _isUpdateSupported: VerifyUpdateSupport = (updateInfo: UpdateInfo): boolean | Promise<boolean> => this.checkIfUpdateSupported(updateInfo)\n\n  /**\n   * Allows developer to override default logic for determining if an update is supported.\n   * The default logic compares the `UpdateInfo` minimum system version against the `os.release()` with `semver` package\n   */\n  get isUpdateSupported(): VerifyUpdateSupport {\n    return this._isUpdateSupported\n  }\n\n  set isUpdateSupported(value: VerifyUpdateSupport) {\n    if (value) {\n      this._isUpdateSupported = value\n    }\n  }\n\n  private clientPromise: Promise<Provider<any>> | null = null\n\n  protected readonly stagingUserIdPromise = new Lazy<string>(() => this.getOrCreateStagingUserId())\n\n  // public, allow to read old config for anyone\n  /** @internal */\n  configOnDisk = new Lazy<any>(() => this.loadUpdateConfig())\n\n  private checkForUpdatesPromise: Promise<UpdateCheckResult> | null = null\n  private downloadPromise: Promise<Array<string>> | null = null\n\n  protected readonly app: AppAdapter\n\n  protected updateInfoAndProvider: UpdateInfoAndProvider | null = null\n\n  /** @internal */\n  readonly httpExecutor: ElectronHttpExecutor\n\n  protected constructor(options: AllPublishOptions | null | undefined, app?: AppAdapter) {\n    super()\n\n    this.on(\"error\", (error: Error) => {\n      this._logger.error(`Error: ${error.stack || error.message}`)\n    })\n\n    if (app == null) {\n      this.app = new ElectronAppAdapter()\n      this.httpExecutor = new ElectronHttpExecutor((authInfo, callback) => this.emit(\"login\", authInfo, callback))\n    } else {\n      this.app = app\n      this.httpExecutor = null as any\n    }\n\n    const currentVersionString = this.app.version\n    const currentVersion = parseVersion(currentVersionString)\n    if (currentVersion == null) {\n      throw newError(`App version is not a valid semver version: \"${currentVersionString}\"`, \"ERR_UPDATER_INVALID_VERSION\")\n    }\n    this.currentVersion = currentVersion\n    this.allowPrerelease = hasPrereleaseComponents(currentVersion)\n\n    if (options != null) {\n      this.setFeedURL(options)\n\n      if (typeof options !== \"string\" && options.requestHeaders) {\n        this.requestHeaders = options.requestHeaders\n      }\n    }\n  }\n\n  //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n  getFeedURL(): string | null | undefined {\n    return \"Deprecated. Do not use it.\"\n  }\n\n  /**\n   * Configure update provider. If value is `string`, [GenericServerOptions](./publish.md#genericserveroptions) will be set with value as `url`.\n   * @param options If you want to override configuration in the `app-update.yml`.\n   */\n  setFeedURL(options: PublishConfiguration | AllPublishOptions | string) {\n    const runtimeOptions = this.createProviderRuntimeOptions()\n    // https://github.com/electron-userland/electron-builder/issues/1105\n    let provider: Provider<any>\n    if (typeof options === \"string\") {\n      provider = new GenericProvider({ provider: \"generic\", url: options }, this, {\n        ...runtimeOptions,\n        isUseMultipleRangeRequest: isUrlProbablySupportMultiRangeRequests(options),\n      })\n    } else {\n      provider = createClient(options, this, runtimeOptions)\n    }\n    this.clientPromise = Promise.resolve(provider)\n  }\n\n  /**\n   * Asks the server whether there is an update.\n   * @returns null if the updater is disabled, otherwise info about the latest version\n   */\n  checkForUpdates(): Promise<UpdateCheckResult | null> {\n    if (!this.isUpdaterActive()) {\n      return Promise.resolve(null)\n    }\n\n    let checkForUpdatesPromise = this.checkForUpdatesPromise\n    if (checkForUpdatesPromise != null) {\n      this._logger.info(\"Checking for update (already in progress)\")\n      return checkForUpdatesPromise\n    }\n\n    const nullizePromise = () => (this.checkForUpdatesPromise = null)\n\n    this._logger.info(\"Checking for update\")\n    checkForUpdatesPromise = this.doCheckForUpdates()\n      .then(it => {\n        nullizePromise()\n        return it\n      })\n      .catch((e: any) => {\n        nullizePromise()\n        this.emit(\"error\", e, `Cannot check for updates: ${(e.stack || e).toString()}`)\n        throw e\n      })\n\n    this.checkForUpdatesPromise = checkForUpdatesPromise\n    return checkForUpdatesPromise\n  }\n\n  public isUpdaterActive(): boolean {\n    const isEnabled = this.app.isPackaged || this.forceDevUpdateConfig\n    if (!isEnabled) {\n      this._logger.info(\"Skip checkForUpdates because application is not packed and dev update config is not forced\")\n      return false\n    }\n    return true\n  }\n\n  // noinspection JSUnusedGlobalSymbols\n  checkForUpdatesAndNotify(downloadNotification?: DownloadNotification): Promise<UpdateCheckResult | null> {\n    return this.checkForUpdates().then(it => {\n      if (!it?.downloadPromise) {\n        if (this._logger.debug != null) {\n          this._logger.debug(\"checkForUpdatesAndNotify called, downloadPromise is null\")\n        }\n        return it\n      }\n\n      void it.downloadPromise.then(() => {\n        const notificationContent = AppUpdater.formatDownloadNotification(it.updateInfo.version, this.app.name, downloadNotification)\n        new (require(\"electron\").Notification)(notificationContent).show()\n      })\n\n      return it\n    })\n  }\n\n  private static formatDownloadNotification(version: string, appName: string, downloadNotification?: DownloadNotification): DownloadNotification {\n    if (downloadNotification == null) {\n      downloadNotification = {\n        title: \"A new update is ready to install\",\n        body: `{appName} version {version} has been downloaded and will be automatically installed on exit`,\n      }\n    }\n    downloadNotification = {\n      title: downloadNotification.title.replace(\"{appName}\", appName).replace(\"{version}\", version),\n      body: downloadNotification.body.replace(\"{appName}\", appName).replace(\"{version}\", version),\n    }\n    return downloadNotification\n  }\n\n  private async isStagingMatch(updateInfo: UpdateInfo): Promise<boolean> {\n    const rawStagingPercentage = updateInfo.stagingPercentage\n    let stagingPercentage = rawStagingPercentage\n    if (stagingPercentage == null) {\n      return true\n    }\n\n    stagingPercentage = parseInt(stagingPercentage as any, 10)\n    if (isNaN(stagingPercentage)) {\n      this._logger.warn(`Staging percentage is NaN: ${rawStagingPercentage}`)\n      return true\n    }\n\n    // convert from user 0-100 to internal 0-1\n    stagingPercentage = stagingPercentage / 100\n\n    const stagingUserId = await this.stagingUserIdPromise.value\n    const val = UUID.parse(stagingUserId).readUInt32BE(12)\n    const percentage = val / 0xffffffff\n    this._logger.info(`Staging percentage: ${stagingPercentage}, percentage: ${percentage}, user id: ${stagingUserId}`)\n    return percentage < stagingPercentage\n  }\n\n  private computeFinalHeaders(headers: OutgoingHttpHeaders) {\n    if (this.requestHeaders != null) {\n      Object.assign(headers, this.requestHeaders)\n    }\n    return headers\n  }\n\n  private async isUpdateAvailable(updateInfo: UpdateInfo): Promise<boolean> {\n    const latestVersion = parseVersion(updateInfo.version)\n    if (latestVersion == null) {\n      throw newError(\n        `This file could not be downloaded, or the latest version (from update server) does not have a valid semver version: \"${updateInfo.version}\"`,\n        \"ERR_UPDATER_INVALID_VERSION\"\n      )\n    }\n\n    const currentVersion = this.currentVersion\n    if (isVersionsEqual(latestVersion, currentVersion)) {\n      return false\n    }\n\n    if (!(await Promise.resolve(this.isUpdateSupported(updateInfo)))) {\n      return false\n    }\n\n    const isStagingMatch = await this.isStagingMatch(updateInfo)\n    if (!isStagingMatch) {\n      return false\n    }\n\n    // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405033227\n    // https://github.com/electron-userland/electron-builder/pull/3111#issuecomment-405030797\n    const isLatestVersionNewer = isVersionGreaterThan(latestVersion, currentVersion)\n    const isLatestVersionOlder = isVersionLessThan(latestVersion, currentVersion)\n\n    if (isLatestVersionNewer) {\n      return true\n    }\n    return this.allowDowngrade && isLatestVersionOlder\n  }\n\n  private checkIfUpdateSupported(updateInfo: UpdateInfo) {\n    const minimumSystemVersion = updateInfo?.minimumSystemVersion\n    const currentOSVersion = release()\n    if (minimumSystemVersion) {\n      try {\n        if (isVersionLessThan(currentOSVersion, minimumSystemVersion)) {\n          this._logger.info(`Current OS version ${currentOSVersion} is less than the minimum OS version required ${minimumSystemVersion} for version ${currentOSVersion}`)\n          return false\n        }\n      } catch (e: any) {\n        this._logger.warn(`Failed to compare current OS version(${currentOSVersion}) with minimum OS version(${minimumSystemVersion}): ${(e.message || e).toString()}`)\n      }\n    }\n    return true\n  }\n\n  protected async getUpdateInfoAndProvider(): Promise<UpdateInfoAndProvider> {\n    await this.app.whenReady()\n\n    if (this.clientPromise == null) {\n      this.clientPromise = this.configOnDisk.value.then(it => createClient(it, this, this.createProviderRuntimeOptions()))\n    }\n\n    const client = await this.clientPromise\n    const stagingUserId = await this.stagingUserIdPromise.value\n    client.setRequestHeaders(this.computeFinalHeaders({ \"x-user-staging-id\": stagingUserId }))\n    return {\n      info: await client.getLatestVersion(),\n      provider: client,\n    }\n  }\n\n  private createProviderRuntimeOptions() {\n    return {\n      isUseMultipleRangeRequest: true,\n      platform: this._testOnlyOptions == null ? (process.platform as ProviderPlatform) : this._testOnlyOptions.platform,\n      executor: this.httpExecutor,\n    }\n  }\n\n  private async doCheckForUpdates(): Promise<UpdateCheckResult> {\n    this.emit(\"checking-for-update\")\n\n    const result = await this.getUpdateInfoAndProvider()\n    const updateInfo = result.info\n    if (!(await this.isUpdateAvailable(updateInfo))) {\n      this._logger.info(\n        `Update for version ${this.currentVersion.format()} is not available (latest version: ${updateInfo.version}, downgrade is ${\n          this.allowDowngrade ? \"allowed\" : \"disallowed\"\n        }).`\n      )\n      this.emit(\"update-not-available\", updateInfo)\n      return {\n        isUpdateAvailable: false,\n        versionInfo: updateInfo,\n        updateInfo,\n      }\n    }\n\n    this.updateInfoAndProvider = result\n    this.onUpdateAvailable(updateInfo)\n\n    const cancellationToken = new CancellationToken()\n    //noinspection ES6MissingAwait\n    return {\n      isUpdateAvailable: true,\n      versionInfo: updateInfo,\n      updateInfo,\n      cancellationToken,\n      downloadPromise: this.autoDownload ? this.downloadUpdate(cancellationToken) : null,\n    }\n  }\n\n  protected onUpdateAvailable(updateInfo: UpdateInfo): void {\n    this._logger.info(\n      `Found version ${updateInfo.version} (url: ${asArray(updateInfo.files)\n        .map(it => it.url)\n        .join(\", \")})`\n    )\n    this.emit(\"update-available\", updateInfo)\n  }\n\n  /**\n   * Start downloading update manually. You can use this method if `autoDownload` option is set to `false`.\n   * @returns {Promise<Array<string>>} Paths to downloaded files.\n   */\n  downloadUpdate(cancellationToken: CancellationToken = new CancellationToken()): Promise<Array<string>> {\n    const updateInfoAndProvider = this.updateInfoAndProvider\n    if (updateInfoAndProvider == null) {\n      const error = new Error(\"Please check update first\")\n      this.dispatchError(error)\n      return Promise.reject(error)\n    }\n\n    if (this.downloadPromise != null) {\n      this._logger.info(\"Downloading update (already in progress)\")\n      return this.downloadPromise\n    }\n\n    this._logger.info(\n      `Downloading update from ${asArray(updateInfoAndProvider.info.files)\n        .map(it => it.url)\n        .join(\", \")}`\n    )\n    const errorHandler = (e: Error): Error => {\n      // https://github.com/electron-userland/electron-builder/issues/1150#issuecomment-436891159\n      if (!(e instanceof CancellationError)) {\n        try {\n          this.dispatchError(e)\n        } catch (nestedError: any) {\n          this._logger.warn(`Cannot dispatch error event: ${nestedError.stack || nestedError}`)\n        }\n      }\n\n      return e\n    }\n\n    this.downloadPromise = this.doDownloadUpdate({\n      updateInfoAndProvider,\n      requestHeaders: this.computeRequestHeaders(updateInfoAndProvider.provider),\n      cancellationToken,\n      disableWebInstaller: this.disableWebInstaller,\n      disableDifferentialDownload: this.disableDifferentialDownload,\n    })\n      .catch((e: any) => {\n        throw errorHandler(e)\n      })\n      .finally(() => {\n        this.downloadPromise = null\n      })\n\n    return this.downloadPromise\n  }\n\n  protected dispatchError(e: Error): void {\n    this.emit(\"error\", e, (e.stack || e).toString())\n  }\n\n  protected dispatchUpdateDownloaded(event: UpdateDownloadedEvent): void {\n    this.emit(UPDATE_DOWNLOADED, event)\n  }\n\n  protected abstract doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>>\n\n  /**\n   * Restarts the app and installs the update after it has been downloaded.\n   * It should only be called after `update-downloaded` has been emitted.\n   *\n   * **Note:** `autoUpdater.quitAndInstall()` will close all application windows first and only emit `before-quit` event on `app` after that.\n   * This is different from the normal quit event sequence.\n   *\n   * @param isSilent *windows-only* Runs the installer in silent mode. Defaults to `false`.\n   * @param isForceRunAfter Run the app after finish even on silent install. Not applicable for macOS.\n   * Ignored if `isSilent` is set to `false`(In this case you can still set `autoRunAppAfterInstall` to `false` to prevent run the app after finish).\n   */\n  abstract quitAndInstall(isSilent?: boolean, isForceRunAfter?: boolean): void\n\n  private async loadUpdateConfig(): Promise<any> {\n    if (this._appUpdateConfigPath == null) {\n      this._appUpdateConfigPath = this.app.appUpdateConfigPath\n    }\n    return load(await readFile(this._appUpdateConfigPath, \"utf-8\"))\n  }\n\n  private computeRequestHeaders(provider: Provider<any>): OutgoingHttpHeaders {\n    const fileExtraDownloadHeaders = provider.fileExtraDownloadHeaders\n    if (fileExtraDownloadHeaders != null) {\n      const requestHeaders = this.requestHeaders\n      return requestHeaders == null\n        ? fileExtraDownloadHeaders\n        : {\n            ...fileExtraDownloadHeaders,\n            ...requestHeaders,\n          }\n    }\n    return this.computeFinalHeaders({ accept: \"*/*\" })\n  }\n\n  private async getOrCreateStagingUserId(): Promise<string> {\n    const file = path.join(this.app.userDataPath, \".updaterId\")\n    try {\n      const id = await readFile(file, \"utf-8\")\n      if (UUID.check(id)) {\n        return id\n      } else {\n        this._logger.warn(`Staging user id file exists, but content was invalid: ${id}`)\n      }\n    } catch (e: any) {\n      if (e.code !== \"ENOENT\") {\n        this._logger.warn(`Couldn't read staging user ID, creating a blank one: ${e}`)\n      }\n    }\n\n    const id = UUID.v5(randomBytes(4096), UUID.OID)\n    this._logger.info(`Generated new staging user ID: ${id}`)\n    try {\n      await outputFile(file, id)\n    } catch (e: any) {\n      this._logger.warn(`Couldn't write out staging user ID: ${e}`)\n    }\n    return id\n  }\n\n  /** @internal */\n  get isAddNoCacheQuery(): boolean {\n    const headers = this.requestHeaders\n    // https://github.com/electron-userland/electron-builder/issues/3021\n    if (headers == null) {\n      return true\n    }\n\n    for (const headerName of Object.keys(headers)) {\n      const s = headerName.toLowerCase()\n      if (s === \"authorization\" || s === \"private-token\") {\n        return false\n      }\n    }\n    return true\n  }\n\n  /**\n   * @private\n   * @internal\n   */\n  _testOnlyOptions: TestOnlyUpdaterOptions | null = null\n\n  private async getOrCreateDownloadHelper(): Promise<DownloadedUpdateHelper> {\n    let result = this.downloadedUpdateHelper\n    if (result == null) {\n      const dirName = (await this.configOnDisk.value).updaterCacheDirName\n      const logger = this._logger\n      if (dirName == null) {\n        logger.error(\"updaterCacheDirName is not specified in app-update.yml Was app build using at least electron-builder 20.34.0?\")\n      }\n      const cacheDir = path.join(this.app.baseCachePath, dirName || this.app.name)\n      if (logger.debug != null) {\n        logger.debug(`updater cache dir: ${cacheDir}`)\n      }\n\n      result = new DownloadedUpdateHelper(cacheDir)\n      this.downloadedUpdateHelper = result\n    }\n    return result\n  }\n\n  protected async executeDownload(taskOptions: DownloadExecutorTask): Promise<Array<string>> {\n    const fileInfo = taskOptions.fileInfo\n    const downloadOptions: DownloadOptions = {\n      headers: taskOptions.downloadUpdateOptions.requestHeaders,\n      cancellationToken: taskOptions.downloadUpdateOptions.cancellationToken,\n      sha2: (fileInfo.info as any).sha2,\n      sha512: fileInfo.info.sha512,\n    }\n\n    if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n      downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n    }\n\n    const updateInfo = taskOptions.downloadUpdateOptions.updateInfoAndProvider.info\n    const version = updateInfo.version\n    const packageInfo = fileInfo.packageInfo\n\n    function getCacheUpdateFileName(): string {\n      // NodeJS URL doesn't decode automatically\n      const urlPath = decodeURIComponent(taskOptions.fileInfo.url.pathname)\n      if (urlPath.endsWith(`.${taskOptions.fileExtension}`)) {\n        return path.basename(urlPath)\n      } else {\n        // url like /latest, generate name\n        return taskOptions.fileInfo.info.url\n      }\n    }\n\n    const downloadedUpdateHelper = await this.getOrCreateDownloadHelper()\n    const cacheDir = downloadedUpdateHelper.cacheDirForPendingUpdate\n    await mkdir(cacheDir, { recursive: true })\n    const updateFileName = getCacheUpdateFileName()\n    let updateFile = path.join(cacheDir, updateFileName)\n    const packageFile = packageInfo == null ? null : path.join(cacheDir, `package-${version}${path.extname(packageInfo.path) || \".7z\"}`)\n\n    const done = async (isSaveCache: boolean) => {\n      await downloadedUpdateHelper.setDownloadedFile(updateFile, packageFile, updateInfo, fileInfo, updateFileName, isSaveCache)\n      await taskOptions.done!({\n        ...updateInfo,\n        downloadedFile: updateFile,\n      })\n      return packageFile == null ? [updateFile] : [updateFile, packageFile]\n    }\n\n    const log = this._logger\n    const cachedUpdateFile = await downloadedUpdateHelper.validateDownloadedPath(updateFile, updateInfo, fileInfo, log)\n    if (cachedUpdateFile != null) {\n      updateFile = cachedUpdateFile\n      return await done(false)\n    }\n\n    const removeFileIfAny = async () => {\n      await downloadedUpdateHelper.clear().catch(() => {\n        // ignore\n      })\n      return await unlink(updateFile).catch(() => {\n        // ignore\n      })\n    }\n\n    const tempUpdateFile = await createTempUpdateFile(`temp-${updateFileName}`, cacheDir, log)\n    try {\n      await taskOptions.task(tempUpdateFile, downloadOptions, packageFile, removeFileIfAny)\n      await retry(\n        () => rename(tempUpdateFile, updateFile),\n        60,\n        500,\n        0,\n        0,\n        error => error instanceof Error && /^EBUSY:/.test(error.message)\n      )\n    } catch (e: any) {\n      await removeFileIfAny()\n\n      if (e instanceof CancellationError) {\n        log.info(\"cancelled\")\n        this.emit(\"update-cancelled\", updateInfo)\n      }\n      throw e\n    }\n\n    log.info(`New version ${version} has been downloaded to ${updateFile}`)\n    return await done(true)\n  }\n  protected async differentialDownloadInstaller(\n    fileInfo: ResolvedUpdateFileInfo,\n    downloadUpdateOptions: DownloadUpdateOptions,\n    installerPath: string,\n    provider: Provider<any>,\n    oldInstallerFileName: string\n  ): Promise<boolean> {\n    try {\n      if (this._testOnlyOptions != null && !this._testOnlyOptions.isUseDifferentialDownload) {\n        return true\n      }\n      const blockmapFileUrls = blockmapFiles(fileInfo.url, this.app.version, downloadUpdateOptions.updateInfoAndProvider.info.version)\n      this._logger.info(`Download block maps (old: \"${blockmapFileUrls[0]}\", new: ${blockmapFileUrls[1]})`)\n\n      const downloadBlockMap = async (url: URL): Promise<BlockMap> => {\n        const data = await this.httpExecutor.downloadToBuffer(url, {\n          headers: downloadUpdateOptions.requestHeaders,\n          cancellationToken: downloadUpdateOptions.cancellationToken,\n        })\n\n        if (data == null || data.length === 0) {\n          throw new Error(`Blockmap \"${url.href}\" is empty`)\n        }\n\n        try {\n          return JSON.parse(gunzipSync(data).toString())\n        } catch (e: any) {\n          throw new Error(`Cannot parse blockmap \"${url.href}\", error: ${e}`)\n        }\n      }\n\n      const downloadOptions: DifferentialDownloaderOptions = {\n        newUrl: fileInfo.url,\n        oldFile: path.join(this.downloadedUpdateHelper!.cacheDir, oldInstallerFileName),\n        logger: this._logger,\n        newFile: installerPath,\n        isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,\n        requestHeaders: downloadUpdateOptions.requestHeaders,\n        cancellationToken: downloadUpdateOptions.cancellationToken,\n      }\n\n      if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n        downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n      }\n\n      const blockMapDataList = await Promise.all(blockmapFileUrls.map(u => downloadBlockMap(u)))\n      await new GenericDifferentialDownloader(fileInfo.info, this.httpExecutor, downloadOptions).download(blockMapDataList[0], blockMapDataList[1])\n      return false\n    } catch (e: any) {\n      this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`)\n      if (this._testOnlyOptions != null) {\n        // test mode\n        throw e\n      }\n      return true\n    }\n  }\n}\n\nexport interface DownloadUpdateOptions {\n  readonly updateInfoAndProvider: UpdateInfoAndProvider\n  readonly requestHeaders: OutgoingHttpHeaders\n  readonly cancellationToken: CancellationToken\n  readonly disableWebInstaller?: boolean\n  readonly disableDifferentialDownload?: boolean\n}\n\nfunction hasPrereleaseComponents(version: SemVer) {\n  const versionPrereleaseComponent = getVersionPreleaseComponents(version)\n  return versionPrereleaseComponent != null && versionPrereleaseComponent.length > 0\n}\n\n/** @private */\nexport class NoOpLogger implements Logger {\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  info(message?: any) {\n    // ignore\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  warn(message?: any) {\n    // ignore\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  error(message?: any) {\n    // ignore\n  }\n}\n\nexport interface UpdateInfoAndProvider {\n  info: UpdateInfo\n  provider: Provider<any>\n}\n\nexport interface DownloadExecutorTask {\n  readonly fileExtension: string\n  readonly fileInfo: ResolvedUpdateFileInfo\n  readonly downloadUpdateOptions: DownloadUpdateOptions\n  readonly task: (destinationFile: string, downloadOptions: DownloadOptions, packageFile: string | null, removeTempDirIfAny: () => Promise<any>) => Promise<any>\n\n  readonly done?: (event: UpdateDownloadedEvent) => Promise<any>\n}\n\nexport interface DownloadNotification {\n  body: string\n  title: string\n}\n\n/** @private */\nexport interface TestOnlyUpdaterOptions {\n  platform: ProviderPlatform\n\n  isUseDifferentialDownload?: boolean\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseUpdater = void 0;
const child_process_1 = require("child_process");
const AppUpdater_1 = require("./AppUpdater");
class BaseUpdater extends AppUpdater_1.AppUpdater {
    constructor(options, app) {
        super(options, app);
        this.quitAndInstallCalled = false;
        this.quitHandlerAdded = false;
    }
    quitAndInstall(isSilent = false, isForceRunAfter = false) {
        this._logger.info(`Install on explicit quitAndInstall`);
        // If NOT in silent mode use `autoRunAppAfterInstall` to determine whether to force run the app
        const isInstalled = this.install(isSilent, isSilent ? isForceRunAfter : this.autoRunAppAfterInstall);
        if (isInstalled) {
            setImmediate(() => {
                // this event is normally emitted when calling quitAndInstall, this emulates that
                require("electron").autoUpdater.emit("before-quit-for-update");
                this.app.quit();
            });
        }
        else {
            this.quitAndInstallCalled = false;
        }
    }
    executeDownload(taskOptions) {
        return super.executeDownload({
            ...taskOptions,
            done: event => {
                this.dispatchUpdateDownloaded(event);
                this.addQuitHandler();
                return Promise.resolve();
            },
        });
    }
    get installerPath() {
        return this.downloadedUpdateHelper == null ? null : this.downloadedUpdateHelper.file;
    }
    // must be sync (because quit even handler is not async)
    install(isSilent = false, isForceRunAfter = false) {
        if (this.quitAndInstallCalled) {
            this._logger.warn("install call ignored: quitAndInstallCalled is set to true");
            return false;
        }
        const downloadedUpdateHelper = this.downloadedUpdateHelper;
        const installerPath = this.installerPath;
        const downloadedFileInfo = downloadedUpdateHelper == null ? null : downloadedUpdateHelper.downloadedFileInfo;
        if (installerPath == null || downloadedFileInfo == null) {
            this.dispatchError(new Error("No valid update available, can't quit and install"));
            return false;
        }
        // prevent calling several times
        this.quitAndInstallCalled = true;
        try {
            this._logger.info(`Install: isSilent: ${isSilent}, isForceRunAfter: ${isForceRunAfter}`);
            return this.doInstall({
                isSilent,
                isForceRunAfter,
                isAdminRightsRequired: downloadedFileInfo.isAdminRightsRequired,
            });
        }
        catch (e) {
            this.dispatchError(e);
            return false;
        }
    }
    addQuitHandler() {
        if (this.quitHandlerAdded || !this.autoInstallOnAppQuit) {
            return;
        }
        this.quitHandlerAdded = true;
        this.app.onQuit(exitCode => {
            if (this.quitAndInstallCalled) {
                this._logger.info("Update installer has already been triggered. Quitting application.");
                return;
            }
            if (!this.autoInstallOnAppQuit) {
                this._logger.info("Update will not be installed on quit because autoInstallOnAppQuit is set to false.");
                return;
            }
            if (exitCode !== 0) {
                this._logger.info(`Update will be not installed on quit because application is quitting with exit code ${exitCode}`);
                return;
            }
            this._logger.info("Auto install update on quit");
            this.install(true, false);
        });
    }
    wrapSudo() {
        const { name } = this.app;
        const installComment = `"${name} would like to update"`;
        const sudo = this.spawnSyncLog("which gksudo || which kdesudo || which pkexec || which beesu");
        const command = [sudo];
        if (/kdesudo/i.test(sudo)) {
            command.push("--comment", installComment);
            command.push("-c");
        }
        else if (/gksudo/i.test(sudo)) {
            command.push("--message", installComment);
        }
        else if (/pkexec/i.test(sudo)) {
            command.push("--disable-internal-agent");
        }
        return command.join(" ");
    }
    spawnSyncLog(cmd, args = [], env = {}) {
        this._logger.info(`Executing: ${cmd} with args: ${args}`);
        const response = (0, child_process_1.spawnSync)(cmd, args, {
            env: { ...process.env, ...env },
            encoding: "utf-8",
            shell: true,
        });
        const { error, status, stdout, stderr } = response;
        if (error != null) {
            this._logger.error(stderr);
            throw error;
        }
        else if (status != null && status !== 0) {
            this._logger.error(stderr);
            throw new Error(`Command ${cmd} exited with code ${status}`);
        }
        return stdout.trim();
    }
    /**
     * This handles both node 8 and node 10 way of emitting error when spawning a process
     *   - node 8: Throws the error
     *   - node 10: Emit the error(Need to listen with on)
     */
    // https://github.com/electron-userland/electron-builder/issues/1129
    // Node 8 sends errors: https://nodejs.org/dist/latest-v8.x/docs/api/errors.html#errors_common_system_errors
    async spawnLog(cmd, args = [], env = undefined, stdio = "ignore") {
        this._logger.info(`Executing: ${cmd} with args: ${args}`);
        return new Promise((resolve, reject) => {
            try {
                const params = { stdio, env, detached: true };
                const p = (0, child_process_1.spawn)(cmd, args, params);
                p.on("error", error => {
                    reject(error);
                });
                p.unref();
                if (p.pid !== undefined) {
                    resolve(true);
                }
            }
            catch (error) {
                reject(error);
            }
        });
    }
}
exports.BaseUpdater = BaseUpdater;
//# sourceMappingURL=BaseUpdater.js.map{"version":3,"file":"BaseUpdater.js","sourceRoot":"","sources":["../src/BaseUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllPublishOptions } from \"builder-util-runtime\"\nimport { spawn, SpawnOptions, spawnSync, StdioOptions } from \"child_process\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { AppUpdater, DownloadExecutorTask } from \"./AppUpdater\"\n\nexport abstract class BaseUpdater extends AppUpdater {\n  protected quitAndInstallCalled = false\n  private quitHandlerAdded = false\n\n  protected constructor(options?: AllPublishOptions | null, app?: AppAdapter) {\n    super(options, app)\n  }\n\n  quitAndInstall(isSilent = false, isForceRunAfter = false): void {\n    this._logger.info(`Install on explicit quitAndInstall`)\n    // If NOT in silent mode use `autoRunAppAfterInstall` to determine whether to force run the app\n    const isInstalled = this.install(isSilent, isSilent ? isForceRunAfter : this.autoRunAppAfterInstall)\n    if (isInstalled) {\n      setImmediate(() => {\n        // this event is normally emitted when calling quitAndInstall, this emulates that\n        require(\"electron\").autoUpdater.emit(\"before-quit-for-update\")\n        this.app.quit()\n      })\n    } else {\n      this.quitAndInstallCalled = false\n    }\n  }\n\n  protected executeDownload(taskOptions: DownloadExecutorTask): Promise<Array<string>> {\n    return super.executeDownload({\n      ...taskOptions,\n      done: event => {\n        this.dispatchUpdateDownloaded(event)\n        this.addQuitHandler()\n        return Promise.resolve()\n      },\n    })\n  }\n\n  protected get installerPath(): string | null {\n    return this.downloadedUpdateHelper == null ? null : this.downloadedUpdateHelper.file\n  }\n\n  // must be sync\n  protected abstract doInstall(options: InstallOptions): boolean\n\n  // must be sync (because quit even handler is not async)\n  install(isSilent = false, isForceRunAfter = false): boolean {\n    if (this.quitAndInstallCalled) {\n      this._logger.warn(\"install call ignored: quitAndInstallCalled is set to true\")\n      return false\n    }\n\n    const downloadedUpdateHelper = this.downloadedUpdateHelper\n    const installerPath = this.installerPath\n    const downloadedFileInfo = downloadedUpdateHelper == null ? null : downloadedUpdateHelper.downloadedFileInfo\n    if (installerPath == null || downloadedFileInfo == null) {\n      this.dispatchError(new Error(\"No valid update available, can't quit and install\"))\n      return false\n    }\n\n    // prevent calling several times\n    this.quitAndInstallCalled = true\n\n    try {\n      this._logger.info(`Install: isSilent: ${isSilent}, isForceRunAfter: ${isForceRunAfter}`)\n      return this.doInstall({\n        isSilent,\n        isForceRunAfter,\n        isAdminRightsRequired: downloadedFileInfo.isAdminRightsRequired,\n      })\n    } catch (e: any) {\n      this.dispatchError(e)\n      return false\n    }\n  }\n\n  protected addQuitHandler(): void {\n    if (this.quitHandlerAdded || !this.autoInstallOnAppQuit) {\n      return\n    }\n\n    this.quitHandlerAdded = true\n\n    this.app.onQuit(exitCode => {\n      if (this.quitAndInstallCalled) {\n        this._logger.info(\"Update installer has already been triggered. Quitting application.\")\n        return\n      }\n\n      if (!this.autoInstallOnAppQuit) {\n        this._logger.info(\"Update will not be installed on quit because autoInstallOnAppQuit is set to false.\")\n        return\n      }\n\n      if (exitCode !== 0) {\n        this._logger.info(`Update will be not installed on quit because application is quitting with exit code ${exitCode}`)\n        return\n      }\n\n      this._logger.info(\"Auto install update on quit\")\n      this.install(true, false)\n    })\n  }\n\n  protected wrapSudo() {\n    const { name } = this.app\n    const installComment = `\"${name} would like to update\"`\n    const sudo = this.spawnSyncLog(\"which gksudo || which kdesudo || which pkexec || which beesu\")\n    const command = [sudo]\n    if (/kdesudo/i.test(sudo)) {\n      command.push(\"--comment\", installComment)\n      command.push(\"-c\")\n    } else if (/gksudo/i.test(sudo)) {\n      command.push(\"--message\", installComment)\n    } else if (/pkexec/i.test(sudo)) {\n      command.push(\"--disable-internal-agent\")\n    }\n    return command.join(\" \")\n  }\n\n  protected spawnSyncLog(cmd: string, args: string[] = [], env = {}): string {\n    this._logger.info(`Executing: ${cmd} with args: ${args}`)\n    const response = spawnSync(cmd, args, {\n      env: { ...process.env, ...env },\n      encoding: \"utf-8\",\n      shell: true,\n    })\n\n    const { error, status, stdout, stderr } = response\n    if (error != null) {\n      this._logger.error(stderr)\n      throw error\n    } else if (status != null && status !== 0) {\n      this._logger.error(stderr)\n      throw new Error(`Command ${cmd} exited with code ${status}`)\n    }\n\n    return stdout.trim()\n  }\n\n  /**\n   * This handles both node 8 and node 10 way of emitting error when spawning a process\n   *   - node 8: Throws the error\n   *   - node 10: Emit the error(Need to listen with on)\n   */\n  // https://github.com/electron-userland/electron-builder/issues/1129\n  // Node 8 sends errors: https://nodejs.org/dist/latest-v8.x/docs/api/errors.html#errors_common_system_errors\n  protected async spawnLog(cmd: string, args: string[] = [], env: any = undefined, stdio: StdioOptions = \"ignore\"): Promise<boolean> {\n    this._logger.info(`Executing: ${cmd} with args: ${args}`)\n    return new Promise<boolean>((resolve, reject) => {\n      try {\n        const params: SpawnOptions = { stdio, env, detached: true }\n        const p = spawn(cmd, args, params)\n        p.on(\"error\", error => {\n          reject(error)\n        })\n        p.unref()\n        if (p.pid !== undefined) {\n          resolve(true)\n        }\n      } catch (error) {\n        reject(error)\n      }\n    })\n  }\n}\n\nexport interface InstallOptions {\n  readonly isSilent: boolean\n  readonly isForceRunAfter: boolean\n  readonly isAdminRightsRequired: boolean\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DebUpdater = void 0;
const BaseUpdater_1 = require("./BaseUpdater");
const Provider_1 = require("./providers/Provider");
const types_1 = require("./types");
class DebUpdater extends BaseUpdater_1.BaseUpdater {
    constructor(options, app) {
        super(options, app);
    }
    /*** @private */
    doDownloadUpdate(downloadUpdateOptions) {
        const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
        const fileInfo = (0, Provider_1.findFile)(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), "deb", ["AppImage", "rpm", "pacman"]);
        return this.executeDownload({
            fileExtension: "deb",
            fileInfo,
            downloadUpdateOptions,
            task: async (updateFile, downloadOptions) => {
                if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
                    downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
                }
                await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions);
            },
        });
    }
    get installerPath() {
        var _a, _b;
        return (_b = (_a = super.installerPath) === null || _a === void 0 ? void 0 : _a.replace(/ /g, "\\ ")) !== null && _b !== void 0 ? _b : null;
    }
    doInstall(options) {
        const sudo = this.wrapSudo();
        // pkexec doesn't want the command to be wrapped in " quotes
        const wrapper = /pkexec/i.test(sudo) ? "" : `"`;
        const installerPath = this.installerPath;
        if (installerPath == null) {
            this.dispatchError(new Error("No valid update available, can't quit and install"));
            return false;
        }
        const cmd = ["dpkg", "-i", installerPath, "||", "apt-get", "install", "-f", "-y"];
        this.spawnSyncLog(sudo, [`${wrapper}/bin/bash`, "-c", `'${cmd.join(" ")}'${wrapper}`]);
        if (options.isForceRunAfter) {
            this.app.relaunch();
        }
        return true;
    }
}
exports.DebUpdater = DebUpdater;
//# sourceMappingURL=DebUpdater.js.map{"version":3,"file":"DebUpdater.js","sourceRoot":"","sources":["../src/DebUpdater.ts"],"names":[],"mappings":";;;AAGA,+CAA2D;AAC3D,mDAA+C;AAC/C,mCAA2C;AAE3C,MAAa,UAAW,SAAQ,yBAAW;IACzC,YAAY,OAAkC,EAAE,GAAgB;QAC9D,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;IACrB,CAAC;IAED,gBAAgB;IACN,gBAAgB,CAAC,qBAA4C;QACrE,MAAM,QAAQ,GAAG,qBAAqB,CAAC,qBAAqB,CAAC,QAAQ,CAAA;QACrE,MAAM,QAAQ,GAAG,IAAA,mBAAQ,EAAC,QAAQ,CAAC,YAAY,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAE,CAAA;QACzI,OAAO,IAAI,CAAC,eAAe,CAAC;YAC1B,aAAa,EAAE,KAAK;YACpB,QAAQ;YACR,qBAAqB;YACrB,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,EAAE;gBAC1C,IAAI,IAAI,CAAC,aAAa,CAAC,yBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC9C,eAAe,CAAC,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAiB,EAAE,EAAE,CAAC,CAAA;gBACrE,CAAC;gBACD,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,eAAe,CAAC,CAAA;YAC7E,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;IAED,IAAc,aAAa;;QACzB,OAAO,MAAA,MAAA,KAAK,CAAC,aAAa,0CAAE,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,mCAAI,IAAI,CAAA;IAC1D,CAAC;IAES,SAAS,CAAC,OAAuB;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;QAC5B,4DAA4D;QAC5D,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA;QAC/C,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAA;QACxC,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC,CAAA;YAClF,OAAO,KAAK,CAAA;QACd,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;QACjF,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,WAAW,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAA;QACtF,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAA;QACrB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;CACF;AA1CD,gCA0CC","sourcesContent":["import { AllPublishOptions } from \"builder-util-runtime\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { DownloadUpdateOptions } from \"./AppUpdater\"\nimport { BaseUpdater, InstallOptions } from \"./BaseUpdater\"\nimport { findFile } from \"./providers/Provider\"\nimport { DOWNLOAD_PROGRESS } from \"./types\"\n\nexport class DebUpdater extends BaseUpdater {\n  constructor(options?: AllPublishOptions | null, app?: AppAdapter) {\n    super(options, app)\n  }\n\n  /*** @private */\n  protected doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n    const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n    const fileInfo = findFile(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), \"deb\", [\"AppImage\", \"rpm\", \"pacman\"])!\n    return this.executeDownload({\n      fileExtension: \"deb\",\n      fileInfo,\n      downloadUpdateOptions,\n      task: async (updateFile, downloadOptions) => {\n        if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n          downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n        }\n        await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions)\n      },\n    })\n  }\n\n  protected get installerPath(): string | null {\n    return super.installerPath?.replace(/ /g, \"\\\\ \") ?? null\n  }\n\n  protected doInstall(options: InstallOptions): boolean {\n    const sudo = this.wrapSudo()\n    // pkexec doesn't want the command to be wrapped in \" quotes\n    const wrapper = /pkexec/i.test(sudo) ? \"\" : `\"`\n    const installerPath = this.installerPath\n    if (installerPath == null) {\n      this.dispatchError(new Error(\"No valid update available, can't quit and install\"))\n      return false\n    }\n    const cmd = [\"dpkg\", \"-i\", installerPath, \"||\", \"apt-get\", \"install\", \"-f\", \"-y\"]\n    this.spawnSyncLog(sudo, [`${wrapper}/bin/bash`, \"-c\", `'${cmd.join(\" \")}'${wrapper}`])\n    if (options.isForceRunAfter) {\n      this.app.relaunch()\n    }\n    return true\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DownloadedUpdateHelper = void 0;
exports.createTempUpdateFile = createTempUpdateFile;
const crypto_1 = require("crypto");
const fs_1 = require("fs");
// @ts-ignore
const isEqual = require("lodash.isequal");
const fs_extra_1 = require("fs-extra");
const path = require("path");
/** @private **/
class DownloadedUpdateHelper {
    constructor(cacheDir) {
        this.cacheDir = cacheDir;
        this._file = null;
        this._packageFile = null;
        this.versionInfo = null;
        this.fileInfo = null;
        this._downloadedFileInfo = null;
    }
    get downloadedFileInfo() {
        return this._downloadedFileInfo;
    }
    get file() {
        return this._file;
    }
    get packageFile() {
        return this._packageFile;
    }
    get cacheDirForPendingUpdate() {
        return path.join(this.cacheDir, "pending");
    }
    async validateDownloadedPath(updateFile, updateInfo, fileInfo, logger) {
        if (this.versionInfo != null && this.file === updateFile && this.fileInfo != null) {
            // update has already been downloaded from this running instance
            // check here only existence, not checksum
            if (isEqual(this.versionInfo, updateInfo) && isEqual(this.fileInfo.info, fileInfo.info) && (await (0, fs_extra_1.pathExists)(updateFile))) {
                return updateFile;
            }
            else {
                return null;
            }
        }
        // update has already been downloaded from some previous app launch
        const cachedUpdateFile = await this.getValidCachedUpdateFile(fileInfo, logger);
        if (cachedUpdateFile === null) {
            return null;
        }
        logger.info(`Update has already been downloaded to ${updateFile}).`);
        this._file = cachedUpdateFile;
        return cachedUpdateFile;
    }
    async setDownloadedFile(downloadedFile, packageFile, versionInfo, fileInfo, updateFileName, isSaveCache) {
        this._file = downloadedFile;
        this._packageFile = packageFile;
        this.versionInfo = versionInfo;
        this.fileInfo = fileInfo;
        this._downloadedFileInfo = {
            fileName: updateFileName,
            sha512: fileInfo.info.sha512,
            isAdminRightsRequired: fileInfo.info.isAdminRightsRequired === true,
        };
        if (isSaveCache) {
            await (0, fs_extra_1.outputJson)(this.getUpdateInfoFile(), this._downloadedFileInfo);
        }
    }
    async clear() {
        this._file = null;
        this._packageFile = null;
        this.versionInfo = null;
        this.fileInfo = null;
        await this.cleanCacheDirForPendingUpdate();
    }
    async cleanCacheDirForPendingUpdate() {
        try {
            // remove stale data
            await (0, fs_extra_1.emptyDir)(this.cacheDirForPendingUpdate);
        }
        catch (_ignore) {
            // ignore
        }
    }
    /**
     * Returns "update-info.json" which is created in the update cache directory's "pending" subfolder after the first update is downloaded.  If the update file does not exist then the cache is cleared and recreated.  If the update file exists then its properties are validated.
     * @param fileInfo
     * @param logger
     */
    async getValidCachedUpdateFile(fileInfo, logger) {
        const updateInfoFilePath = this.getUpdateInfoFile();
        const doesUpdateInfoFileExist = await (0, fs_extra_1.pathExists)(updateInfoFilePath);
        if (!doesUpdateInfoFileExist) {
            return null;
        }
        let cachedInfo;
        try {
            cachedInfo = await (0, fs_extra_1.readJson)(updateInfoFilePath);
        }
        catch (error) {
            let message = `No cached update info available`;
            if (error.code !== "ENOENT") {
                await this.cleanCacheDirForPendingUpdate();
                message += ` (error on read: ${error.message})`;
            }
            logger.info(message);
            return null;
        }
        const isCachedInfoFileNameValid = (cachedInfo === null || cachedInfo === void 0 ? void 0 : cachedInfo.fileName) !== null;
        if (!isCachedInfoFileNameValid) {
            logger.warn(`Cached update info is corrupted: no fileName, directory for cached update will be cleaned`);
            await this.cleanCacheDirForPendingUpdate();
            return null;
        }
        if (fileInfo.info.sha512 !== cachedInfo.sha512) {
            logger.info(`Cached update sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${cachedInfo.sha512}, expected: ${fileInfo.info.sha512}. Directory for cached update will be cleaned`);
            await this.cleanCacheDirForPendingUpdate();
            return null;
        }
        const updateFile = path.join(this.cacheDirForPendingUpdate, cachedInfo.fileName);
        if (!(await (0, fs_extra_1.pathExists)(updateFile))) {
            logger.info("Cached update file doesn't exist");
            return null;
        }
        const sha512 = await hashFile(updateFile);
        if (fileInfo.info.sha512 !== sha512) {
            logger.warn(`Sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${sha512}, expected: ${fileInfo.info.sha512}`);
            await this.cleanCacheDirForPendingUpdate();
            return null;
        }
        this._downloadedFileInfo = cachedInfo;
        return updateFile;
    }
    getUpdateInfoFile() {
        return path.join(this.cacheDirForPendingUpdate, "update-info.json");
    }
}
exports.DownloadedUpdateHelper = DownloadedUpdateHelper;
function hashFile(file, algorithm = "sha512", encoding = "base64", options) {
    return new Promise((resolve, reject) => {
        const hash = (0, crypto_1.createHash)(algorithm);
        hash.on("error", reject).setEncoding(encoding);
        (0, fs_1.createReadStream)(file, { ...options, highWaterMark: 1024 * 1024 /* better to use more memory but hash faster */ })
            .on("error", reject)
            .on("end", () => {
            hash.end();
            resolve(hash.read());
        })
            .pipe(hash, { end: false });
    });
}
async function createTempUpdateFile(name, cacheDir, log) {
    // https://github.com/electron-userland/electron-builder/pull/2474#issuecomment-366481912
    let nameCounter = 0;
    let result = path.join(cacheDir, name);
    for (let i = 0; i < 3; i++) {
        try {
            await (0, fs_extra_1.unlink)(result);
            return result;
        }
        catch (e) {
            if (e.code === "ENOENT") {
                return result;
            }
            log.warn(`Error on remove temp update file: ${e}`);
            result = path.join(cacheDir, `${nameCounter++}-${name}`);
        }
    }
    return result;
}
//# sourceMappingURL=DownloadedUpdateHelper.js.map{"version":3,"file":"DownloadedUpdateHelper.js","sourceRoot":"","sources":["../src/DownloadedUpdateHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import { UpdateInfo } from \"builder-util-runtime\"\nimport { createHash } from \"crypto\"\nimport { createReadStream } from \"fs\"\n// @ts-ignore\nimport * as isEqual from \"lodash.isequal\"\nimport { ResolvedUpdateFileInfo } from \"./types\"\nimport { Logger } from \"./types\"\nimport { pathExists, readJson, emptyDir, outputJson, unlink } from \"fs-extra\"\nimport * as path from \"path\"\n\n/** @private **/\nexport class DownloadedUpdateHelper {\n  private _file: string | null = null\n  private _packageFile: string | null = null\n\n  private versionInfo: UpdateInfo | null = null\n  private fileInfo: ResolvedUpdateFileInfo | null = null\n\n  constructor(readonly cacheDir: string) {}\n\n  private _downloadedFileInfo: CachedUpdateInfo | null = null\n  get downloadedFileInfo(): CachedUpdateInfo | null {\n    return this._downloadedFileInfo\n  }\n\n  get file(): string | null {\n    return this._file\n  }\n\n  get packageFile(): string | null {\n    return this._packageFile\n  }\n\n  get cacheDirForPendingUpdate(): string {\n    return path.join(this.cacheDir, \"pending\")\n  }\n\n  async validateDownloadedPath(updateFile: string, updateInfo: UpdateInfo, fileInfo: ResolvedUpdateFileInfo, logger: Logger): Promise<string | null> {\n    if (this.versionInfo != null && this.file === updateFile && this.fileInfo != null) {\n      // update has already been downloaded from this running instance\n      // check here only existence, not checksum\n      if (isEqual(this.versionInfo, updateInfo) && isEqual(this.fileInfo.info, fileInfo.info) && (await pathExists(updateFile))) {\n        return updateFile\n      } else {\n        return null\n      }\n    }\n\n    // update has already been downloaded from some previous app launch\n    const cachedUpdateFile = await this.getValidCachedUpdateFile(fileInfo, logger)\n    if (cachedUpdateFile === null) {\n      return null\n    }\n    logger.info(`Update has already been downloaded to ${updateFile}).`)\n    this._file = cachedUpdateFile\n    return cachedUpdateFile\n  }\n\n  async setDownloadedFile(\n    downloadedFile: string,\n    packageFile: string | null,\n    versionInfo: UpdateInfo,\n    fileInfo: ResolvedUpdateFileInfo,\n    updateFileName: string,\n    isSaveCache: boolean\n  ): Promise<void> {\n    this._file = downloadedFile\n    this._packageFile = packageFile\n    this.versionInfo = versionInfo\n    this.fileInfo = fileInfo\n    this._downloadedFileInfo = {\n      fileName: updateFileName,\n      sha512: fileInfo.info.sha512,\n      isAdminRightsRequired: fileInfo.info.isAdminRightsRequired === true,\n    }\n\n    if (isSaveCache) {\n      await outputJson(this.getUpdateInfoFile(), this._downloadedFileInfo)\n    }\n  }\n\n  async clear(): Promise<void> {\n    this._file = null\n    this._packageFile = null\n    this.versionInfo = null\n    this.fileInfo = null\n    await this.cleanCacheDirForPendingUpdate()\n  }\n\n  private async cleanCacheDirForPendingUpdate(): Promise<void> {\n    try {\n      // remove stale data\n      await emptyDir(this.cacheDirForPendingUpdate)\n    } catch (_ignore) {\n      // ignore\n    }\n  }\n\n  /**\n   * Returns \"update-info.json\" which is created in the update cache directory's \"pending\" subfolder after the first update is downloaded.  If the update file does not exist then the cache is cleared and recreated.  If the update file exists then its properties are validated.\n   * @param fileInfo\n   * @param logger\n   */\n  private async getValidCachedUpdateFile(fileInfo: ResolvedUpdateFileInfo, logger: Logger): Promise<string | null> {\n    const updateInfoFilePath: string = this.getUpdateInfoFile()\n\n    const doesUpdateInfoFileExist = await pathExists(updateInfoFilePath)\n    if (!doesUpdateInfoFileExist) {\n      return null\n    }\n\n    let cachedInfo: CachedUpdateInfo\n    try {\n      cachedInfo = await readJson(updateInfoFilePath)\n    } catch (error: any) {\n      let message = `No cached update info available`\n      if (error.code !== \"ENOENT\") {\n        await this.cleanCacheDirForPendingUpdate()\n        message += ` (error on read: ${error.message})`\n      }\n      logger.info(message)\n      return null\n    }\n\n    const isCachedInfoFileNameValid = cachedInfo?.fileName !== null\n    if (!isCachedInfoFileNameValid) {\n      logger.warn(`Cached update info is corrupted: no fileName, directory for cached update will be cleaned`)\n      await this.cleanCacheDirForPendingUpdate()\n      return null\n    }\n\n    if (fileInfo.info.sha512 !== cachedInfo.sha512) {\n      logger.info(\n        `Cached update sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${cachedInfo.sha512}, expected: ${fileInfo.info.sha512}. Directory for cached update will be cleaned`\n      )\n      await this.cleanCacheDirForPendingUpdate()\n      return null\n    }\n\n    const updateFile = path.join(this.cacheDirForPendingUpdate, cachedInfo.fileName)\n    if (!(await pathExists(updateFile))) {\n      logger.info(\"Cached update file doesn't exist\")\n      return null\n    }\n\n    const sha512 = await hashFile(updateFile)\n    if (fileInfo.info.sha512 !== sha512) {\n      logger.warn(`Sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${sha512}, expected: ${fileInfo.info.sha512}`)\n      await this.cleanCacheDirForPendingUpdate()\n      return null\n    }\n    this._downloadedFileInfo = cachedInfo\n    return updateFile\n  }\n\n  private getUpdateInfoFile(): string {\n    return path.join(this.cacheDirForPendingUpdate, \"update-info.json\")\n  }\n}\n\ninterface CachedUpdateInfo {\n  fileName: string\n  sha512: string\n  readonly isAdminRightsRequired: boolean\n}\n\nfunction hashFile(file: string, algorithm = \"sha512\", encoding: \"base64\" | \"hex\" = \"base64\", options?: any): Promise<string> {\n  return new Promise<string>((resolve, reject) => {\n    const hash = createHash(algorithm)\n    hash.on(\"error\", reject).setEncoding(encoding)\n\n    createReadStream(file, { ...options, highWaterMark: 1024 * 1024 /* better to use more memory but hash faster */ })\n      .on(\"error\", reject)\n      .on(\"end\", () => {\n        hash.end()\n        resolve(hash.read() as string)\n      })\n      .pipe(hash, { end: false })\n  })\n}\n\nexport async function createTempUpdateFile(name: string, cacheDir: string, log: Logger): Promise<string> {\n  // https://github.com/electron-userland/electron-builder/pull/2474#issuecomment-366481912\n  let nameCounter = 0\n  let result = path.join(cacheDir, name)\n  for (let i = 0; i < 3; i++) {\n    try {\n      await unlink(result)\n      return result\n    } catch (e: any) {\n      if (e.code === \"ENOENT\") {\n        return result\n      }\n\n      log.warn(`Error on remove temp update file: ${e}`)\n      result = path.join(cacheDir, `${nameCounter++}-${name}`)\n    }\n  }\n  return result\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ElectronAppAdapter = void 0;
const path = require("path");
const AppAdapter_1 = require("./AppAdapter");
class ElectronAppAdapter {
    constructor(app = require("electron").app) {
        this.app = app;
    }
    whenReady() {
        return this.app.whenReady();
    }
    get version() {
        return this.app.getVersion();
    }
    get name() {
        return this.app.getName();
    }
    get isPackaged() {
        return this.app.isPackaged === true;
    }
    get appUpdateConfigPath() {
        return this.isPackaged ? path.join(process.resourcesPath, "app-update.yml") : path.join(this.app.getAppPath(), "dev-app-update.yml");
    }
    get userDataPath() {
        return this.app.getPath("userData");
    }
    get baseCachePath() {
        return (0, AppAdapter_1.getAppCacheDir)();
    }
    quit() {
        this.app.quit();
    }
    relaunch() {
        this.app.relaunch();
    }
    onQuit(handler) {
        this.app.once("quit", (_, exitCode) => handler(exitCode));
    }
}
exports.ElectronAppAdapter = ElectronAppAdapter;
//# sourceMappingURL=ElectronAppAdapter.js.map{"version":3,"file":"ElectronAppAdapter.js","sourceRoot":"","sources":["../src/ElectronAppAdapter.ts"],"names":[],"mappings":";;;AAAA,6BAA4B;AAC5B,6CAAyD;AAEzD,MAAa,kBAAkB;IAC7B,YAA6B,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG;QAA7B,QAAG,GAAH,GAAG,CAA0B;IAAG,CAAC;IAE9D,SAAS;QACP,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAA;IAC7B,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAA;IAC9B,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAA;IAC3B,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,KAAK,IAAI,CAAA;IACrC,CAAC;IAED,IAAI,mBAAmB;QACrB,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,oBAAoB,CAAC,CAAA;IACtI,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IACrC,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAA,2BAAc,GAAE,CAAA;IACzB,CAAC;IAED,IAAI;QACF,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;IACjB,CAAC;IAED,QAAQ;QACN,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAA;IACrB,CAAC;IAED,MAAM,CAAC,OAAmC;QACxC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAiB,EAAE,QAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;IACnF,CAAC;CACF;AA1CD,gDA0CC","sourcesContent":["import * as path from \"path\"\nimport { AppAdapter, getAppCacheDir } from \"./AppAdapter\"\n\nexport class ElectronAppAdapter implements AppAdapter {\n  constructor(private readonly app = require(\"electron\").app) {}\n\n  whenReady(): Promise<void> {\n    return this.app.whenReady()\n  }\n\n  get version(): string {\n    return this.app.getVersion()\n  }\n\n  get name(): string {\n    return this.app.getName()\n  }\n\n  get isPackaged(): boolean {\n    return this.app.isPackaged === true\n  }\n\n  get appUpdateConfigPath(): string {\n    return this.isPackaged ? path.join(process.resourcesPath, \"app-update.yml\") : path.join(this.app.getAppPath(), \"dev-app-update.yml\")\n  }\n\n  get userDataPath(): string {\n    return this.app.getPath(\"userData\")\n  }\n\n  get baseCachePath(): string {\n    return getAppCacheDir()\n  }\n\n  quit(): void {\n    this.app.quit()\n  }\n\n  relaunch(): void {\n    this.app.relaunch()\n  }\n\n  onQuit(handler: (exitCode: number) => void): void {\n    this.app.once(\"quit\", (_: Electron.Event, exitCode: number) => handler(exitCode))\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MacUpdater = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const fs_extra_1 = require("fs-extra");
const fs_1 = require("fs");
const path = require("path");
const http_1 = require("http");
const AppUpdater_1 = require("./AppUpdater");
const Provider_1 = require("./providers/Provider");
const child_process_1 = require("child_process");
const crypto_1 = require("crypto");
class MacUpdater extends AppUpdater_1.AppUpdater {
    constructor(options, app) {
        super(options, app);
        this.nativeUpdater = require("electron").autoUpdater;
        this.squirrelDownloadedUpdate = false;
        this.nativeUpdater.on("error", it => {
            this._logger.warn(it);
            this.emit("error", it);
        });
        this.nativeUpdater.on("update-downloaded", () => {
            this.squirrelDownloadedUpdate = true;
            this.debug("nativeUpdater.update-downloaded");
        });
    }
    debug(message) {
        if (this._logger.debug != null) {
            this._logger.debug(message);
        }
    }
    closeServerIfExists() {
        if (this.server) {
            this.debug("Closing proxy server");
            this.server.close(err => {
                if (err) {
                    this.debug("proxy server wasn't already open, probably attempted closing again as a safety check before quit");
                }
            });
        }
    }
    async doDownloadUpdate(downloadUpdateOptions) {
        let files = downloadUpdateOptions.updateInfoAndProvider.provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info);
        const log = this._logger;
        // detect if we are running inside Rosetta emulation
        const sysctlRosettaInfoKey = "sysctl.proc_translated";
        let isRosetta = false;
        try {
            this.debug("Checking for macOS Rosetta environment");
            const result = (0, child_process_1.execFileSync)("sysctl", [sysctlRosettaInfoKey], { encoding: "utf8" });
            isRosetta = result.includes(`${sysctlRosettaInfoKey}: 1`);
            log.info(`Checked for macOS Rosetta environment (isRosetta=${isRosetta})`);
        }
        catch (e) {
            log.warn(`sysctl shell command to check for macOS Rosetta environment failed: ${e}`);
        }
        let isArm64Mac = false;
        try {
            this.debug("Checking for arm64 in uname");
            const result = (0, child_process_1.execFileSync)("uname", ["-a"], { encoding: "utf8" });
            const isArm = result.includes("ARM");
            log.info(`Checked 'uname -a': arm64=${isArm}`);
            isArm64Mac = isArm64Mac || isArm;
        }
        catch (e) {
            log.warn(`uname shell command to check for arm64 failed: ${e}`);
        }
        isArm64Mac = isArm64Mac || process.arch === "arm64" || isRosetta;
        // allow arm64 macs to install universal or rosetta2(x64) - https://github.com/electron-userland/electron-builder/pull/5524
        const isArm64 = (file) => { var _a; return file.url.pathname.includes("arm64") || ((_a = file.info.url) === null || _a === void 0 ? void 0 : _a.includes("arm64")); };
        if (isArm64Mac && files.some(isArm64)) {
            files = files.filter(file => isArm64Mac === isArm64(file));
        }
        else {
            files = files.filter(file => !isArm64(file));
        }
        const zipFileInfo = (0, Provider_1.findFile)(files, "zip", ["pkg", "dmg"]);
        if (zipFileInfo == null) {
            throw (0, builder_util_runtime_1.newError)(`ZIP file not provided: ${(0, builder_util_runtime_1.safeStringifyJson)(files)}`, "ERR_UPDATER_ZIP_FILE_NOT_FOUND");
        }
        const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
        const CURRENT_MAC_APP_ZIP_FILE_NAME = "update.zip";
        return this.executeDownload({
            fileExtension: "zip",
            fileInfo: zipFileInfo,
            downloadUpdateOptions,
            task: async (destinationFile, downloadOptions) => {
                const cachedUpdateFilePath = path.join(this.downloadedUpdateHelper.cacheDir, CURRENT_MAC_APP_ZIP_FILE_NAME);
                const canDifferentialDownload = () => {
                    if (!(0, fs_extra_1.pathExistsSync)(cachedUpdateFilePath)) {
                        log.info("Unable to locate previous update.zip for differential download (is this first install?), falling back to full download");
                        return false;
                    }
                    return !downloadUpdateOptions.disableDifferentialDownload;
                };
                let differentialDownloadFailed = true;
                if (canDifferentialDownload()) {
                    differentialDownloadFailed = await this.differentialDownloadInstaller(zipFileInfo, downloadUpdateOptions, destinationFile, provider, CURRENT_MAC_APP_ZIP_FILE_NAME);
                }
                if (differentialDownloadFailed) {
                    await this.httpExecutor.download(zipFileInfo.url, destinationFile, downloadOptions);
                }
            },
            done: async (event) => {
                if (!downloadUpdateOptions.disableDifferentialDownload) {
                    try {
                        const cachedUpdateFilePath = path.join(this.downloadedUpdateHelper.cacheDir, CURRENT_MAC_APP_ZIP_FILE_NAME);
                        await (0, fs_extra_1.copyFile)(event.downloadedFile, cachedUpdateFilePath);
                    }
                    catch (error) {
                        this._logger.warn(`Unable to copy file for caching for future differential downloads: ${error.message}`);
                    }
                }
                return this.updateDownloaded(zipFileInfo, event);
            },
        });
    }
    async updateDownloaded(zipFileInfo, event) {
        var _a;
        const downloadedFile = event.downloadedFile;
        const updateFileSize = (_a = zipFileInfo.info.size) !== null && _a !== void 0 ? _a : (await (0, fs_extra_1.stat)(downloadedFile)).size;
        const log = this._logger;
        const logContext = `fileToProxy=${zipFileInfo.url.href}`;
        this.closeServerIfExists();
        this.debug(`Creating proxy server for native Squirrel.Mac (${logContext})`);
        this.server = (0, http_1.createServer)();
        this.debug(`Proxy server for native Squirrel.Mac is created (${logContext})`);
        this.server.on("close", () => {
            log.info(`Proxy server for native Squirrel.Mac is closed (${logContext})`);
        });
        // must be called after server is listening, otherwise address is null
        const getServerUrl = (s) => {
            const address = s.address();
            if (typeof address === "string") {
                return address;
            }
            return `http://127.0.0.1:${address === null || address === void 0 ? void 0 : address.port}`;
        };
        return await new Promise((resolve, reject) => {
            const pass = (0, crypto_1.randomBytes)(64).toString("base64").replace(/\//g, "_").replace(/\+/g, "-");
            const authInfo = Buffer.from(`autoupdater:${pass}`, "ascii");
            // insecure random is ok
            const fileUrl = `/${(0, crypto_1.randomBytes)(64).toString("hex")}.zip`;
            this.server.on("request", (request, response) => {
                const requestUrl = request.url;
                log.info(`${requestUrl} requested`);
                if (requestUrl === "/") {
                    // check for basic auth header
                    if (!request.headers.authorization || request.headers.authorization.indexOf("Basic ") === -1) {
                        response.statusCode = 401;
                        response.statusMessage = "Invalid Authentication Credentials";
                        response.end();
                        log.warn("No authenthication info");
                        return;
                    }
                    // verify auth credentials
                    const base64Credentials = request.headers.authorization.split(" ")[1];
                    const credentials = Buffer.from(base64Credentials, "base64").toString("ascii");
                    const [username, password] = credentials.split(":");
                    if (username !== "autoupdater" || password !== pass) {
                        response.statusCode = 401;
                        response.statusMessage = "Invalid Authentication Credentials";
                        response.end();
                        log.warn("Invalid authenthication credentials");
                        return;
                    }
                    const data = Buffer.from(`{ "url": "${getServerUrl(this.server)}${fileUrl}" }`);
                    response.writeHead(200, { "Content-Type": "application/json", "Content-Length": data.length });
                    response.end(data);
                    return;
                }
                if (!requestUrl.startsWith(fileUrl)) {
                    log.warn(`${requestUrl} requested, but not supported`);
                    response.writeHead(404);
                    response.end();
                    return;
                }
                log.info(`${fileUrl} requested by Squirrel.Mac, pipe ${downloadedFile}`);
                let errorOccurred = false;
                response.on("finish", () => {
                    if (!errorOccurred) {
                        this.nativeUpdater.removeListener("error", reject);
                        resolve([]);
                    }
                });
                const readStream = (0, fs_1.createReadStream)(downloadedFile);
                readStream.on("error", error => {
                    try {
                        response.end();
                    }
                    catch (e) {
                        log.warn(`cannot end response: ${e}`);
                    }
                    errorOccurred = true;
                    this.nativeUpdater.removeListener("error", reject);
                    reject(new Error(`Cannot pipe "${downloadedFile}": ${error}`));
                });
                response.writeHead(200, {
                    "Content-Type": "application/zip",
                    "Content-Length": updateFileSize,
                });
                readStream.pipe(response);
            });
            this.debug(`Proxy server for native Squirrel.Mac is starting to listen (${logContext})`);
            this.server.listen(0, "127.0.0.1", () => {
                this.debug(`Proxy server for native Squirrel.Mac is listening (address=${getServerUrl(this.server)}, ${logContext})`);
                this.nativeUpdater.setFeedURL({
                    url: getServerUrl(this.server),
                    headers: {
                        "Cache-Control": "no-cache",
                        Authorization: `Basic ${authInfo.toString("base64")}`,
                    },
                });
                // The update has been downloaded and is ready to be served to Squirrel
                this.dispatchUpdateDownloaded(event);
                if (this.autoInstallOnAppQuit) {
                    this.nativeUpdater.once("error", reject);
                    // This will trigger fetching and installing the file on Squirrel side
                    this.nativeUpdater.checkForUpdates();
                }
                else {
                    resolve([]);
                }
            });
        });
    }
    handleUpdateDownloaded() {
        if (this.autoRunAppAfterInstall) {
            this.nativeUpdater.quitAndInstall();
        }
        else {
            this.app.quit();
        }
        this.closeServerIfExists();
    }
    quitAndInstall() {
        if (this.squirrelDownloadedUpdate) {
            // update already fetched by Squirrel, it's ready to install
            this.handleUpdateDownloaded();
        }
        else {
            // Quit and install as soon as Squirrel get the update
            this.nativeUpdater.on("update-downloaded", () => this.handleUpdateDownloaded());
            if (!this.autoInstallOnAppQuit) {
                /**
                 * If this was not `true` previously then MacUpdater.doDownloadUpdate()
                 * would not actually initiate the downloading by electron's autoUpdater
                 */
                this.nativeUpdater.checkForUpdates();
            }
        }
    }
}
exports.MacUpdater = MacUpdater;
//# sourceMappingURL=MacUpdater.js.map{"version":3,"file":"MacUpdater.js","sourceRoot":"","sources":["../src/MacUpdater.ts"],"names":[],"mappings":";;;AAAA,+DAAqF;AACrF,uCAAyD;AACzD,2BAAqC;AACrC,6BAA4B;AAC5B,+BAA4E;AAE5E,6CAAgE;AAGhE,mDAA+C;AAE/C,iDAA4C;AAC5C,mCAAoC;AAEpC,MAAa,UAAW,SAAQ,uBAAU;IAOxC,YAAY,OAA2B,EAAE,GAAgB;QACvD,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;QAPJ,kBAAa,GAAgB,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,CAAA;QAErE,6BAAwB,GAAG,KAAK,CAAA;QAOtC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE;YAClC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YACrB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;QACxB,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;YAC9C,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAA;YACpC,IAAI,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAA;QAC/C,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,KAAK,CAAC,OAAe;QAC3B,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;YAC/B,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC7B,CAAC;IACH,CAAC;IAEO,mBAAmB;QACzB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAA;YAClC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;gBACtB,IAAI,GAAG,EAAE,CAAC;oBACR,IAAI,CAAC,KAAK,CAAC,kGAAkG,CAAC,CAAA;gBAChH,CAAC;YACH,CAAC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAES,KAAK,CAAC,gBAAgB,CAAC,qBAA4C;QAC3E,IAAI,KAAK,GAAG,qBAAqB,CAAC,qBAAqB,CAAC,QAAQ,CAAC,YAAY,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAA;QAE/H,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAA;QAExB,oDAAoD;QACpD,MAAM,oBAAoB,GAAG,wBAAwB,CAAA;QACrD,IAAI,SAAS,GAAG,KAAK,CAAA;QACrB,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAA;YACpD,MAAM,MAAM,GAAG,IAAA,4BAAY,EAAC,QAAQ,EAAE,CAAC,oBAAoB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;YACnF,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,oBAAoB,KAAK,CAAC,CAAA;YACzD,GAAG,CAAC,IAAI,CAAC,oDAAoD,SAAS,GAAG,CAAC,CAAA;QAC5E,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,GAAG,CAAC,IAAI,CAAC,uEAAuE,CAAC,EAAE,CAAC,CAAA;QACtF,CAAC;QAED,IAAI,UAAU,GAAG,KAAK,CAAA;QACtB,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;YACzC,MAAM,MAAM,GAAG,IAAA,4BAAY,EAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;YAClE,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YACpC,GAAG,CAAC,IAAI,CAAC,6BAA6B,KAAK,EAAE,CAAC,CAAA;YAC9C,UAAU,GAAG,UAAU,IAAI,KAAK,CAAA;QAClC,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,GAAG,CAAC,IAAI,CAAC,kDAAkD,CAAC,EAAE,CAAC,CAAA;QACjE,CAAC;QAED,UAAU,GAAG,UAAU,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,SAAS,CAAA;QAEhE,2HAA2H;QAC3H,MAAM,OAAO,GAAG,CAAC,IAA4B,EAAE,EAAE,WAAC,OAAA,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAI,MAAA,IAAI,CAAC,IAAI,CAAC,GAAG,0CAAE,QAAQ,CAAC,OAAO,CAAC,CAAA,CAAA,EAAA,CAAA;QACzH,IAAI,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACtC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;QAC5D,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;QAC9C,CAAC;QAED,MAAM,WAAW,GAAG,IAAA,mBAAQ,EAAC,KAAK,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;QAE1D,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;YACxB,MAAM,IAAA,+BAAQ,EAAC,0BAA0B,IAAA,wCAAiB,EAAC,KAAK,CAAC,EAAE,EAAE,gCAAgC,CAAC,CAAA;QACxG,CAAC;QAED,MAAM,QAAQ,GAAG,qBAAqB,CAAC,qBAAqB,CAAC,QAAQ,CAAA;QACrE,MAAM,6BAA6B,GAAG,YAAY,CAAA;QAElD,OAAO,IAAI,CAAC,eAAe,CAAC;YAC1B,aAAa,EAAE,KAAK;YACpB,QAAQ,EAAE,WAAW;YACrB,qBAAqB;YACrB,IAAI,EAAE,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,EAAE;gBAC/C,MAAM,oBAAoB,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAuB,CAAC,QAAQ,EAAE,6BAA6B,CAAC,CAAA;gBAC5G,MAAM,uBAAuB,GAAG,GAAG,EAAE;oBACnC,IAAI,CAAC,IAAA,yBAAc,EAAC,oBAAoB,CAAC,EAAE,CAAC;wBAC1C,GAAG,CAAC,IAAI,CAAC,wHAAwH,CAAC,CAAA;wBAClI,OAAO,KAAK,CAAA;oBACd,CAAC;oBACD,OAAO,CAAC,qBAAqB,CAAC,2BAA2B,CAAA;gBAC3D,CAAC,CAAA;gBACD,IAAI,0BAA0B,GAAG,IAAI,CAAA;gBACrC,IAAI,uBAAuB,EAAE,EAAE,CAAC;oBAC9B,0BAA0B,GAAG,MAAM,IAAI,CAAC,6BAA6B,CAAC,WAAW,EAAE,qBAAqB,EAAE,eAAe,EAAE,QAAQ,EAAE,6BAA6B,CAAC,CAAA;gBACrK,CAAC;gBAED,IAAI,0BAA0B,EAAE,CAAC;oBAC/B,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,eAAe,CAAC,CAAA;gBACrF,CAAC;YACH,CAAC;YACD,IAAI,EAAE,KAAK,EAAC,KAAK,EAAC,EAAE;gBAClB,IAAI,CAAC,qBAAqB,CAAC,2BAA2B,EAAE,CAAC;oBACvD,IAAI,CAAC;wBACH,MAAM,oBAAoB,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAuB,CAAC,QAAQ,EAAE,6BAA6B,CAAC,CAAA;wBAC5G,MAAM,IAAA,mBAAQ,EAAC,KAAK,CAAC,cAAc,EAAE,oBAAoB,CAAC,CAAA;oBAC5D,CAAC;oBAAC,OAAO,KAAU,EAAE,CAAC;wBACpB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,sEAAsE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;oBAC1G,CAAC;gBACH,CAAC;gBACD,OAAO,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;YAClD,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,WAAmC,EAAE,KAA4B;;QAC9F,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,CAAA;QAC3C,MAAM,cAAc,GAAG,MAAA,WAAW,CAAC,IAAI,CAAC,IAAI,mCAAI,CAAC,MAAM,IAAA,eAAI,EAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAA;QAEjF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAA;QACxB,MAAM,UAAU,GAAG,eAAe,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;QACxD,IAAI,CAAC,mBAAmB,EAAE,CAAA;QAC1B,IAAI,CAAC,KAAK,CAAC,kDAAkD,UAAU,GAAG,CAAC,CAAA;QAC3E,IAAI,CAAC,MAAM,GAAG,IAAA,mBAAY,GAAE,CAAA;QAC5B,IAAI,CAAC,KAAK,CAAC,oDAAoD,UAAU,GAAG,CAAC,CAAA;QAC7E,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAC3B,GAAG,CAAC,IAAI,CAAC,mDAAmD,UAAU,GAAG,CAAC,CAAA;QAC5E,CAAC,CAAC,CAAA;QAEF,sEAAsE;QACtE,MAAM,YAAY,GAAG,CAAC,CAAS,EAAU,EAAE;YACzC,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,CAAA;YAC3B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAChC,OAAO,OAAO,CAAA;YAChB,CAAC;YACD,OAAO,oBAAoB,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,EAAE,CAAA;QAC5C,CAAC,CAAA;QAED,OAAO,MAAM,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1D,MAAM,IAAI,GAAG,IAAA,oBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;YACvF,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,IAAI,EAAE,EAAE,OAAO,CAAC,CAAA;YAE5D,wBAAwB;YACxB,MAAM,OAAO,GAAG,IAAI,IAAA,oBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAA;YACzD,IAAI,CAAC,MAAO,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAAwB,EAAE,QAAwB,EAAE,EAAE;gBAChF,MAAM,UAAU,GAAG,OAAO,CAAC,GAAI,CAAA;gBAC/B,GAAG,CAAC,IAAI,CAAC,GAAG,UAAU,YAAY,CAAC,CAAA;gBACnC,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;oBACvB,8BAA8B;oBAC9B,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;wBAC7F,QAAQ,CAAC,UAAU,GAAG,GAAG,CAAA;wBACzB,QAAQ,CAAC,aAAa,GAAG,oCAAoC,CAAA;wBAC7D,QAAQ,CAAC,GAAG,EAAE,CAAA;wBACd,GAAG,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAA;wBACnC,OAAM;oBACR,CAAC;oBAED,0BAA0B;oBAC1B,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;oBACrE,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;oBAC9E,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;oBACnD,IAAI,QAAQ,KAAK,aAAa,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;wBACpD,QAAQ,CAAC,UAAU,GAAG,GAAG,CAAA;wBACzB,QAAQ,CAAC,aAAa,GAAG,oCAAoC,CAAA;wBAC7D,QAAQ,CAAC,GAAG,EAAE,CAAA;wBACd,GAAG,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAA;wBAC/C,OAAM;oBACR,CAAC;oBAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,YAAY,CAAC,IAAI,CAAC,MAAO,CAAC,GAAG,OAAO,KAAK,CAAC,CAAA;oBAChF,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;oBAC9F,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;oBAClB,OAAM;gBACR,CAAC;gBAED,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;oBACpC,GAAG,CAAC,IAAI,CAAC,GAAG,UAAU,+BAA+B,CAAC,CAAA;oBACtD,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;oBACvB,QAAQ,CAAC,GAAG,EAAE,CAAA;oBACd,OAAM;gBACR,CAAC;gBAED,GAAG,CAAC,IAAI,CAAC,GAAG,OAAO,oCAAoC,cAAc,EAAE,CAAC,CAAA;gBAExE,IAAI,aAAa,GAAG,KAAK,CAAA;gBACzB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;oBACzB,IAAI,CAAC,aAAa,EAAE,CAAC;wBACnB,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;wBAClD,OAAO,CAAC,EAAE,CAAC,CAAA;oBACb,CAAC;gBACH,CAAC,CAAC,CAAA;gBAEF,MAAM,UAAU,GAAG,IAAA,qBAAgB,EAAC,cAAc,CAAC,CAAA;gBACnD,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;oBAC7B,IAAI,CAAC;wBACH,QAAQ,CAAC,GAAG,EAAE,CAAA;oBAChB,CAAC;oBAAC,OAAO,CAAM,EAAE,CAAC;wBAChB,GAAG,CAAC,IAAI,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAA;oBACvC,CAAC;oBACD,aAAa,GAAG,IAAI,CAAA;oBACpB,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;oBAClD,MAAM,CAAC,IAAI,KAAK,CAAC,gBAAgB,cAAc,MAAM,KAAK,EAAE,CAAC,CAAC,CAAA;gBAChE,CAAC,CAAC,CAAA;gBAEF,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE;oBACtB,cAAc,EAAE,iBAAiB;oBACjC,gBAAgB,EAAE,cAAc;iBACjC,CAAC,CAAA;gBACF,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YAC3B,CAAC,CAAC,CAAA;YAEF,IAAI,CAAC,KAAK,CAAC,+DAA+D,UAAU,GAAG,CAAC,CAAA;YAExF,IAAI,CAAC,MAAO,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE;gBACvC,IAAI,CAAC,KAAK,CAAC,8DAA8D,YAAY,CAAC,IAAI,CAAC,MAAO,CAAC,KAAK,UAAU,GAAG,CAAC,CAAA;gBACtH,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC;oBAC5B,GAAG,EAAE,YAAY,CAAC,IAAI,CAAC,MAAO,CAAC;oBAC/B,OAAO,EAAE;wBACP,eAAe,EAAE,UAAU;wBAC3B,aAAa,EAAE,SAAS,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;qBACtD;iBACF,CAAC,CAAA;gBAEF,uEAAuE;gBACvE,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAA;gBAEpC,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;oBAC9B,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;oBACxC,sEAAsE;oBACtE,IAAI,CAAC,aAAa,CAAC,eAAe,EAAE,CAAA;gBACtC,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,EAAE,CAAC,CAAA;gBACb,CAAC;YACH,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,sBAAsB;QAC5B,IAAI,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAChC,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,CAAA;QACrC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;QACjB,CAAC;QACD,IAAI,CAAC,mBAAmB,EAAE,CAAA;IAC5B,CAAC;IAED,cAAc;QACZ,IAAI,IAAI,CAAC,wBAAwB,EAAE,CAAC;YAClC,4DAA4D;YAC5D,IAAI,CAAC,sBAAsB,EAAE,CAAA;QAC/B,CAAC;aAAM,CAAC;YACN,sDAAsD;YACtD,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC,CAAA;YAE/E,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAC/B;;;mBAGG;gBACH,IAAI,CAAC,aAAa,CAAC,eAAe,EAAE,CAAA;YACtC,CAAC;QACH,CAAC;IACH,CAAC;CACF;AA5QD,gCA4QC","sourcesContent":["import { AllPublishOptions, newError, safeStringifyJson } from \"builder-util-runtime\"\nimport { pathExistsSync, stat, copyFile } from \"fs-extra\"\nimport { createReadStream } from \"fs\"\nimport * as path from \"path\"\nimport { createServer, IncomingMessage, Server, ServerResponse } from \"http\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { AppUpdater, DownloadUpdateOptions } from \"./AppUpdater\"\nimport { ResolvedUpdateFileInfo } from \"./main\"\nimport { UpdateDownloadedEvent } from \"./types\"\nimport { findFile } from \"./providers/Provider\"\nimport AutoUpdater = Electron.AutoUpdater\nimport { execFileSync } from \"child_process\"\nimport { randomBytes } from \"crypto\"\n\nexport class MacUpdater extends AppUpdater {\n  private readonly nativeUpdater: AutoUpdater = require(\"electron\").autoUpdater\n\n  private squirrelDownloadedUpdate = false\n\n  private server?: Server\n\n  constructor(options?: AllPublishOptions, app?: AppAdapter) {\n    super(options, app)\n\n    this.nativeUpdater.on(\"error\", it => {\n      this._logger.warn(it)\n      this.emit(\"error\", it)\n    })\n    this.nativeUpdater.on(\"update-downloaded\", () => {\n      this.squirrelDownloadedUpdate = true\n      this.debug(\"nativeUpdater.update-downloaded\")\n    })\n  }\n\n  private debug(message: string): void {\n    if (this._logger.debug != null) {\n      this._logger.debug(message)\n    }\n  }\n\n  private closeServerIfExists() {\n    if (this.server) {\n      this.debug(\"Closing proxy server\")\n      this.server.close(err => {\n        if (err) {\n          this.debug(\"proxy server wasn't already open, probably attempted closing again as a safety check before quit\")\n        }\n      })\n    }\n  }\n\n  protected async doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n    let files = downloadUpdateOptions.updateInfoAndProvider.provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info)\n\n    const log = this._logger\n\n    // detect if we are running inside Rosetta emulation\n    const sysctlRosettaInfoKey = \"sysctl.proc_translated\"\n    let isRosetta = false\n    try {\n      this.debug(\"Checking for macOS Rosetta environment\")\n      const result = execFileSync(\"sysctl\", [sysctlRosettaInfoKey], { encoding: \"utf8\" })\n      isRosetta = result.includes(`${sysctlRosettaInfoKey}: 1`)\n      log.info(`Checked for macOS Rosetta environment (isRosetta=${isRosetta})`)\n    } catch (e: any) {\n      log.warn(`sysctl shell command to check for macOS Rosetta environment failed: ${e}`)\n    }\n\n    let isArm64Mac = false\n    try {\n      this.debug(\"Checking for arm64 in uname\")\n      const result = execFileSync(\"uname\", [\"-a\"], { encoding: \"utf8\" })\n      const isArm = result.includes(\"ARM\")\n      log.info(`Checked 'uname -a': arm64=${isArm}`)\n      isArm64Mac = isArm64Mac || isArm\n    } catch (e: any) {\n      log.warn(`uname shell command to check for arm64 failed: ${e}`)\n    }\n\n    isArm64Mac = isArm64Mac || process.arch === \"arm64\" || isRosetta\n\n    // allow arm64 macs to install universal or rosetta2(x64) - https://github.com/electron-userland/electron-builder/pull/5524\n    const isArm64 = (file: ResolvedUpdateFileInfo) => file.url.pathname.includes(\"arm64\") || file.info.url?.includes(\"arm64\")\n    if (isArm64Mac && files.some(isArm64)) {\n      files = files.filter(file => isArm64Mac === isArm64(file))\n    } else {\n      files = files.filter(file => !isArm64(file))\n    }\n\n    const zipFileInfo = findFile(files, \"zip\", [\"pkg\", \"dmg\"])\n\n    if (zipFileInfo == null) {\n      throw newError(`ZIP file not provided: ${safeStringifyJson(files)}`, \"ERR_UPDATER_ZIP_FILE_NOT_FOUND\")\n    }\n\n    const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n    const CURRENT_MAC_APP_ZIP_FILE_NAME = \"update.zip\"\n\n    return this.executeDownload({\n      fileExtension: \"zip\",\n      fileInfo: zipFileInfo,\n      downloadUpdateOptions,\n      task: async (destinationFile, downloadOptions) => {\n        const cachedUpdateFilePath = path.join(this.downloadedUpdateHelper!.cacheDir, CURRENT_MAC_APP_ZIP_FILE_NAME)\n        const canDifferentialDownload = () => {\n          if (!pathExistsSync(cachedUpdateFilePath)) {\n            log.info(\"Unable to locate previous update.zip for differential download (is this first install?), falling back to full download\")\n            return false\n          }\n          return !downloadUpdateOptions.disableDifferentialDownload\n        }\n        let differentialDownloadFailed = true\n        if (canDifferentialDownload()) {\n          differentialDownloadFailed = await this.differentialDownloadInstaller(zipFileInfo, downloadUpdateOptions, destinationFile, provider, CURRENT_MAC_APP_ZIP_FILE_NAME)\n        }\n\n        if (differentialDownloadFailed) {\n          await this.httpExecutor.download(zipFileInfo.url, destinationFile, downloadOptions)\n        }\n      },\n      done: async event => {\n        if (!downloadUpdateOptions.disableDifferentialDownload) {\n          try {\n            const cachedUpdateFilePath = path.join(this.downloadedUpdateHelper!.cacheDir, CURRENT_MAC_APP_ZIP_FILE_NAME)\n            await copyFile(event.downloadedFile, cachedUpdateFilePath)\n          } catch (error: any) {\n            this._logger.warn(`Unable to copy file for caching for future differential downloads: ${error.message}`)\n          }\n        }\n        return this.updateDownloaded(zipFileInfo, event)\n      },\n    })\n  }\n\n  private async updateDownloaded(zipFileInfo: ResolvedUpdateFileInfo, event: UpdateDownloadedEvent): Promise<Array<string>> {\n    const downloadedFile = event.downloadedFile\n    const updateFileSize = zipFileInfo.info.size ?? (await stat(downloadedFile)).size\n\n    const log = this._logger\n    const logContext = `fileToProxy=${zipFileInfo.url.href}`\n    this.closeServerIfExists()\n    this.debug(`Creating proxy server for native Squirrel.Mac (${logContext})`)\n    this.server = createServer()\n    this.debug(`Proxy server for native Squirrel.Mac is created (${logContext})`)\n    this.server.on(\"close\", () => {\n      log.info(`Proxy server for native Squirrel.Mac is closed (${logContext})`)\n    })\n\n    // must be called after server is listening, otherwise address is null\n    const getServerUrl = (s: Server): string => {\n      const address = s.address()\n      if (typeof address === \"string\") {\n        return address\n      }\n      return `http://127.0.0.1:${address?.port}`\n    }\n\n    return await new Promise<Array<string>>((resolve, reject) => {\n      const pass = randomBytes(64).toString(\"base64\").replace(/\\//g, \"_\").replace(/\\+/g, \"-\")\n      const authInfo = Buffer.from(`autoupdater:${pass}`, \"ascii\")\n\n      // insecure random is ok\n      const fileUrl = `/${randomBytes(64).toString(\"hex\")}.zip`\n      this.server!.on(\"request\", (request: IncomingMessage, response: ServerResponse) => {\n        const requestUrl = request.url!\n        log.info(`${requestUrl} requested`)\n        if (requestUrl === \"/\") {\n          // check for basic auth header\n          if (!request.headers.authorization || request.headers.authorization.indexOf(\"Basic \") === -1) {\n            response.statusCode = 401\n            response.statusMessage = \"Invalid Authentication Credentials\"\n            response.end()\n            log.warn(\"No authenthication info\")\n            return\n          }\n\n          // verify auth credentials\n          const base64Credentials = request.headers.authorization.split(\" \")[1]\n          const credentials = Buffer.from(base64Credentials, \"base64\").toString(\"ascii\")\n          const [username, password] = credentials.split(\":\")\n          if (username !== \"autoupdater\" || password !== pass) {\n            response.statusCode = 401\n            response.statusMessage = \"Invalid Authentication Credentials\"\n            response.end()\n            log.warn(\"Invalid authenthication credentials\")\n            return\n          }\n\n          const data = Buffer.from(`{ \"url\": \"${getServerUrl(this.server!)}${fileUrl}\" }`)\n          response.writeHead(200, { \"Content-Type\": \"application/json\", \"Content-Length\": data.length })\n          response.end(data)\n          return\n        }\n\n        if (!requestUrl.startsWith(fileUrl)) {\n          log.warn(`${requestUrl} requested, but not supported`)\n          response.writeHead(404)\n          response.end()\n          return\n        }\n\n        log.info(`${fileUrl} requested by Squirrel.Mac, pipe ${downloadedFile}`)\n\n        let errorOccurred = false\n        response.on(\"finish\", () => {\n          if (!errorOccurred) {\n            this.nativeUpdater.removeListener(\"error\", reject)\n            resolve([])\n          }\n        })\n\n        const readStream = createReadStream(downloadedFile)\n        readStream.on(\"error\", error => {\n          try {\n            response.end()\n          } catch (e: any) {\n            log.warn(`cannot end response: ${e}`)\n          }\n          errorOccurred = true\n          this.nativeUpdater.removeListener(\"error\", reject)\n          reject(new Error(`Cannot pipe \"${downloadedFile}\": ${error}`))\n        })\n\n        response.writeHead(200, {\n          \"Content-Type\": \"application/zip\",\n          \"Content-Length\": updateFileSize,\n        })\n        readStream.pipe(response)\n      })\n\n      this.debug(`Proxy server for native Squirrel.Mac is starting to listen (${logContext})`)\n\n      this.server!.listen(0, \"127.0.0.1\", () => {\n        this.debug(`Proxy server for native Squirrel.Mac is listening (address=${getServerUrl(this.server!)}, ${logContext})`)\n        this.nativeUpdater.setFeedURL({\n          url: getServerUrl(this.server!),\n          headers: {\n            \"Cache-Control\": \"no-cache\",\n            Authorization: `Basic ${authInfo.toString(\"base64\")}`,\n          },\n        })\n\n        // The update has been downloaded and is ready to be served to Squirrel\n        this.dispatchUpdateDownloaded(event)\n\n        if (this.autoInstallOnAppQuit) {\n          this.nativeUpdater.once(\"error\", reject)\n          // This will trigger fetching and installing the file on Squirrel side\n          this.nativeUpdater.checkForUpdates()\n        } else {\n          resolve([])\n        }\n      })\n    })\n  }\n\n  private handleUpdateDownloaded() {\n    if (this.autoRunAppAfterInstall) {\n      this.nativeUpdater.quitAndInstall()\n    } else {\n      this.app.quit()\n    }\n    this.closeServerIfExists()\n  }\n\n  quitAndInstall(): void {\n    if (this.squirrelDownloadedUpdate) {\n      // update already fetched by Squirrel, it's ready to install\n      this.handleUpdateDownloaded()\n    } else {\n      // Quit and install as soon as Squirrel get the update\n      this.nativeUpdater.on(\"update-downloaded\", () => this.handleUpdateDownloaded())\n\n      if (!this.autoInstallOnAppQuit) {\n        /**\n         * If this was not `true` previously then MacUpdater.doDownloadUpdate()\n         * would not actually initiate the downloading by electron's autoUpdater\n         */\n        this.nativeUpdater.checkForUpdates()\n      }\n    }\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NsisUpdater = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const path = require("path");
const BaseUpdater_1 = require("./BaseUpdater");
const FileWithEmbeddedBlockMapDifferentialDownloader_1 = require("./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader");
const types_1 = require("./types");
const Provider_1 = require("./providers/Provider");
const fs_extra_1 = require("fs-extra");
const windowsExecutableCodeSignatureVerifier_1 = require("./windowsExecutableCodeSignatureVerifier");
const url_1 = require("url");
class NsisUpdater extends BaseUpdater_1.BaseUpdater {
    constructor(options, app) {
        super(options, app);
        this._verifyUpdateCodeSignature = (publisherNames, unescapedTempUpdateFile) => (0, windowsExecutableCodeSignatureVerifier_1.verifySignature)(publisherNames, unescapedTempUpdateFile, this._logger);
    }
    /**
     * The verifyUpdateCodeSignature. You can pass [win-verify-signature](https://github.com/beyondkmp/win-verify-trust) or another custom verify function: ` (publisherName: string[], path: string) => Promise<string | null>`.
     * The default verify function uses [windowsExecutableCodeSignatureVerifier](https://github.com/electron-userland/electron-builder/blob/master/packages/electron-updater/src/windowsExecutableCodeSignatureVerifier.ts)
     */
    get verifyUpdateCodeSignature() {
        return this._verifyUpdateCodeSignature;
    }
    set verifyUpdateCodeSignature(value) {
        if (value) {
            this._verifyUpdateCodeSignature = value;
        }
    }
    /*** @private */
    doDownloadUpdate(downloadUpdateOptions) {
        const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
        const fileInfo = (0, Provider_1.findFile)(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), "exe");
        return this.executeDownload({
            fileExtension: "exe",
            downloadUpdateOptions,
            fileInfo,
            task: async (destinationFile, downloadOptions, packageFile, removeTempDirIfAny) => {
                const packageInfo = fileInfo.packageInfo;
                const isWebInstaller = packageInfo != null && packageFile != null;
                if (isWebInstaller && downloadUpdateOptions.disableWebInstaller) {
                    throw (0, builder_util_runtime_1.newError)(`Unable to download new version ${downloadUpdateOptions.updateInfoAndProvider.info.version}. Web Installers are disabled`, "ERR_UPDATER_WEB_INSTALLER_DISABLED");
                }
                if (!isWebInstaller && !downloadUpdateOptions.disableWebInstaller) {
                    this._logger.warn("disableWebInstaller is set to false, you should set it to true if you do not plan on using a web installer. This will default to true in a future version.");
                }
                if (isWebInstaller ||
                    downloadUpdateOptions.disableDifferentialDownload ||
                    (await this.differentialDownloadInstaller(fileInfo, downloadUpdateOptions, destinationFile, provider, builder_util_runtime_1.CURRENT_APP_INSTALLER_FILE_NAME))) {
                    await this.httpExecutor.download(fileInfo.url, destinationFile, downloadOptions);
                }
                const signatureVerificationStatus = await this.verifySignature(destinationFile);
                if (signatureVerificationStatus != null) {
                    await removeTempDirIfAny();
                    // noinspection ThrowInsideFinallyBlockJS
                    throw (0, builder_util_runtime_1.newError)(`New version ${downloadUpdateOptions.updateInfoAndProvider.info.version} is not signed by the application owner: ${signatureVerificationStatus}`, "ERR_UPDATER_INVALID_SIGNATURE");
                }
                if (isWebInstaller) {
                    if (await this.differentialDownloadWebPackage(downloadUpdateOptions, packageInfo, packageFile, provider)) {
                        try {
                            await this.httpExecutor.download(new url_1.URL(packageInfo.path), packageFile, {
                                headers: downloadUpdateOptions.requestHeaders,
                                cancellationToken: downloadUpdateOptions.cancellationToken,
                                sha512: packageInfo.sha512,
                            });
                        }
                        catch (e) {
                            try {
                                await (0, fs_extra_1.unlink)(packageFile);
                            }
                            catch (_ignored) {
                                // ignore
                            }
                            throw e;
                        }
                    }
                }
            },
        });
    }
    // $certificateInfo = (Get-AuthenticodeSignature 'xxx\yyy.exe'
    // | where {$_.Status.Equals([System.Management.Automation.SignatureStatus]::Valid) -and $_.SignerCertificate.Subject.Contains("CN=siemens.com")})
    // | Out-String ; if ($certificateInfo) { exit 0 } else { exit 1 }
    async verifySignature(tempUpdateFile) {
        let publisherName;
        try {
            publisherName = (await this.configOnDisk.value).publisherName;
            if (publisherName == null) {
                return null;
            }
        }
        catch (e) {
            if (e.code === "ENOENT") {
                // no app-update.yml
                return null;
            }
            throw e;
        }
        return await this._verifyUpdateCodeSignature(Array.isArray(publisherName) ? publisherName : [publisherName], tempUpdateFile);
    }
    doInstall(options) {
        const installerPath = this.installerPath;
        if (installerPath == null) {
            this.dispatchError(new Error("No valid update available, can't quit and install"));
            return false;
        }
        const args = ["--updated"];
        if (options.isSilent) {
            args.push("/S");
        }
        if (options.isForceRunAfter) {
            args.push("--force-run");
        }
        if (this.installDirectory) {
            // maybe check if folder exists
            args.push(`/D=${this.installDirectory}`);
        }
        const packagePath = this.downloadedUpdateHelper == null ? null : this.downloadedUpdateHelper.packageFile;
        if (packagePath != null) {
            // only = form is supported
            args.push(`--package-file=${packagePath}`);
        }
        const callUsingElevation = () => {
            this.spawnLog(path.join(process.resourcesPath, "elevate.exe"), [installerPath].concat(args)).catch(e => this.dispatchError(e));
        };
        if (options.isAdminRightsRequired) {
            this._logger.info("isAdminRightsRequired is set to true, run installer using elevate.exe");
            callUsingElevation();
            return true;
        }
        this.spawnLog(installerPath, args).catch((e) => {
            // https://github.com/electron-userland/electron-builder/issues/1129
            // Node 8 sends errors: https://nodejs.org/dist/latest-v8.x/docs/api/errors.html#errors_common_system_errors
            const errorCode = e.code;
            this._logger.info(`Cannot run installer: error code: ${errorCode}, error message: "${e.message}", will be executed again using elevate if EACCES, and will try to use electron.shell.openItem if ENOENT`);
            if (errorCode === "UNKNOWN" || errorCode === "EACCES") {
                callUsingElevation();
            }
            else if (errorCode === "ENOENT") {
                require("electron")
                    .shell.openPath(installerPath)
                    .catch((err) => this.dispatchError(err));
            }
            else {
                this.dispatchError(e);
            }
        });
        return true;
    }
    async differentialDownloadWebPackage(downloadUpdateOptions, packageInfo, packagePath, provider) {
        if (packageInfo.blockMapSize == null) {
            return true;
        }
        try {
            const downloadOptions = {
                newUrl: new url_1.URL(packageInfo.path),
                oldFile: path.join(this.downloadedUpdateHelper.cacheDir, builder_util_runtime_1.CURRENT_APP_PACKAGE_FILE_NAME),
                logger: this._logger,
                newFile: packagePath,
                requestHeaders: this.requestHeaders,
                isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,
                cancellationToken: downloadUpdateOptions.cancellationToken,
            };
            if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
                downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
            }
            await new FileWithEmbeddedBlockMapDifferentialDownloader_1.FileWithEmbeddedBlockMapDifferentialDownloader(packageInfo, this.httpExecutor, downloadOptions).download();
        }
        catch (e) {
            this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`);
            // during test (developer machine mac or linux) we must throw error
            return process.platform === "win32";
        }
        return false;
    }
}
exports.NsisUpdater = NsisUpdater;
//# sourceMappingURL=NsisUpdater.js.map{"version":3,"file":"NsisUpdater.js","sourceRoot":"","sources":["../src/NsisUpdater.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllPublishOptions, newError, PackageFileInfo, CURRENT_APP_INSTALLER_FILE_NAME, CURRENT_APP_PACKAGE_FILE_NAME } from \"builder-util-runtime\"\nimport * as path from \"path\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { DownloadUpdateOptions } from \"./AppUpdater\"\nimport { BaseUpdater, InstallOptions } from \"./BaseUpdater\"\nimport { DifferentialDownloaderOptions } from \"./differentialDownloader/DifferentialDownloader\"\nimport { FileWithEmbeddedBlockMapDifferentialDownloader } from \"./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader\"\nimport { DOWNLOAD_PROGRESS } from \"./types\"\nimport { VerifyUpdateCodeSignature } from \"./main\"\nimport { findFile, Provider } from \"./providers/Provider\"\nimport { unlink } from \"fs-extra\"\nimport { verifySignature } from \"./windowsExecutableCodeSignatureVerifier\"\nimport { URL } from \"url\"\n\nexport class NsisUpdater extends BaseUpdater {\n  /**\n   * Specify custom install directory path\n   *\n   */\n  installDirectory?: string\n\n  constructor(options?: AllPublishOptions | null, app?: AppAdapter) {\n    super(options, app)\n  }\n\n  protected _verifyUpdateCodeSignature: VerifyUpdateCodeSignature = (publisherNames: Array<string>, unescapedTempUpdateFile: string) =>\n    verifySignature(publisherNames, unescapedTempUpdateFile, this._logger)\n\n  /**\n   * The verifyUpdateCodeSignature. You can pass [win-verify-signature](https://github.com/beyondkmp/win-verify-trust) or another custom verify function: ` (publisherName: string[], path: string) => Promise<string | null>`.\n   * The default verify function uses [windowsExecutableCodeSignatureVerifier](https://github.com/electron-userland/electron-builder/blob/master/packages/electron-updater/src/windowsExecutableCodeSignatureVerifier.ts)\n   */\n  get verifyUpdateCodeSignature(): VerifyUpdateCodeSignature {\n    return this._verifyUpdateCodeSignature\n  }\n\n  set verifyUpdateCodeSignature(value: VerifyUpdateCodeSignature) {\n    if (value) {\n      this._verifyUpdateCodeSignature = value\n    }\n  }\n\n  /*** @private */\n  protected doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n    const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n    const fileInfo = findFile(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), \"exe\")!\n    return this.executeDownload({\n      fileExtension: \"exe\",\n      downloadUpdateOptions,\n      fileInfo,\n      task: async (destinationFile, downloadOptions, packageFile, removeTempDirIfAny) => {\n        const packageInfo = fileInfo.packageInfo\n        const isWebInstaller = packageInfo != null && packageFile != null\n        if (isWebInstaller && downloadUpdateOptions.disableWebInstaller) {\n          throw newError(\n            `Unable to download new version ${downloadUpdateOptions.updateInfoAndProvider.info.version}. Web Installers are disabled`,\n            \"ERR_UPDATER_WEB_INSTALLER_DISABLED\"\n          )\n        }\n        if (!isWebInstaller && !downloadUpdateOptions.disableWebInstaller) {\n          this._logger.warn(\n            \"disableWebInstaller is set to false, you should set it to true if you do not plan on using a web installer. This will default to true in a future version.\"\n          )\n        }\n        if (\n          isWebInstaller ||\n          downloadUpdateOptions.disableDifferentialDownload ||\n          (await this.differentialDownloadInstaller(fileInfo, downloadUpdateOptions, destinationFile, provider, CURRENT_APP_INSTALLER_FILE_NAME))\n        ) {\n          await this.httpExecutor.download(fileInfo.url, destinationFile, downloadOptions)\n        }\n\n        const signatureVerificationStatus = await this.verifySignature(destinationFile)\n        if (signatureVerificationStatus != null) {\n          await removeTempDirIfAny()\n          // noinspection ThrowInsideFinallyBlockJS\n          throw newError(\n            `New version ${downloadUpdateOptions.updateInfoAndProvider.info.version} is not signed by the application owner: ${signatureVerificationStatus}`,\n            \"ERR_UPDATER_INVALID_SIGNATURE\"\n          )\n        }\n\n        if (isWebInstaller) {\n          if (await this.differentialDownloadWebPackage(downloadUpdateOptions, packageInfo, packageFile, provider)) {\n            try {\n              await this.httpExecutor.download(new URL(packageInfo.path), packageFile, {\n                headers: downloadUpdateOptions.requestHeaders,\n                cancellationToken: downloadUpdateOptions.cancellationToken,\n                sha512: packageInfo.sha512,\n              })\n            } catch (e: any) {\n              try {\n                await unlink(packageFile)\n              } catch (_ignored) {\n                // ignore\n              }\n\n              throw e\n            }\n          }\n        }\n      },\n    })\n  }\n\n  // $certificateInfo = (Get-AuthenticodeSignature 'xxx\\yyy.exe'\n  // | where {$_.Status.Equals([System.Management.Automation.SignatureStatus]::Valid) -and $_.SignerCertificate.Subject.Contains(\"CN=siemens.com\")})\n  // | Out-String ; if ($certificateInfo) { exit 0 } else { exit 1 }\n  private async verifySignature(tempUpdateFile: string): Promise<string | null> {\n    let publisherName: Array<string> | string | null\n    try {\n      publisherName = (await this.configOnDisk.value).publisherName\n      if (publisherName == null) {\n        return null\n      }\n    } catch (e: any) {\n      if (e.code === \"ENOENT\") {\n        // no app-update.yml\n        return null\n      }\n      throw e\n    }\n    return await this._verifyUpdateCodeSignature(Array.isArray(publisherName) ? publisherName : [publisherName], tempUpdateFile)\n  }\n\n  protected doInstall(options: InstallOptions): boolean {\n    const installerPath = this.installerPath\n    if (installerPath == null) {\n      this.dispatchError(new Error(\"No valid update available, can't quit and install\"))\n      return false\n    }\n\n    const args = [\"--updated\"]\n    if (options.isSilent) {\n      args.push(\"/S\")\n    }\n\n    if (options.isForceRunAfter) {\n      args.push(\"--force-run\")\n    }\n\n    if (this.installDirectory) {\n      // maybe check if folder exists\n      args.push(`/D=${this.installDirectory}`)\n    }\n\n    const packagePath = this.downloadedUpdateHelper == null ? null : this.downloadedUpdateHelper.packageFile\n    if (packagePath != null) {\n      // only = form is supported\n      args.push(`--package-file=${packagePath}`)\n    }\n\n    const callUsingElevation = (): void => {\n      this.spawnLog(path.join(process.resourcesPath, \"elevate.exe\"), [installerPath].concat(args)).catch(e => this.dispatchError(e))\n    }\n\n    if (options.isAdminRightsRequired) {\n      this._logger.info(\"isAdminRightsRequired is set to true, run installer using elevate.exe\")\n      callUsingElevation()\n      return true\n    }\n\n    this.spawnLog(installerPath, args).catch((e: Error) => {\n      // https://github.com/electron-userland/electron-builder/issues/1129\n      // Node 8 sends errors: https://nodejs.org/dist/latest-v8.x/docs/api/errors.html#errors_common_system_errors\n      const errorCode = (e as NodeJS.ErrnoException).code\n      this._logger.info(\n        `Cannot run installer: error code: ${errorCode}, error message: \"${e.message}\", will be executed again using elevate if EACCES, and will try to use electron.shell.openItem if ENOENT`\n      )\n      if (errorCode === \"UNKNOWN\" || errorCode === \"EACCES\") {\n        callUsingElevation()\n      } else if (errorCode === \"ENOENT\") {\n        require(\"electron\")\n          .shell.openPath(installerPath)\n          .catch((err: Error) => this.dispatchError(err))\n      } else {\n        this.dispatchError(e)\n      }\n    })\n    return true\n  }\n\n  private async differentialDownloadWebPackage(\n    downloadUpdateOptions: DownloadUpdateOptions,\n    packageInfo: PackageFileInfo,\n    packagePath: string,\n    provider: Provider<any>\n  ): Promise<boolean> {\n    if (packageInfo.blockMapSize == null) {\n      return true\n    }\n\n    try {\n      const downloadOptions: DifferentialDownloaderOptions = {\n        newUrl: new URL(packageInfo.path),\n        oldFile: path.join(this.downloadedUpdateHelper!.cacheDir, CURRENT_APP_PACKAGE_FILE_NAME),\n        logger: this._logger,\n        newFile: packagePath,\n        requestHeaders: this.requestHeaders,\n        isUseMultipleRangeRequest: provider.isUseMultipleRangeRequest,\n        cancellationToken: downloadUpdateOptions.cancellationToken,\n      }\n\n      if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n        downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n      }\n\n      await new FileWithEmbeddedBlockMapDifferentialDownloader(packageInfo, this.httpExecutor, downloadOptions).download()\n    } catch (e: any) {\n      this._logger.error(`Cannot download differentially, fallback to full download: ${e.stack || e}`)\n      // during test (developer machine mac or linux) we must throw error\n      return process.platform === \"win32\"\n    }\n    return false\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PacmanUpdater = void 0;
const BaseUpdater_1 = require("./BaseUpdater");
const types_1 = require("./types");
const Provider_1 = require("./providers/Provider");
class PacmanUpdater extends BaseUpdater_1.BaseUpdater {
    constructor(options, app) {
        super(options, app);
    }
    /*** @private */
    doDownloadUpdate(downloadUpdateOptions) {
        const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
        const fileInfo = (0, Provider_1.findFile)(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), "pacman", ["AppImage", "deb", "rpm"]);
        return this.executeDownload({
            fileExtension: "pacman",
            fileInfo,
            downloadUpdateOptions,
            task: async (updateFile, downloadOptions) => {
                if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
                    downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
                }
                await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions);
            },
        });
    }
    get installerPath() {
        var _a, _b;
        return (_b = (_a = super.installerPath) === null || _a === void 0 ? void 0 : _a.replace(/ /g, "\\ ")) !== null && _b !== void 0 ? _b : null;
    }
    doInstall(options) {
        const sudo = this.wrapSudo();
        // pkexec doesn't want the command to be wrapped in " quotes
        const wrapper = /pkexec/i.test(sudo) ? "" : `"`;
        const installerPath = this.installerPath;
        if (installerPath == null) {
            this.dispatchError(new Error("No valid update available, can't quit and install"));
            return false;
        }
        const cmd = ["pacman", "-U", "--noconfirm", installerPath];
        this.spawnSyncLog(sudo, [`${wrapper}/bin/bash`, "-c", `'${cmd.join(" ")}'${wrapper}`]);
        if (options.isForceRunAfter) {
            this.app.relaunch();
        }
        return true;
    }
}
exports.PacmanUpdater = PacmanUpdater;
//# sourceMappingURL=PacmanUpdater.js.map{"version":3,"file":"PacmanUpdater.js","sourceRoot":"","sources":["../src/PacmanUpdater.ts"],"names":[],"mappings":";;;AAGA,+CAA2D;AAC3D,mCAA2C;AAC3C,mDAA+C;AAE/C,MAAa,aAAc,SAAQ,yBAAW;IAC5C,YAAY,OAAkC,EAAE,GAAgB;QAC9D,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;IACrB,CAAC;IAED,gBAAgB;IACN,gBAAgB,CAAC,qBAA4C;QACrE,MAAM,QAAQ,GAAG,qBAAqB,CAAC,qBAAqB,CAAC,QAAQ,CAAA;QACrE,MAAM,QAAQ,GAAG,IAAA,mBAAQ,EAAC,QAAQ,CAAC,YAAY,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,CAAE,CAAA;QACzI,OAAO,IAAI,CAAC,eAAe,CAAC;YAC1B,aAAa,EAAE,QAAQ;YACvB,QAAQ;YACR,qBAAqB;YACrB,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,EAAE;gBAC1C,IAAI,IAAI,CAAC,aAAa,CAAC,yBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC9C,eAAe,CAAC,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAiB,EAAE,EAAE,CAAC,CAAA;gBACrE,CAAC;gBACD,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,eAAe,CAAC,CAAA;YAC7E,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;IAED,IAAc,aAAa;;QACzB,OAAO,MAAA,MAAA,KAAK,CAAC,aAAa,0CAAE,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,mCAAI,IAAI,CAAA;IAC1D,CAAC;IAES,SAAS,CAAC,OAAuB;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;QAC5B,4DAA4D;QAC5D,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA;QAC/C,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAA;QACxC,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC,CAAA;YAClF,OAAO,KAAK,CAAA;QACd,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,aAAa,CAAC,CAAA;QAC1D,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,WAAW,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAA;QACtF,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAA;QACrB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;CACF;AA1CD,sCA0CC","sourcesContent":["import { AllPublishOptions } from \"builder-util-runtime\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { DownloadUpdateOptions } from \"./AppUpdater\"\nimport { BaseUpdater, InstallOptions } from \"./BaseUpdater\"\nimport { DOWNLOAD_PROGRESS } from \"./types\"\nimport { findFile } from \"./providers/Provider\"\n\nexport class PacmanUpdater extends BaseUpdater {\n  constructor(options?: AllPublishOptions | null, app?: AppAdapter) {\n    super(options, app)\n  }\n\n  /*** @private */\n  protected doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n    const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n    const fileInfo = findFile(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), \"pacman\", [\"AppImage\", \"deb\", \"rpm\"])!\n    return this.executeDownload({\n      fileExtension: \"pacman\",\n      fileInfo,\n      downloadUpdateOptions,\n      task: async (updateFile, downloadOptions) => {\n        if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n          downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n        }\n        await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions)\n      },\n    })\n  }\n\n  protected get installerPath(): string | null {\n    return super.installerPath?.replace(/ /g, \"\\\\ \") ?? null\n  }\n\n  protected doInstall(options: InstallOptions): boolean {\n    const sudo = this.wrapSudo()\n    // pkexec doesn't want the command to be wrapped in \" quotes\n    const wrapper = /pkexec/i.test(sudo) ? \"\" : `\"`\n    const installerPath = this.installerPath\n    if (installerPath == null) {\n      this.dispatchError(new Error(\"No valid update available, can't quit and install\"))\n      return false\n    }\n    const cmd = [\"pacman\", \"-U\", \"--noconfirm\", installerPath]\n    this.spawnSyncLog(sudo, [`${wrapper}/bin/bash`, \"-c\", `'${cmd.join(\" \")}'${wrapper}`])\n    if (options.isForceRunAfter) {\n      this.app.relaunch()\n    }\n    return true\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RpmUpdater = void 0;
const BaseUpdater_1 = require("./BaseUpdater");
const types_1 = require("./types");
const Provider_1 = require("./providers/Provider");
class RpmUpdater extends BaseUpdater_1.BaseUpdater {
    constructor(options, app) {
        super(options, app);
    }
    /*** @private */
    doDownloadUpdate(downloadUpdateOptions) {
        const provider = downloadUpdateOptions.updateInfoAndProvider.provider;
        const fileInfo = (0, Provider_1.findFile)(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), "rpm", ["AppImage", "deb", "pacman"]);
        return this.executeDownload({
            fileExtension: "rpm",
            fileInfo,
            downloadUpdateOptions,
            task: async (updateFile, downloadOptions) => {
                if (this.listenerCount(types_1.DOWNLOAD_PROGRESS) > 0) {
                    downloadOptions.onProgress = it => this.emit(types_1.DOWNLOAD_PROGRESS, it);
                }
                await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions);
            },
        });
    }
    get installerPath() {
        var _a, _b;
        return (_b = (_a = super.installerPath) === null || _a === void 0 ? void 0 : _a.replace(/ /g, "\\ ")) !== null && _b !== void 0 ? _b : null;
    }
    doInstall(options) {
        const sudo = this.wrapSudo();
        // pkexec doesn't want the command to be wrapped in " quotes
        const wrapper = /pkexec/i.test(sudo) ? "" : `"`;
        const packageManager = this.spawnSyncLog("which zypper");
        const installerPath = this.installerPath;
        if (installerPath == null) {
            this.dispatchError(new Error("No valid update available, can't quit and install"));
            return false;
        }
        let cmd;
        if (!packageManager) {
            const packageManager = this.spawnSyncLog("which dnf || which yum");
            cmd = [packageManager, "-y", "install", installerPath];
        }
        else {
            cmd = [packageManager, "--no-refresh", "install", "--allow-unsigned-rpm", "-y", "-f", installerPath];
        }
        this.spawnSyncLog(sudo, [`${wrapper}/bin/bash`, "-c", `'${cmd.join(" ")}'${wrapper}`]);
        if (options.isForceRunAfter) {
            this.app.relaunch();
        }
        return true;
    }
}
exports.RpmUpdater = RpmUpdater;
//# sourceMappingURL=RpmUpdater.js.map{"version":3,"file":"RpmUpdater.js","sourceRoot":"","sources":["../src/RpmUpdater.ts"],"names":[],"mappings":";;;AAGA,+CAA2D;AAC3D,mCAA2C;AAC3C,mDAA+C;AAE/C,MAAa,UAAW,SAAQ,yBAAW;IACzC,YAAY,OAAkC,EAAE,GAAgB;QAC9D,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;IACrB,CAAC;IAED,gBAAgB;IACN,gBAAgB,CAAC,qBAA4C;QACrE,MAAM,QAAQ,GAAG,qBAAqB,CAAC,qBAAqB,CAAC,QAAQ,CAAA;QACrE,MAAM,QAAQ,GAAG,IAAA,mBAAQ,EAAC,QAAQ,CAAC,YAAY,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAE,CAAA;QACzI,OAAO,IAAI,CAAC,eAAe,CAAC;YAC1B,aAAa,EAAE,KAAK;YACpB,QAAQ;YACR,qBAAqB;YACrB,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,EAAE;gBAC1C,IAAI,IAAI,CAAC,aAAa,CAAC,yBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC9C,eAAe,CAAC,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAiB,EAAE,EAAE,CAAC,CAAA;gBACrE,CAAC;gBACD,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,eAAe,CAAC,CAAA;YAC7E,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;IAED,IAAc,aAAa;;QACzB,OAAO,MAAA,MAAA,KAAK,CAAC,aAAa,0CAAE,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,mCAAI,IAAI,CAAA;IAC1D,CAAC;IAES,SAAS,CAAC,OAAuB;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;QAC5B,4DAA4D;QAC5D,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA;QAC/C,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,CAAA;QACxD,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAA;QACxC,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC,CAAA;YAClF,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,GAAa,CAAA;QACjB,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,CAAC,wBAAwB,CAAC,CAAA;YAClE,GAAG,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,CAAC,CAAA;QACxD,CAAC;aAAM,CAAC;YACN,GAAG,GAAG,CAAC,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,sBAAsB,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,CAAA;QACtG,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,WAAW,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAA;QACtF,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAA;QACrB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;CACF;AAjDD,gCAiDC","sourcesContent":["import { AllPublishOptions } from \"builder-util-runtime\"\nimport { AppAdapter } from \"./AppAdapter\"\nimport { DownloadUpdateOptions } from \"./AppUpdater\"\nimport { BaseUpdater, InstallOptions } from \"./BaseUpdater\"\nimport { DOWNLOAD_PROGRESS } from \"./types\"\nimport { findFile } from \"./providers/Provider\"\n\nexport class RpmUpdater extends BaseUpdater {\n  constructor(options?: AllPublishOptions | null, app?: AppAdapter) {\n    super(options, app)\n  }\n\n  /*** @private */\n  protected doDownloadUpdate(downloadUpdateOptions: DownloadUpdateOptions): Promise<Array<string>> {\n    const provider = downloadUpdateOptions.updateInfoAndProvider.provider\n    const fileInfo = findFile(provider.resolveFiles(downloadUpdateOptions.updateInfoAndProvider.info), \"rpm\", [\"AppImage\", \"deb\", \"pacman\"])!\n    return this.executeDownload({\n      fileExtension: \"rpm\",\n      fileInfo,\n      downloadUpdateOptions,\n      task: async (updateFile, downloadOptions) => {\n        if (this.listenerCount(DOWNLOAD_PROGRESS) > 0) {\n          downloadOptions.onProgress = it => this.emit(DOWNLOAD_PROGRESS, it)\n        }\n        await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions)\n      },\n    })\n  }\n\n  protected get installerPath(): string | null {\n    return super.installerPath?.replace(/ /g, \"\\\\ \") ?? null\n  }\n\n  protected doInstall(options: InstallOptions): boolean {\n    const sudo = this.wrapSudo()\n    // pkexec doesn't want the command to be wrapped in \" quotes\n    const wrapper = /pkexec/i.test(sudo) ? \"\" : `\"`\n    const packageManager = this.spawnSyncLog(\"which zypper\")\n    const installerPath = this.installerPath\n    if (installerPath == null) {\n      this.dispatchError(new Error(\"No valid update available, can't quit and install\"))\n      return false\n    }\n    let cmd: string[]\n    if (!packageManager) {\n      const packageManager = this.spawnSyncLog(\"which dnf || which yum\")\n      cmd = [packageManager, \"-y\", \"install\", installerPath]\n    } else {\n      cmd = [packageManager, \"--no-refresh\", \"install\", \"--allow-unsigned-rpm\", \"-y\", \"-f\", installerPath]\n    }\n    this.spawnSyncLog(sudo, [`${wrapper}/bin/bash`, \"-c\", `'${cmd.join(\" \")}'${wrapper}`])\n    if (options.isForceRunAfter) {\n      this.app.relaunch()\n    }\n    return true\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataSplitter = void 0;
exports.copyData = copyData;
const builder_util_runtime_1 = require("builder-util-runtime");
const fs_1 = require("fs");
const stream_1 = require("stream");
const downloadPlanBuilder_1 = require("./downloadPlanBuilder");
const DOUBLE_CRLF = Buffer.from("\r\n\r\n");
var ReadState;
(function (ReadState) {
    ReadState[ReadState["INIT"] = 0] = "INIT";
    ReadState[ReadState["HEADER"] = 1] = "HEADER";
    ReadState[ReadState["BODY"] = 2] = "BODY";
})(ReadState || (ReadState = {}));
function copyData(task, out, oldFileFd, reject, resolve) {
    const readStream = (0, fs_1.createReadStream)("", {
        fd: oldFileFd,
        autoClose: false,
        start: task.start,
        // end is inclusive
        end: task.end - 1,
    });
    readStream.on("error", reject);
    readStream.once("end", resolve);
    readStream.pipe(out, {
        end: false,
    });
}
class DataSplitter extends stream_1.Writable {
    constructor(out, options, partIndexToTaskIndex, boundary, partIndexToLength, finishHandler) {
        super();
        this.out = out;
        this.options = options;
        this.partIndexToTaskIndex = partIndexToTaskIndex;
        this.partIndexToLength = partIndexToLength;
        this.finishHandler = finishHandler;
        this.partIndex = -1;
        this.headerListBuffer = null;
        this.readState = ReadState.INIT;
        this.ignoreByteCount = 0;
        this.remainingPartDataCount = 0;
        this.actualPartLength = 0;
        this.boundaryLength = boundary.length + 4; /* size of \r\n-- */
        // first chunk doesn't start with \r\n
        this.ignoreByteCount = this.boundaryLength - 2;
    }
    get isFinished() {
        return this.partIndex === this.partIndexToLength.length;
    }
    // noinspection JSUnusedGlobalSymbols
    _write(data, encoding, callback) {
        if (this.isFinished) {
            console.error(`Trailing ignored data: ${data.length} bytes`);
            return;
        }
        this.handleData(data).then(callback).catch(callback);
    }
    async handleData(chunk) {
        let start = 0;
        if (this.ignoreByteCount !== 0 && this.remainingPartDataCount !== 0) {
            throw (0, builder_util_runtime_1.newError)("Internal error", "ERR_DATA_SPLITTER_BYTE_COUNT_MISMATCH");
        }
        if (this.ignoreByteCount > 0) {
            const toIgnore = Math.min(this.ignoreByteCount, chunk.length);
            this.ignoreByteCount -= toIgnore;
            start = toIgnore;
        }
        else if (this.remainingPartDataCount > 0) {
            const toRead = Math.min(this.remainingPartDataCount, chunk.length);
            this.remainingPartDataCount -= toRead;
            await this.processPartData(chunk, 0, toRead);
            start = toRead;
        }
        if (start === chunk.length) {
            return;
        }
        if (this.readState === ReadState.HEADER) {
            const headerListEnd = this.searchHeaderListEnd(chunk, start);
            if (headerListEnd === -1) {
                return;
            }
            start = headerListEnd;
            this.readState = ReadState.BODY;
            // header list is ignored, we don't need it
            this.headerListBuffer = null;
        }
        while (true) {
            if (this.readState === ReadState.BODY) {
                this.readState = ReadState.INIT;
            }
            else {
                this.partIndex++;
                let taskIndex = this.partIndexToTaskIndex.get(this.partIndex);
                if (taskIndex == null) {
                    if (this.isFinished) {
                        taskIndex = this.options.end;
                    }
                    else {
                        throw (0, builder_util_runtime_1.newError)("taskIndex is null", "ERR_DATA_SPLITTER_TASK_INDEX_IS_NULL");
                    }
                }
                const prevTaskIndex = this.partIndex === 0 ? this.options.start : this.partIndexToTaskIndex.get(this.partIndex - 1) + 1; /* prev part is download, next maybe copy */
                if (prevTaskIndex < taskIndex) {
                    await this.copyExistingData(prevTaskIndex, taskIndex);
                }
                else if (prevTaskIndex > taskIndex) {
                    throw (0, builder_util_runtime_1.newError)("prevTaskIndex must be < taskIndex", "ERR_DATA_SPLITTER_TASK_INDEX_ASSERT_FAILED");
                }
                if (this.isFinished) {
                    this.onPartEnd();
                    this.finishHandler();
                    return;
                }
                start = this.searchHeaderListEnd(chunk, start);
                if (start === -1) {
                    this.readState = ReadState.HEADER;
                    return;
                }
            }
            const partLength = this.partIndexToLength[this.partIndex];
            const end = start + partLength;
            const effectiveEnd = Math.min(end, chunk.length);
            await this.processPartStarted(chunk, start, effectiveEnd);
            this.remainingPartDataCount = partLength - (effectiveEnd - start);
            if (this.remainingPartDataCount > 0) {
                return;
            }
            start = end + this.boundaryLength;
            if (start >= chunk.length) {
                this.ignoreByteCount = this.boundaryLength - (chunk.length - end);
                return;
            }
        }
    }
    copyExistingData(index, end) {
        return new Promise((resolve, reject) => {
            const w = () => {
                if (index === end) {
                    resolve();
                    return;
                }
                const task = this.options.tasks[index];
                if (task.kind !== downloadPlanBuilder_1.OperationKind.COPY) {
                    reject(new Error("Task kind must be COPY"));
                    return;
                }
                copyData(task, this.out, this.options.oldFileFd, reject, () => {
                    index++;
                    w();
                });
            };
            w();
        });
    }
    searchHeaderListEnd(chunk, readOffset) {
        const headerListEnd = chunk.indexOf(DOUBLE_CRLF, readOffset);
        if (headerListEnd !== -1) {
            return headerListEnd + DOUBLE_CRLF.length;
        }
        // not all headers data were received, save to buffer
        const partialChunk = readOffset === 0 ? chunk : chunk.slice(readOffset);
        if (this.headerListBuffer == null) {
            this.headerListBuffer = partialChunk;
        }
        else {
            this.headerListBuffer = Buffer.concat([this.headerListBuffer, partialChunk]);
        }
        return -1;
    }
    onPartEnd() {
        const expectedLength = this.partIndexToLength[this.partIndex - 1];
        if (this.actualPartLength !== expectedLength) {
            throw (0, builder_util_runtime_1.newError)(`Expected length: ${expectedLength} differs from actual: ${this.actualPartLength}`, "ERR_DATA_SPLITTER_LENGTH_MISMATCH");
        }
        this.actualPartLength = 0;
    }
    processPartStarted(data, start, end) {
        if (this.partIndex !== 0) {
            this.onPartEnd();
        }
        return this.processPartData(data, start, end);
    }
    processPartData(data, start, end) {
        this.actualPartLength += end - start;
        const out = this.out;
        if (out.write(start === 0 && data.length === end ? data : data.slice(start, end))) {
            return Promise.resolve();
        }
        else {
            return new Promise((resolve, reject) => {
                out.on("error", reject);
                out.once("drain", () => {
                    out.removeListener("error", reject);
                    resolve();
                });
            });
        }
    }
}
exports.DataSplitter = DataSplitter;
//# sourceMappingURL=DataSplitter.js.map{"version":3,"file":"DataSplitter.js","sourceRoot":"","sources":["../../src/differentialDownloader/DataSplitter.ts"],"names":[],"mappings":"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","sourcesContent":["import { newError } from \"builder-util-runtime\"\nimport { createReadStream } from \"fs\"\nimport { Writable } from \"stream\"\nimport { Operation, OperationKind } from \"./downloadPlanBuilder\"\n\nconst DOUBLE_CRLF = Buffer.from(\"\\r\\n\\r\\n\")\n\nenum ReadState {\n  INIT,\n  HEADER,\n  BODY,\n}\n\nexport interface PartListDataTask {\n  readonly oldFileFd: number\n  readonly tasks: Array<Operation>\n  readonly start: number\n  readonly end: number\n}\n\nexport function copyData(task: Operation, out: Writable, oldFileFd: number, reject: (error: Error) => void, resolve: () => void): void {\n  const readStream = createReadStream(\"\", {\n    fd: oldFileFd,\n    autoClose: false,\n    start: task.start,\n    // end is inclusive\n    end: task.end - 1,\n  })\n  readStream.on(\"error\", reject)\n  readStream.once(\"end\", resolve)\n  readStream.pipe(out, {\n    end: false,\n  })\n}\n\nexport class DataSplitter extends Writable {\n  partIndex = -1\n\n  private headerListBuffer: Buffer | null = null\n  private readState = ReadState.INIT\n  private ignoreByteCount = 0\n  private remainingPartDataCount = 0\n\n  private readonly boundaryLength: number\n\n  constructor(\n    private readonly out: Writable,\n    private readonly options: PartListDataTask,\n    private readonly partIndexToTaskIndex: Map<number, number>,\n    boundary: string,\n    private readonly partIndexToLength: Array<number>,\n    private readonly finishHandler: () => any\n  ) {\n    super()\n\n    this.boundaryLength = boundary.length + 4 /* size of \\r\\n-- */\n    // first chunk doesn't start with \\r\\n\n    this.ignoreByteCount = this.boundaryLength - 2\n  }\n\n  get isFinished(): boolean {\n    return this.partIndex === this.partIndexToLength.length\n  }\n\n  // noinspection JSUnusedGlobalSymbols\n  _write(data: Buffer, encoding: string, callback: (error?: Error) => void): void {\n    if (this.isFinished) {\n      console.error(`Trailing ignored data: ${data.length} bytes`)\n      return\n    }\n\n    this.handleData(data).then(callback).catch(callback)\n  }\n\n  private async handleData(chunk: Buffer): Promise<undefined> {\n    let start = 0\n\n    if (this.ignoreByteCount !== 0 && this.remainingPartDataCount !== 0) {\n      throw newError(\"Internal error\", \"ERR_DATA_SPLITTER_BYTE_COUNT_MISMATCH\")\n    }\n\n    if (this.ignoreByteCount > 0) {\n      const toIgnore = Math.min(this.ignoreByteCount, chunk.length)\n      this.ignoreByteCount -= toIgnore\n      start = toIgnore\n    } else if (this.remainingPartDataCount > 0) {\n      const toRead = Math.min(this.remainingPartDataCount, chunk.length)\n      this.remainingPartDataCount -= toRead\n      await this.processPartData(chunk, 0, toRead)\n      start = toRead\n    }\n\n    if (start === chunk.length) {\n      return\n    }\n\n    if (this.readState === ReadState.HEADER) {\n      const headerListEnd = this.searchHeaderListEnd(chunk, start)\n      if (headerListEnd === -1) {\n        return\n      }\n\n      start = headerListEnd\n      this.readState = ReadState.BODY\n      // header list is ignored, we don't need it\n      this.headerListBuffer = null\n    }\n\n    while (true) {\n      if (this.readState === ReadState.BODY) {\n        this.readState = ReadState.INIT\n      } else {\n        this.partIndex++\n\n        let taskIndex = this.partIndexToTaskIndex.get(this.partIndex)\n        if (taskIndex == null) {\n          if (this.isFinished) {\n            taskIndex = this.options.end\n          } else {\n            throw newError(\"taskIndex is null\", \"ERR_DATA_SPLITTER_TASK_INDEX_IS_NULL\")\n          }\n        }\n\n        const prevTaskIndex = this.partIndex === 0 ? this.options.start : this.partIndexToTaskIndex.get(this.partIndex - 1)! + 1 /* prev part is download, next maybe copy */\n        if (prevTaskIndex < taskIndex) {\n          await this.copyExistingData(prevTaskIndex, taskIndex)\n        } else if (prevTaskIndex > taskIndex) {\n          throw newError(\"prevTaskIndex must be < taskIndex\", \"ERR_DATA_SPLITTER_TASK_INDEX_ASSERT_FAILED\")\n        }\n\n        if (this.isFinished) {\n          this.onPartEnd()\n          this.finishHandler()\n          return\n        }\n\n        start = this.searchHeaderListEnd(chunk, start)\n\n        if (start === -1) {\n          this.readState = ReadState.HEADER\n          return\n        }\n      }\n\n      const partLength = this.partIndexToLength[this.partIndex]\n      const end = start + partLength\n      const effectiveEnd = Math.min(end, chunk.length)\n      await this.processPartStarted(chunk, start, effectiveEnd)\n      this.remainingPartDataCount = partLength - (effectiveEnd - start)\n      if (this.remainingPartDataCount > 0) {\n        return\n      }\n\n      start = end + this.boundaryLength\n      if (start >= chunk.length) {\n        this.ignoreByteCount = this.boundaryLength - (chunk.length - end)\n        return\n      }\n    }\n  }\n\n  private copyExistingData(index: number, end: number): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const w = (): void => {\n        if (index === end) {\n          resolve()\n          return\n        }\n\n        const task = this.options.tasks[index]\n        if (task.kind !== OperationKind.COPY) {\n          reject(new Error(\"Task kind must be COPY\"))\n          return\n        }\n\n        copyData(task, this.out, this.options.oldFileFd, reject, () => {\n          index++\n          w()\n        })\n      }\n      w()\n    })\n  }\n\n  private searchHeaderListEnd(chunk: Buffer, readOffset: number): number {\n    const headerListEnd = chunk.indexOf(DOUBLE_CRLF, readOffset)\n    if (headerListEnd !== -1) {\n      return headerListEnd + DOUBLE_CRLF.length\n    }\n\n    // not all headers data were received, save to buffer\n    const partialChunk = readOffset === 0 ? chunk : chunk.slice(readOffset)\n    if (this.headerListBuffer == null) {\n      this.headerListBuffer = partialChunk\n    } else {\n      this.headerListBuffer = Buffer.concat([this.headerListBuffer, partialChunk])\n    }\n    return -1\n  }\n\n  private actualPartLength = 0\n\n  private onPartEnd(): void {\n    const expectedLength = this.partIndexToLength[this.partIndex - 1]\n    if (this.actualPartLength !== expectedLength) {\n      throw newError(`Expected length: ${expectedLength} differs from actual: ${this.actualPartLength}`, \"ERR_DATA_SPLITTER_LENGTH_MISMATCH\")\n    }\n    this.actualPartLength = 0\n  }\n\n  private processPartStarted(data: Buffer, start: number, end: number): Promise<void> {\n    if (this.partIndex !== 0) {\n      this.onPartEnd()\n    }\n    return this.processPartData(data, start, end)\n  }\n\n  private processPartData(data: Buffer, start: number, end: number): Promise<void> {\n    this.actualPartLength += end - start\n    const out = this.out\n    if (out.write(start === 0 && data.length === end ? data : data.slice(start, end))) {\n      return Promise.resolve()\n    } else {\n      return new Promise((resolve, reject) => {\n        out.on(\"error\", reject)\n        out.once(\"drain\", () => {\n          out.removeListener(\"error\", reject)\n          resolve()\n        })\n      })\n    }\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DifferentialDownloader = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const fs_extra_1 = require("fs-extra");
const fs_1 = require("fs");
const DataSplitter_1 = require("./DataSplitter");
const url_1 = require("url");
const downloadPlanBuilder_1 = require("./downloadPlanBuilder");
const multipleRangeDownloader_1 = require("./multipleRangeDownloader");
const ProgressDifferentialDownloadCallbackTransform_1 = require("./ProgressDifferentialDownloadCallbackTransform");
class DifferentialDownloader {
    // noinspection TypeScriptAbstractClassConstructorCanBeMadeProtected
    constructor(blockAwareFileInfo, httpExecutor, options) {
        this.blockAwareFileInfo = blockAwareFileInfo;
        this.httpExecutor = httpExecutor;
        this.options = options;
        this.fileMetadataBuffer = null;
        this.logger = options.logger;
    }
    createRequestOptions() {
        const result = {
            headers: {
                ...this.options.requestHeaders,
                accept: "*/*",
            },
        };
        (0, builder_util_runtime_1.configureRequestUrl)(this.options.newUrl, result);
        // user-agent, cache-control and other common options
        (0, builder_util_runtime_1.configureRequestOptions)(result);
        return result;
    }
    doDownload(oldBlockMap, newBlockMap) {
        // we don't check other metadata like compressionMethod - generic check that it is make sense to differentially update is suitable for it
        if (oldBlockMap.version !== newBlockMap.version) {
            throw new Error(`version is different (${oldBlockMap.version} - ${newBlockMap.version}), full download is required`);
        }
        const logger = this.logger;
        const operations = (0, downloadPlanBuilder_1.computeOperations)(oldBlockMap, newBlockMap, logger);
        if (logger.debug != null) {
            logger.debug(JSON.stringify(operations, null, 2));
        }
        let downloadSize = 0;
        let copySize = 0;
        for (const operation of operations) {
            const length = operation.end - operation.start;
            if (operation.kind === downloadPlanBuilder_1.OperationKind.DOWNLOAD) {
                downloadSize += length;
            }
            else {
                copySize += length;
            }
        }
        const newSize = this.blockAwareFileInfo.size;
        if (downloadSize + copySize + (this.fileMetadataBuffer == null ? 0 : this.fileMetadataBuffer.length) !== newSize) {
            throw new Error(`Internal error, size mismatch: downloadSize: ${downloadSize}, copySize: ${copySize}, newSize: ${newSize}`);
        }
        logger.info(`Full: ${formatBytes(newSize)}, To download: ${formatBytes(downloadSize)} (${Math.round(downloadSize / (newSize / 100))}%)`);
        return this.downloadFile(operations);
    }
    downloadFile(tasks) {
        const fdList = [];
        const closeFiles = () => {
            return Promise.all(fdList.map(openedFile => {
                return (0, fs_extra_1.close)(openedFile.descriptor).catch((e) => {
                    this.logger.error(`cannot close file "${openedFile.path}": ${e}`);
                });
            }));
        };
        return this.doDownloadFile(tasks, fdList)
            .then(closeFiles)
            .catch((e) => {
            // then must be after catch here (since then always throws error)
            return closeFiles()
                .catch(closeFilesError => {
                // closeFiles never throw error, but just to be sure
                try {
                    this.logger.error(`cannot close files: ${closeFilesError}`);
                }
                catch (errorOnLog) {
                    try {
                        console.error(errorOnLog);
                    }
                    catch (_ignored) {
                        // ok, give up and ignore error
                    }
                }
                throw e;
            })
                .then(() => {
                throw e;
            });
        });
    }
    async doDownloadFile(tasks, fdList) {
        const oldFileFd = await (0, fs_extra_1.open)(this.options.oldFile, "r");
        fdList.push({ descriptor: oldFileFd, path: this.options.oldFile });
        const newFileFd = await (0, fs_extra_1.open)(this.options.newFile, "w");
        fdList.push({ descriptor: newFileFd, path: this.options.newFile });
        const fileOut = (0, fs_1.createWriteStream)(this.options.newFile, { fd: newFileFd });
        await new Promise((resolve, reject) => {
            const streams = [];
            // Create our download info transformer if we have one
            let downloadInfoTransform = undefined;
            if (!this.options.isUseMultipleRangeRequest && this.options.onProgress) {
                // TODO: Does not support multiple ranges (someone feel free to PR this!)
                const expectedByteCounts = [];
                let grandTotalBytes = 0;
                for (const task of tasks) {
                    if (task.kind === downloadPlanBuilder_1.OperationKind.DOWNLOAD) {
                        expectedByteCounts.push(task.end - task.start);
                        grandTotalBytes += task.end - task.start;
                    }
                }
                const progressDifferentialDownloadInfo = {
                    expectedByteCounts: expectedByteCounts,
                    grandTotal: grandTotalBytes,
                };
                downloadInfoTransform = new ProgressDifferentialDownloadCallbackTransform_1.ProgressDifferentialDownloadCallbackTransform(progressDifferentialDownloadInfo, this.options.cancellationToken, this.options.onProgress);
                streams.push(downloadInfoTransform);
            }
            const digestTransform = new builder_util_runtime_1.DigestTransform(this.blockAwareFileInfo.sha512);
            // to simply debug, do manual validation to allow file to be fully written
            digestTransform.isValidateOnEnd = false;
            streams.push(digestTransform);
            // noinspection JSArrowFunctionCanBeReplacedWithShorthand
            fileOut.on("finish", () => {
                ;
                fileOut.close(() => {
                    // remove from fd list because closed successfully
                    fdList.splice(1, 1);
                    try {
                        digestTransform.validate();
                    }
                    catch (e) {
                        reject(e);
                        return;
                    }
                    resolve(undefined);
                });
            });
            streams.push(fileOut);
            let lastStream = null;
            for (const stream of streams) {
                stream.on("error", reject);
                if (lastStream == null) {
                    lastStream = stream;
                }
                else {
                    lastStream = lastStream.pipe(stream);
                }
            }
            const firstStream = streams[0];
            let w;
            if (this.options.isUseMultipleRangeRequest) {
                w = (0, multipleRangeDownloader_1.executeTasksUsingMultipleRangeRequests)(this, tasks, firstStream, oldFileFd, reject);
                w(0);
                return;
            }
            let downloadOperationCount = 0;
            let actualUrl = null;
            this.logger.info(`Differential download: ${this.options.newUrl}`);
            const requestOptions = this.createRequestOptions();
            requestOptions.redirect = "manual";
            w = (index) => {
                var _a, _b;
                if (index >= tasks.length) {
                    if (this.fileMetadataBuffer != null) {
                        firstStream.write(this.fileMetadataBuffer);
                    }
                    firstStream.end();
                    return;
                }
                const operation = tasks[index++];
                if (operation.kind === downloadPlanBuilder_1.OperationKind.COPY) {
                    // We are copying, let's not send status updates to the UI
                    if (downloadInfoTransform) {
                        downloadInfoTransform.beginFileCopy();
                    }
                    (0, DataSplitter_1.copyData)(operation, firstStream, oldFileFd, reject, () => w(index));
                    return;
                }
                const range = `bytes=${operation.start}-${operation.end - 1}`;
                requestOptions.headers.range = range;
                (_b = (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug) === null || _b === void 0 ? void 0 : _b.call(_a, `download range: ${range}`);
                // We are starting to download
                if (downloadInfoTransform) {
                    downloadInfoTransform.beginRangeDownload();
                }
                const request = this.httpExecutor.createRequest(requestOptions, response => {
                    response.on("error", reject);
                    response.on("aborted", () => {
                        reject(new Error("response has been aborted by the server"));
                    });
                    // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.
                    if (response.statusCode >= 400) {
                        reject((0, builder_util_runtime_1.createHttpError)(response));
                    }
                    response.pipe(firstStream, {
                        end: false,
                    });
                    response.once("end", () => {
                        // Pass on that we are downloading a segment
                        if (downloadInfoTransform) {
                            downloadInfoTransform.endRangeDownload();
                        }
                        if (++downloadOperationCount === 100) {
                            downloadOperationCount = 0;
                            setTimeout(() => w(index), 1000);
                        }
                        else {
                            w(index);
                        }
                    });
                });
                request.on("redirect", (statusCode, method, redirectUrl) => {
                    this.logger.info(`Redirect to ${removeQuery(redirectUrl)}`);
                    actualUrl = redirectUrl;
                    (0, builder_util_runtime_1.configureRequestUrl)(new url_1.URL(actualUrl), requestOptions);
                    request.followRedirect();
                });
                this.httpExecutor.addErrorAndTimeoutHandlers(request, reject);
                request.end();
            };
            w(0);
        });
    }
    async readRemoteBytes(start, endInclusive) {
        const buffer = Buffer.allocUnsafe(endInclusive + 1 - start);
        const requestOptions = this.createRequestOptions();
        requestOptions.headers.range = `bytes=${start}-${endInclusive}`;
        let position = 0;
        await this.request(requestOptions, chunk => {
            chunk.copy(buffer, position);
            position += chunk.length;
        });
        if (position !== buffer.length) {
            throw new Error(`Received data length ${position} is not equal to expected ${buffer.length}`);
        }
        return buffer;
    }
    request(requestOptions, dataHandler) {
        return new Promise((resolve, reject) => {
            const request = this.httpExecutor.createRequest(requestOptions, response => {
                if (!(0, multipleRangeDownloader_1.checkIsRangesSupported)(response, reject)) {
                    return;
                }
                response.on("error", reject);
                response.on("aborted", () => {
                    reject(new Error("response has been aborted by the server"));
                });
                response.on("data", dataHandler);
                response.on("end", () => resolve());
            });
            this.httpExecutor.addErrorAndTimeoutHandlers(request, reject);
            request.end();
        });
    }
}
exports.DifferentialDownloader = DifferentialDownloader;
function formatBytes(value, symbol = " KB") {
    return new Intl.NumberFormat("en").format((value / 1024).toFixed(2)) + symbol;
}
// safety
function removeQuery(url) {
    const index = url.indexOf("?");
    return index < 0 ? url : url.substring(0, index);
}
//# sourceMappingURL=DifferentialDownloader.js.map{"version":3,"file":"DifferentialDownloader.js","sourceRoot":"","sources":["../../src/differentialDownloader/DifferentialDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import { BlockMapDataHolder, createHttpError, DigestTransform, HttpExecutor, configureRequestUrl, configureRequestOptions } from \"builder-util-runtime\"\nimport { BlockMap } from \"builder-util-runtime/out/blockMapApi\"\nimport { close, open } from \"fs-extra\"\nimport { createWriteStream } from \"fs\"\nimport { OutgoingHttpHeaders, RequestOptions } from \"http\"\nimport { ProgressInfo, CancellationToken } from \"builder-util-runtime\"\nimport { Logger } from \"../types\"\nimport { copyData } from \"./DataSplitter\"\nimport { URL } from \"url\"\nimport { computeOperations, Operation, OperationKind } from \"./downloadPlanBuilder\"\nimport { checkIsRangesSupported, executeTasksUsingMultipleRangeRequests } from \"./multipleRangeDownloader\"\nimport { ProgressDifferentialDownloadCallbackTransform, ProgressDifferentialDownloadInfo } from \"./ProgressDifferentialDownloadCallbackTransform\"\n\nexport interface DifferentialDownloaderOptions {\n  readonly oldFile: string\n  readonly newUrl: URL\n  readonly logger: Logger\n  readonly newFile: string\n\n  readonly requestHeaders: OutgoingHttpHeaders | null\n\n  readonly isUseMultipleRangeRequest?: boolean\n\n  readonly cancellationToken: CancellationToken\n  onProgress?: (progress: ProgressInfo) => void\n}\n\nexport abstract class DifferentialDownloader {\n  fileMetadataBuffer: Buffer | null = null\n\n  private readonly logger: Logger\n\n  // noinspection TypeScriptAbstractClassConstructorCanBeMadeProtected\n  constructor(\n    protected readonly blockAwareFileInfo: BlockMapDataHolder,\n    readonly httpExecutor: HttpExecutor<any>,\n    readonly options: DifferentialDownloaderOptions\n  ) {\n    this.logger = options.logger\n  }\n\n  createRequestOptions(): RequestOptions {\n    const result = {\n      headers: {\n        ...this.options.requestHeaders,\n        accept: \"*/*\",\n      },\n    }\n    configureRequestUrl(this.options.newUrl, result)\n    // user-agent, cache-control and other common options\n    configureRequestOptions(result)\n    return result\n  }\n\n  protected doDownload(oldBlockMap: BlockMap, newBlockMap: BlockMap): Promise<any> {\n    // we don't check other metadata like compressionMethod - generic check that it is make sense to differentially update is suitable for it\n    if (oldBlockMap.version !== newBlockMap.version) {\n      throw new Error(`version is different (${oldBlockMap.version} - ${newBlockMap.version}), full download is required`)\n    }\n\n    const logger = this.logger\n    const operations = computeOperations(oldBlockMap, newBlockMap, logger)\n    if (logger.debug != null) {\n      logger.debug(JSON.stringify(operations, null, 2))\n    }\n\n    let downloadSize = 0\n    let copySize = 0\n    for (const operation of operations) {\n      const length = operation.end - operation.start\n      if (operation.kind === OperationKind.DOWNLOAD) {\n        downloadSize += length\n      } else {\n        copySize += length\n      }\n    }\n\n    const newSize = this.blockAwareFileInfo.size\n    if (downloadSize + copySize + (this.fileMetadataBuffer == null ? 0 : this.fileMetadataBuffer.length) !== newSize) {\n      throw new Error(`Internal error, size mismatch: downloadSize: ${downloadSize}, copySize: ${copySize}, newSize: ${newSize}`)\n    }\n\n    logger.info(`Full: ${formatBytes(newSize)}, To download: ${formatBytes(downloadSize)} (${Math.round(downloadSize / (newSize / 100))}%)`)\n\n    return this.downloadFile(operations)\n  }\n\n  private downloadFile(tasks: Array<Operation>): Promise<any> {\n    const fdList: Array<OpenedFile> = []\n    const closeFiles = (): Promise<Array<void>> => {\n      return Promise.all(\n        fdList.map(openedFile => {\n          return close(openedFile.descriptor).catch((e: any) => {\n            this.logger.error(`cannot close file \"${openedFile.path}\": ${e}`)\n          })\n        })\n      )\n    }\n    return this.doDownloadFile(tasks, fdList)\n      .then(closeFiles)\n      .catch((e: any) => {\n        // then must be after catch here (since then always throws error)\n        return closeFiles()\n          .catch(closeFilesError => {\n            // closeFiles never throw error, but just to be sure\n            try {\n              this.logger.error(`cannot close files: ${closeFilesError}`)\n            } catch (errorOnLog) {\n              try {\n                console.error(errorOnLog)\n              } catch (_ignored) {\n                // ok, give up and ignore error\n              }\n            }\n            throw e\n          })\n          .then(() => {\n            throw e\n          })\n      })\n  }\n\n  private async doDownloadFile(tasks: Array<Operation>, fdList: Array<OpenedFile>): Promise<any> {\n    const oldFileFd = await open(this.options.oldFile, \"r\")\n    fdList.push({ descriptor: oldFileFd, path: this.options.oldFile })\n    const newFileFd = await open(this.options.newFile, \"w\")\n    fdList.push({ descriptor: newFileFd, path: this.options.newFile })\n    const fileOut = createWriteStream(this.options.newFile, { fd: newFileFd })\n    await new Promise((resolve, reject) => {\n      const streams: Array<any> = []\n\n      // Create our download info transformer if we have one\n      let downloadInfoTransform: ProgressDifferentialDownloadCallbackTransform | undefined = undefined\n      if (!this.options.isUseMultipleRangeRequest && this.options.onProgress) {\n        // TODO: Does not support multiple ranges (someone feel free to PR this!)\n        const expectedByteCounts: Array<number> = []\n        let grandTotalBytes = 0\n\n        for (const task of tasks) {\n          if (task.kind === OperationKind.DOWNLOAD) {\n            expectedByteCounts.push(task.end - task.start)\n            grandTotalBytes += task.end - task.start\n          }\n        }\n\n        const progressDifferentialDownloadInfo: ProgressDifferentialDownloadInfo = {\n          expectedByteCounts: expectedByteCounts,\n          grandTotal: grandTotalBytes,\n        }\n\n        downloadInfoTransform = new ProgressDifferentialDownloadCallbackTransform(progressDifferentialDownloadInfo, this.options.cancellationToken, this.options.onProgress)\n        streams.push(downloadInfoTransform)\n      }\n\n      const digestTransform = new DigestTransform(this.blockAwareFileInfo.sha512)\n      // to simply debug, do manual validation to allow file to be fully written\n      digestTransform.isValidateOnEnd = false\n      streams.push(digestTransform)\n\n      // noinspection JSArrowFunctionCanBeReplacedWithShorthand\n      fileOut.on(\"finish\", () => {\n        ;(fileOut.close as any)(() => {\n          // remove from fd list because closed successfully\n          fdList.splice(1, 1)\n          try {\n            digestTransform.validate()\n          } catch (e: any) {\n            reject(e)\n            return\n          }\n\n          resolve(undefined)\n        })\n      })\n\n      streams.push(fileOut)\n\n      let lastStream = null\n      for (const stream of streams) {\n        stream.on(\"error\", reject)\n        if (lastStream == null) {\n          lastStream = stream\n        } else {\n          lastStream = lastStream.pipe(stream)\n        }\n      }\n\n      const firstStream = streams[0]\n\n      let w: any\n      if (this.options.isUseMultipleRangeRequest) {\n        w = executeTasksUsingMultipleRangeRequests(this, tasks, firstStream, oldFileFd, reject)\n        w(0)\n        return\n      }\n\n      let downloadOperationCount = 0\n      let actualUrl: string | null = null\n      this.logger.info(`Differential download: ${this.options.newUrl}`)\n\n      const requestOptions = this.createRequestOptions()\n      ;(requestOptions as any).redirect = \"manual\"\n\n      w = (index: number): void => {\n        if (index >= tasks.length) {\n          if (this.fileMetadataBuffer != null) {\n            firstStream.write(this.fileMetadataBuffer)\n          }\n          firstStream.end()\n          return\n        }\n\n        const operation = tasks[index++]\n        if (operation.kind === OperationKind.COPY) {\n          // We are copying, let's not send status updates to the UI\n          if (downloadInfoTransform) {\n            downloadInfoTransform.beginFileCopy()\n          }\n\n          copyData(operation, firstStream, oldFileFd, reject, () => w(index))\n          return\n        }\n\n        const range = `bytes=${operation.start}-${operation.end - 1}`\n        requestOptions.headers!.range = range\n\n        this.logger?.debug?.(`download range: ${range}`)\n\n        // We are starting to download\n        if (downloadInfoTransform) {\n          downloadInfoTransform.beginRangeDownload()\n        }\n\n        const request = this.httpExecutor.createRequest(requestOptions, response => {\n          response.on(\"error\", reject)\n          response.on(\"aborted\", () => {\n            reject(new Error(\"response has been aborted by the server\"))\n          })\n          // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.\n          if (response.statusCode >= 400) {\n            reject(createHttpError(response))\n          }\n\n          response.pipe(firstStream, {\n            end: false,\n          })\n          response.once(\"end\", () => {\n            // Pass on that we are downloading a segment\n            if (downloadInfoTransform) {\n              downloadInfoTransform.endRangeDownload()\n            }\n\n            if (++downloadOperationCount === 100) {\n              downloadOperationCount = 0\n              setTimeout(() => w(index), 1000)\n            } else {\n              w(index)\n            }\n          })\n        })\n        request.on(\"redirect\", (statusCode: number, method: string, redirectUrl: string) => {\n          this.logger.info(`Redirect to ${removeQuery(redirectUrl)}`)\n          actualUrl = redirectUrl\n          configureRequestUrl(new URL(actualUrl), requestOptions)\n          request.followRedirect()\n        })\n        this.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n        request.end()\n      }\n\n      w(0)\n    })\n  }\n\n  protected async readRemoteBytes(start: number, endInclusive: number): Promise<Buffer> {\n    const buffer = Buffer.allocUnsafe(endInclusive + 1 - start)\n    const requestOptions = this.createRequestOptions()\n    requestOptions.headers!.range = `bytes=${start}-${endInclusive}`\n    let position = 0\n    await this.request(requestOptions, chunk => {\n      chunk.copy(buffer, position)\n      position += chunk.length\n    })\n\n    if (position !== buffer.length) {\n      throw new Error(`Received data length ${position} is not equal to expected ${buffer.length}`)\n    }\n    return buffer\n  }\n\n  private request(requestOptions: RequestOptions, dataHandler: (chunk: Buffer) => void): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const request = this.httpExecutor.createRequest(requestOptions, response => {\n        if (!checkIsRangesSupported(response, reject)) {\n          return\n        }\n\n        response.on(\"error\", reject)\n        response.on(\"aborted\", () => {\n          reject(new Error(\"response has been aborted by the server\"))\n        })\n\n        response.on(\"data\", dataHandler)\n        response.on(\"end\", () => resolve())\n      })\n      this.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n      request.end()\n    })\n  }\n}\n\nfunction formatBytes(value: number, symbol = \" KB\"): string {\n  return new Intl.NumberFormat(\"en\").format((value / 1024).toFixed(2) as any) + symbol\n}\n\n// safety\nfunction removeQuery(url: string): string {\n  const index = url.indexOf(\"?\")\n  return index < 0 ? url : url.substring(0, index)\n}\n\ninterface OpenedFile {\n  readonly descriptor: number\n  readonly path: string\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileWithEmbeddedBlockMapDifferentialDownloader = void 0;
const fs_extra_1 = require("fs-extra");
const DifferentialDownloader_1 = require("./DifferentialDownloader");
const zlib_1 = require("zlib");
class FileWithEmbeddedBlockMapDifferentialDownloader extends DifferentialDownloader_1.DifferentialDownloader {
    async download() {
        const packageInfo = this.blockAwareFileInfo;
        const fileSize = packageInfo.size;
        const offset = fileSize - (packageInfo.blockMapSize + 4);
        this.fileMetadataBuffer = await this.readRemoteBytes(offset, fileSize - 1);
        const newBlockMap = readBlockMap(this.fileMetadataBuffer.slice(0, this.fileMetadataBuffer.length - 4));
        await this.doDownload(await readEmbeddedBlockMapData(this.options.oldFile), newBlockMap);
    }
}
exports.FileWithEmbeddedBlockMapDifferentialDownloader = FileWithEmbeddedBlockMapDifferentialDownloader;
function readBlockMap(data) {
    return JSON.parse((0, zlib_1.inflateRawSync)(data).toString());
}
async function readEmbeddedBlockMapData(file) {
    const fd = await (0, fs_extra_1.open)(file, "r");
    try {
        const fileSize = (await (0, fs_extra_1.fstat)(fd)).size;
        const sizeBuffer = Buffer.allocUnsafe(4);
        await (0, fs_extra_1.read)(fd, sizeBuffer, 0, sizeBuffer.length, fileSize - sizeBuffer.length);
        const dataBuffer = Buffer.allocUnsafe(sizeBuffer.readUInt32BE(0));
        await (0, fs_extra_1.read)(fd, dataBuffer, 0, dataBuffer.length, fileSize - sizeBuffer.length - dataBuffer.length);
        await (0, fs_extra_1.close)(fd);
        return readBlockMap(dataBuffer);
    }
    catch (e) {
        await (0, fs_extra_1.close)(fd);
        throw e;
    }
}
//# sourceMappingURL=FileWithEmbeddedBlockMapDifferentialDownloader.js.map{"version":3,"file":"FileWithEmbeddedBlockMapDifferentialDownloader.js","sourceRoot":"","sources":["../../src/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.ts"],"names":[],"mappings":";;;AACA,uCAAmD;AACnD,qEAAiE;AACjE,+BAAqC;AAErC,MAAa,8CAA+C,SAAQ,+CAAsB;IACxF,KAAK,CAAC,QAAQ;QACZ,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAA;QAC3C,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAK,CAAA;QAClC,MAAM,MAAM,GAAG,QAAQ,GAAG,CAAC,WAAW,CAAC,YAAa,GAAG,CAAC,CAAC,CAAA;QACzD,IAAI,CAAC,kBAAkB,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAA;QAC1E,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;QACtG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,wBAAwB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,CAAA;IAC1F,CAAC;CACF;AATD,wGASC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,qBAAc,EAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;AACpD,CAAC;AAED,KAAK,UAAU,wBAAwB,CAAC,IAAY;IAClD,MAAM,EAAE,GAAG,MAAM,IAAA,eAAI,EAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAChC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAA,gBAAK,EAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;QACvC,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;QACxC,MAAM,IAAA,eAAI,EAAC,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;QAE9E,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;QACjE,MAAM,IAAA,eAAI,EAAC,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;QAClG,MAAM,IAAA,gBAAK,EAAC,EAAE,CAAC,CAAA;QAEf,OAAO,YAAY,CAAC,UAAU,CAAC,CAAA;IACjC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,IAAA,gBAAK,EAAC,EAAE,CAAC,CAAA;QACf,MAAM,CAAC,CAAA;IACT,CAAC;AACH,CAAC","sourcesContent":["import { BlockMap } from \"builder-util-runtime/out/blockMapApi\"\nimport { close, fstat, open, read } from \"fs-extra\"\nimport { DifferentialDownloader } from \"./DifferentialDownloader\"\nimport { inflateRawSync } from \"zlib\"\n\nexport class FileWithEmbeddedBlockMapDifferentialDownloader extends DifferentialDownloader {\n  async download(): Promise<void> {\n    const packageInfo = this.blockAwareFileInfo\n    const fileSize = packageInfo.size!\n    const offset = fileSize - (packageInfo.blockMapSize! + 4)\n    this.fileMetadataBuffer = await this.readRemoteBytes(offset, fileSize - 1)\n    const newBlockMap = readBlockMap(this.fileMetadataBuffer.slice(0, this.fileMetadataBuffer.length - 4))\n    await this.doDownload(await readEmbeddedBlockMapData(this.options.oldFile), newBlockMap)\n  }\n}\n\nfunction readBlockMap(data: Buffer): BlockMap {\n  return JSON.parse(inflateRawSync(data).toString())\n}\n\nasync function readEmbeddedBlockMapData(file: string): Promise<BlockMap> {\n  const fd = await open(file, \"r\")\n  try {\n    const fileSize = (await fstat(fd)).size\n    const sizeBuffer = Buffer.allocUnsafe(4)\n    await read(fd, sizeBuffer, 0, sizeBuffer.length, fileSize - sizeBuffer.length)\n\n    const dataBuffer = Buffer.allocUnsafe(sizeBuffer.readUInt32BE(0))\n    await read(fd, dataBuffer, 0, dataBuffer.length, fileSize - sizeBuffer.length - dataBuffer.length)\n    await close(fd)\n\n    return readBlockMap(dataBuffer)\n  } catch (e: any) {\n    await close(fd)\n    throw e\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GenericDifferentialDownloader = void 0;
const DifferentialDownloader_1 = require("./DifferentialDownloader");
class GenericDifferentialDownloader extends DifferentialDownloader_1.DifferentialDownloader {
    download(oldBlockMap, newBlockMap) {
        return this.doDownload(oldBlockMap, newBlockMap);
    }
}
exports.GenericDifferentialDownloader = GenericDifferentialDownloader;
//# sourceMappingURL=GenericDifferentialDownloader.js.map{"version":3,"file":"GenericDifferentialDownloader.js","sourceRoot":"","sources":["../../src/differentialDownloader/GenericDifferentialDownloader.ts"],"names":[],"mappings":";;;AACA,qEAAiE;AAEjE,MAAa,6BAA8B,SAAQ,+CAAsB;IACvE,QAAQ,CAAC,WAAqB,EAAE,WAAqB;QACnD,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;IAClD,CAAC;CACF;AAJD,sEAIC","sourcesContent":["import { BlockMap } from \"builder-util-runtime/out/blockMapApi\"\nimport { DifferentialDownloader } from \"./DifferentialDownloader\"\n\nexport class GenericDifferentialDownloader extends DifferentialDownloader {\n  download(oldBlockMap: BlockMap, newBlockMap: BlockMap): Promise<any> {\n    return this.doDownload(oldBlockMap, newBlockMap)\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProgressDifferentialDownloadCallbackTransform = void 0;
const stream_1 = require("stream");
var OperationKind;
(function (OperationKind) {
    OperationKind[OperationKind["COPY"] = 0] = "COPY";
    OperationKind[OperationKind["DOWNLOAD"] = 1] = "DOWNLOAD";
})(OperationKind || (OperationKind = {}));
class ProgressDifferentialDownloadCallbackTransform extends stream_1.Transform {
    constructor(progressDifferentialDownloadInfo, cancellationToken, onProgress) {
        super();
        this.progressDifferentialDownloadInfo = progressDifferentialDownloadInfo;
        this.cancellationToken = cancellationToken;
        this.onProgress = onProgress;
        this.start = Date.now();
        this.transferred = 0;
        this.delta = 0;
        this.expectedBytes = 0;
        this.index = 0;
        this.operationType = OperationKind.COPY;
        this.nextUpdate = this.start + 1000;
    }
    _transform(chunk, encoding, callback) {
        if (this.cancellationToken.cancelled) {
            callback(new Error("cancelled"), null);
            return;
        }
        // Don't send progress update when copying from disk
        if (this.operationType == OperationKind.COPY) {
            callback(null, chunk);
            return;
        }
        this.transferred += chunk.length;
        this.delta += chunk.length;
        const now = Date.now();
        if (now >= this.nextUpdate &&
            this.transferred !== this.expectedBytes /* will be emitted by endRangeDownload() */ &&
            this.transferred !== this.progressDifferentialDownloadInfo.grandTotal /* will be emitted on _flush */) {
            this.nextUpdate = now + 1000;
            this.onProgress({
                total: this.progressDifferentialDownloadInfo.grandTotal,
                delta: this.delta,
                transferred: this.transferred,
                percent: (this.transferred / this.progressDifferentialDownloadInfo.grandTotal) * 100,
                bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000)),
            });
            this.delta = 0;
        }
        callback(null, chunk);
    }
    beginFileCopy() {
        this.operationType = OperationKind.COPY;
    }
    beginRangeDownload() {
        this.operationType = OperationKind.DOWNLOAD;
        this.expectedBytes += this.progressDifferentialDownloadInfo.expectedByteCounts[this.index++];
    }
    endRangeDownload() {
        // _flush() will doour final 100%
        if (this.transferred !== this.progressDifferentialDownloadInfo.grandTotal) {
            this.onProgress({
                total: this.progressDifferentialDownloadInfo.grandTotal,
                delta: this.delta,
                transferred: this.transferred,
                percent: (this.transferred / this.progressDifferentialDownloadInfo.grandTotal) * 100,
                bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000)),
            });
        }
    }
    // Called when we are 100% done with the connection/download
    _flush(callback) {
        if (this.cancellationToken.cancelled) {
            callback(new Error("cancelled"));
            return;
        }
        this.onProgress({
            total: this.progressDifferentialDownloadInfo.grandTotal,
            delta: this.delta,
            transferred: this.transferred,
            percent: 100,
            bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000)),
        });
        this.delta = 0;
        this.transferred = 0;
        callback(null);
    }
}
exports.ProgressDifferentialDownloadCallbackTransform = ProgressDifferentialDownloadCallbackTransform;
//# sourceMappingURL=ProgressDifferentialDownloadCallbackTransform.js.map{"version":3,"file":"ProgressDifferentialDownloadCallbackTransform.js","sourceRoot":"","sources":["../../src/differentialDownloader/ProgressDifferentialDownloadCallbackTransform.ts"],"names":[],"mappings":"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","sourcesContent":["import { Transform } from \"stream\"\nimport { CancellationToken } from \"builder-util-runtime\"\n\nenum OperationKind {\n  COPY,\n  DOWNLOAD,\n}\n\nexport interface ProgressInfo {\n  total: number\n  delta: number\n  transferred: number\n  percent: number\n  bytesPerSecond: number\n}\n\nexport interface ProgressDifferentialDownloadInfo {\n  expectedByteCounts: Array<number>\n  grandTotal: number\n}\n\nexport class ProgressDifferentialDownloadCallbackTransform extends Transform {\n  private start = Date.now()\n  private transferred = 0\n  private delta = 0\n  private expectedBytes = 0\n  private index = 0\n  private operationType = OperationKind.COPY\n\n  private nextUpdate = this.start + 1000\n\n  constructor(\n    private readonly progressDifferentialDownloadInfo: ProgressDifferentialDownloadInfo,\n    private readonly cancellationToken: CancellationToken,\n    private readonly onProgress: (info: ProgressInfo) => any\n  ) {\n    super()\n  }\n\n  _transform(chunk: any, encoding: string, callback: any) {\n    if (this.cancellationToken.cancelled) {\n      callback(new Error(\"cancelled\"), null)\n      return\n    }\n\n    // Don't send progress update when copying from disk\n    if (this.operationType == OperationKind.COPY) {\n      callback(null, chunk)\n      return\n    }\n\n    this.transferred += chunk.length\n    this.delta += chunk.length\n\n    const now = Date.now()\n    if (\n      now >= this.nextUpdate &&\n      this.transferred !== this.expectedBytes /* will be emitted by endRangeDownload() */ &&\n      this.transferred !== this.progressDifferentialDownloadInfo.grandTotal /* will be emitted on _flush */\n    ) {\n      this.nextUpdate = now + 1000\n\n      this.onProgress({\n        total: this.progressDifferentialDownloadInfo.grandTotal,\n        delta: this.delta,\n        transferred: this.transferred,\n        percent: (this.transferred / this.progressDifferentialDownloadInfo.grandTotal) * 100,\n        bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000)),\n      })\n      this.delta = 0\n    }\n\n    callback(null, chunk)\n  }\n\n  beginFileCopy(): void {\n    this.operationType = OperationKind.COPY\n  }\n\n  beginRangeDownload(): void {\n    this.operationType = OperationKind.DOWNLOAD\n\n    this.expectedBytes += this.progressDifferentialDownloadInfo.expectedByteCounts[this.index++]\n  }\n\n  endRangeDownload(): void {\n    // _flush() will doour final 100%\n    if (this.transferred !== this.progressDifferentialDownloadInfo.grandTotal) {\n      this.onProgress({\n        total: this.progressDifferentialDownloadInfo.grandTotal,\n        delta: this.delta,\n        transferred: this.transferred,\n        percent: (this.transferred / this.progressDifferentialDownloadInfo.grandTotal) * 100,\n        bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000)),\n      })\n    }\n  }\n\n  // Called when we are 100% done with the connection/download\n  _flush(callback: any): void {\n    if (this.cancellationToken.cancelled) {\n      callback(new Error(\"cancelled\"))\n      return\n    }\n\n    this.onProgress({\n      total: this.progressDifferentialDownloadInfo.grandTotal,\n      delta: this.delta,\n      transferred: this.transferred,\n      percent: 100,\n      bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000)),\n    })\n    this.delta = 0\n    this.transferred = 0\n\n    callback(null)\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OperationKind = void 0;
exports.computeOperations = computeOperations;
var OperationKind;
(function (OperationKind) {
    OperationKind[OperationKind["COPY"] = 0] = "COPY";
    OperationKind[OperationKind["DOWNLOAD"] = 1] = "DOWNLOAD";
})(OperationKind || (exports.OperationKind = OperationKind = {}));
function computeOperations(oldBlockMap, newBlockMap, logger) {
    const nameToOldBlocks = buildBlockFileMap(oldBlockMap.files);
    const nameToNewBlocks = buildBlockFileMap(newBlockMap.files);
    let lastOperation = null;
    // for now only one file is supported in block map
    const blockMapFile = newBlockMap.files[0];
    const operations = [];
    const name = blockMapFile.name;
    const oldEntry = nameToOldBlocks.get(name);
    if (oldEntry == null) {
        // new file (unrealistic case for now, because in any case both blockmap contain the only file named as "file")
        throw new Error(`no file ${name} in old blockmap`);
    }
    const newFile = nameToNewBlocks.get(name);
    let changedBlockCount = 0;
    const { checksumToOffset: checksumToOldOffset, checksumToOldSize } = buildChecksumMap(nameToOldBlocks.get(name), oldEntry.offset, logger);
    let newOffset = blockMapFile.offset;
    for (let i = 0; i < newFile.checksums.length; newOffset += newFile.sizes[i], i++) {
        const blockSize = newFile.sizes[i];
        const checksum = newFile.checksums[i];
        let oldOffset = checksumToOldOffset.get(checksum);
        if (oldOffset != null && checksumToOldSize.get(checksum) !== blockSize) {
            logger.warn(`Checksum ("${checksum}") matches, but size differs (old: ${checksumToOldSize.get(checksum)}, new: ${blockSize})`);
            oldOffset = undefined;
        }
        if (oldOffset === undefined) {
            // download data from new file
            changedBlockCount++;
            if (lastOperation != null && lastOperation.kind === OperationKind.DOWNLOAD && lastOperation.end === newOffset) {
                lastOperation.end += blockSize;
            }
            else {
                lastOperation = {
                    kind: OperationKind.DOWNLOAD,
                    start: newOffset,
                    end: newOffset + blockSize,
                    // oldBlocks: null,
                };
                validateAndAdd(lastOperation, operations, checksum, i);
            }
        }
        else {
            // reuse data from old file
            if (lastOperation != null && lastOperation.kind === OperationKind.COPY && lastOperation.end === oldOffset) {
                lastOperation.end += blockSize;
                // lastOperation.oldBlocks!!.push(checksum)
            }
            else {
                lastOperation = {
                    kind: OperationKind.COPY,
                    start: oldOffset,
                    end: oldOffset + blockSize,
                    // oldBlocks: [checksum]
                };
                validateAndAdd(lastOperation, operations, checksum, i);
            }
        }
    }
    if (changedBlockCount > 0) {
        logger.info(`File${blockMapFile.name === "file" ? "" : " " + blockMapFile.name} has ${changedBlockCount} changed blocks`);
    }
    return operations;
}
const isValidateOperationRange = process.env["DIFFERENTIAL_DOWNLOAD_PLAN_BUILDER_VALIDATE_RANGES"] === "true";
function validateAndAdd(operation, operations, checksum, index) {
    if (isValidateOperationRange && operations.length !== 0) {
        const lastOperation = operations[operations.length - 1];
        if (lastOperation.kind === operation.kind && operation.start < lastOperation.end && operation.start > lastOperation.start) {
            const min = [lastOperation.start, lastOperation.end, operation.start, operation.end].reduce((p, v) => (p < v ? p : v));
            throw new Error(`operation (block index: ${index}, checksum: ${checksum}, kind: ${OperationKind[operation.kind]}) overlaps previous operation (checksum: ${checksum}):\n` +
                `abs: ${lastOperation.start} until ${lastOperation.end} and ${operation.start} until ${operation.end}\n` +
                `rel: ${lastOperation.start - min} until ${lastOperation.end - min} and ${operation.start - min} until ${operation.end - min}`);
        }
    }
    operations.push(operation);
}
function buildChecksumMap(file, fileOffset, logger) {
    const checksumToOffset = new Map();
    const checksumToSize = new Map();
    let offset = fileOffset;
    for (let i = 0; i < file.checksums.length; i++) {
        const checksum = file.checksums[i];
        const size = file.sizes[i];
        const existing = checksumToSize.get(checksum);
        if (existing === undefined) {
            checksumToOffset.set(checksum, offset);
            checksumToSize.set(checksum, size);
        }
        else if (logger.debug != null) {
            const sizeExplanation = existing === size ? "(same size)" : `(size: ${existing}, this size: ${size})`;
            logger.debug(`${checksum} duplicated in blockmap ${sizeExplanation}, it doesn't lead to broken differential downloader, just corresponding block will be skipped)`);
        }
        offset += size;
    }
    return { checksumToOffset, checksumToOldSize: checksumToSize };
}
function buildBlockFileMap(list) {
    const result = new Map();
    for (const item of list) {
        result.set(item.name, item);
    }
    return result;
}
//# sourceMappingURL=downloadPlanBuilder.js.map{"version":3,"file":"downloadPlanBuilder.js","sourceRoot":"","sources":["../../src/differentialDownloader/downloadPlanBuilder.ts"],"names":[],"mappings":"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","sourcesContent":["import { BlockMap, BlockMapFile } from \"builder-util-runtime/out/blockMapApi\"\nimport { Logger } from \"../types\"\n\nexport enum OperationKind {\n  COPY,\n  DOWNLOAD,\n}\n\nexport interface Operation {\n  kind: OperationKind\n\n  // inclusive\n  start: number\n  // exclusive\n  end: number\n\n  // debug only\n  // oldBlocks: Array<string> | null\n}\n\nexport function computeOperations(oldBlockMap: BlockMap, newBlockMap: BlockMap, logger: Logger): Array<Operation> {\n  const nameToOldBlocks = buildBlockFileMap(oldBlockMap.files)\n  const nameToNewBlocks = buildBlockFileMap(newBlockMap.files)\n\n  let lastOperation: Operation | null = null\n\n  // for now only one file is supported in block map\n  const blockMapFile: { name: string; offset: number } = newBlockMap.files[0]\n  const operations: Array<Operation> = []\n  const name = blockMapFile.name\n  const oldEntry = nameToOldBlocks.get(name)\n  if (oldEntry == null) {\n    // new file (unrealistic case for now, because in any case both blockmap contain the only file named as \"file\")\n    throw new Error(`no file ${name} in old blockmap`)\n  }\n\n  const newFile = nameToNewBlocks.get(name)!\n  let changedBlockCount = 0\n\n  const { checksumToOffset: checksumToOldOffset, checksumToOldSize } = buildChecksumMap(nameToOldBlocks.get(name)!, oldEntry.offset, logger)\n\n  let newOffset = blockMapFile.offset\n  for (let i = 0; i < newFile.checksums.length; newOffset += newFile.sizes[i], i++) {\n    const blockSize: number = newFile.sizes[i]\n    const checksum = newFile.checksums[i]\n    let oldOffset = checksumToOldOffset.get(checksum)\n    if (oldOffset != null && checksumToOldSize.get(checksum) !== blockSize) {\n      logger.warn(`Checksum (\"${checksum}\") matches, but size differs (old: ${checksumToOldSize.get(checksum)}, new: ${blockSize})`)\n      oldOffset = undefined\n    }\n\n    if (oldOffset === undefined) {\n      // download data from new file\n      changedBlockCount++\n\n      if (lastOperation != null && lastOperation.kind === OperationKind.DOWNLOAD && lastOperation.end === newOffset) {\n        lastOperation.end += blockSize\n      } else {\n        lastOperation = {\n          kind: OperationKind.DOWNLOAD,\n          start: newOffset,\n          end: newOffset + blockSize,\n          // oldBlocks: null,\n        }\n        validateAndAdd(lastOperation, operations, checksum, i)\n      }\n    } else {\n      // reuse data from old file\n      if (lastOperation != null && lastOperation.kind === OperationKind.COPY && lastOperation.end === oldOffset) {\n        lastOperation.end += blockSize\n        // lastOperation.oldBlocks!!.push(checksum)\n      } else {\n        lastOperation = {\n          kind: OperationKind.COPY,\n          start: oldOffset,\n          end: oldOffset + blockSize,\n          // oldBlocks: [checksum]\n        }\n        validateAndAdd(lastOperation, operations, checksum, i)\n      }\n    }\n  }\n\n  if (changedBlockCount > 0) {\n    logger.info(`File${blockMapFile.name === \"file\" ? \"\" : \" \" + blockMapFile.name} has ${changedBlockCount} changed blocks`)\n  }\n  return operations\n}\n\nconst isValidateOperationRange = process.env[\"DIFFERENTIAL_DOWNLOAD_PLAN_BUILDER_VALIDATE_RANGES\"] === \"true\"\n\nfunction validateAndAdd(operation: Operation, operations: Array<Operation>, checksum: string, index: number): void {\n  if (isValidateOperationRange && operations.length !== 0) {\n    const lastOperation = operations[operations.length - 1]\n    if (lastOperation.kind === operation.kind && operation.start < lastOperation.end && operation.start > lastOperation.start) {\n      const min = [lastOperation.start, lastOperation.end, operation.start, operation.end].reduce((p, v) => (p < v ? p : v))\n      throw new Error(\n        `operation (block index: ${index}, checksum: ${checksum}, kind: ${OperationKind[operation.kind]}) overlaps previous operation (checksum: ${checksum}):\\n` +\n          `abs: ${lastOperation.start} until ${lastOperation.end} and ${operation.start} until ${operation.end}\\n` +\n          `rel: ${lastOperation.start - min} until ${lastOperation.end - min} and ${operation.start - min} until ${operation.end - min}`\n      )\n    }\n  }\n  operations.push(operation)\n}\n\nfunction buildChecksumMap(file: BlockMapFile, fileOffset: number, logger: Logger) {\n  const checksumToOffset = new Map<string, number>()\n  const checksumToSize = new Map<string, number>()\n  let offset = fileOffset\n  for (let i = 0; i < file.checksums.length; i++) {\n    const checksum = file.checksums[i]\n    const size = file.sizes[i]\n\n    const existing = checksumToSize.get(checksum)\n    if (existing === undefined) {\n      checksumToOffset.set(checksum, offset)\n      checksumToSize.set(checksum, size)\n    } else if (logger.debug != null) {\n      const sizeExplanation = existing === size ? \"(same size)\" : `(size: ${existing}, this size: ${size})`\n      logger.debug(`${checksum} duplicated in blockmap ${sizeExplanation}, it doesn't lead to broken differential downloader, just corresponding block will be skipped)`)\n    }\n    offset += size\n  }\n  return { checksumToOffset, checksumToOldSize: checksumToSize }\n}\n\nfunction buildBlockFileMap(list: Array<BlockMapFile>): Map<string, BlockMapFile> {\n  const result = new Map<string, BlockMapFile>()\n  for (const item of list) {\n    result.set(item.name, item)\n  }\n  return result\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.executeTasksUsingMultipleRangeRequests = executeTasksUsingMultipleRangeRequests;
exports.checkIsRangesSupported = checkIsRangesSupported;
const builder_util_runtime_1 = require("builder-util-runtime");
const DataSplitter_1 = require("./DataSplitter");
const downloadPlanBuilder_1 = require("./downloadPlanBuilder");
function executeTasksUsingMultipleRangeRequests(differentialDownloader, tasks, out, oldFileFd, reject) {
    const w = (taskOffset) => {
        if (taskOffset >= tasks.length) {
            if (differentialDownloader.fileMetadataBuffer != null) {
                out.write(differentialDownloader.fileMetadataBuffer);
            }
            out.end();
            return;
        }
        const nextOffset = taskOffset + 1000;
        doExecuteTasks(differentialDownloader, {
            tasks,
            start: taskOffset,
            end: Math.min(tasks.length, nextOffset),
            oldFileFd,
        }, out, () => w(nextOffset), reject);
    };
    return w;
}
function doExecuteTasks(differentialDownloader, options, out, resolve, reject) {
    let ranges = "bytes=";
    let partCount = 0;
    const partIndexToTaskIndex = new Map();
    const partIndexToLength = [];
    for (let i = options.start; i < options.end; i++) {
        const task = options.tasks[i];
        if (task.kind === downloadPlanBuilder_1.OperationKind.DOWNLOAD) {
            ranges += `${task.start}-${task.end - 1}, `;
            partIndexToTaskIndex.set(partCount, i);
            partCount++;
            partIndexToLength.push(task.end - task.start);
        }
    }
    if (partCount <= 1) {
        // the only remote range - copy
        const w = (index) => {
            if (index >= options.end) {
                resolve();
                return;
            }
            const task = options.tasks[index++];
            if (task.kind === downloadPlanBuilder_1.OperationKind.COPY) {
                (0, DataSplitter_1.copyData)(task, out, options.oldFileFd, reject, () => w(index));
            }
            else {
                const requestOptions = differentialDownloader.createRequestOptions();
                requestOptions.headers.Range = `bytes=${task.start}-${task.end - 1}`;
                const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {
                    if (!checkIsRangesSupported(response, reject)) {
                        return;
                    }
                    response.pipe(out, {
                        end: false,
                    });
                    response.once("end", () => w(index));
                });
                differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject);
                request.end();
            }
        };
        w(options.start);
        return;
    }
    const requestOptions = differentialDownloader.createRequestOptions();
    requestOptions.headers.Range = ranges.substring(0, ranges.length - 2);
    const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {
        if (!checkIsRangesSupported(response, reject)) {
            return;
        }
        const contentType = (0, builder_util_runtime_1.safeGetHeader)(response, "content-type");
        const m = /^multipart\/.+?(?:; boundary=(?:(?:"(.+)")|(?:([^\s]+))))$/i.exec(contentType);
        if (m == null) {
            reject(new Error(`Content-Type "multipart/byteranges" is expected, but got "${contentType}"`));
            return;
        }
        const dicer = new DataSplitter_1.DataSplitter(out, options, partIndexToTaskIndex, m[1] || m[2], partIndexToLength, resolve);
        dicer.on("error", reject);
        response.pipe(dicer);
        response.on("end", () => {
            setTimeout(() => {
                request.abort();
                reject(new Error("Response ends without calling any handlers"));
            }, 10000);
        });
    });
    differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject);
    request.end();
}
function checkIsRangesSupported(response, reject) {
    // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.
    if (response.statusCode >= 400) {
        reject((0, builder_util_runtime_1.createHttpError)(response));
        return false;
    }
    if (response.statusCode !== 206) {
        const acceptRanges = (0, builder_util_runtime_1.safeGetHeader)(response, "accept-ranges");
        if (acceptRanges == null || acceptRanges === "none") {
            reject(new Error(`Server doesn't support Accept-Ranges (response code ${response.statusCode})`));
            return false;
        }
    }
    return true;
}
//# sourceMappingURL=multipleRangeDownloader.js.map{"version":3,"file":"multipleRangeDownloader.js","sourceRoot":"","sources":["../../src/differentialDownloader/multipleRangeDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHttpError, safeGetHeader } from \"builder-util-runtime\"\nimport { IncomingMessage } from \"http\"\nimport { Writable } from \"stream\"\nimport { copyData, DataSplitter, PartListDataTask } from \"./DataSplitter\"\nimport { DifferentialDownloader } from \"./DifferentialDownloader\"\nimport { Operation, OperationKind } from \"./downloadPlanBuilder\"\n\nexport function executeTasksUsingMultipleRangeRequests(\n  differentialDownloader: DifferentialDownloader,\n  tasks: Array<Operation>,\n  out: Writable,\n  oldFileFd: number,\n  reject: (error: Error) => void\n): (taskOffset: number) => void {\n  const w = (taskOffset: number): void => {\n    if (taskOffset >= tasks.length) {\n      if (differentialDownloader.fileMetadataBuffer != null) {\n        out.write(differentialDownloader.fileMetadataBuffer)\n      }\n      out.end()\n      return\n    }\n\n    const nextOffset = taskOffset + 1000\n    doExecuteTasks(\n      differentialDownloader,\n      {\n        tasks,\n        start: taskOffset,\n        end: Math.min(tasks.length, nextOffset),\n        oldFileFd,\n      },\n      out,\n      () => w(nextOffset),\n      reject\n    )\n  }\n  return w\n}\n\nfunction doExecuteTasks(differentialDownloader: DifferentialDownloader, options: PartListDataTask, out: Writable, resolve: () => void, reject: (error: Error) => void): void {\n  let ranges = \"bytes=\"\n  let partCount = 0\n  const partIndexToTaskIndex = new Map<number, number>()\n  const partIndexToLength: Array<number> = []\n  for (let i = options.start; i < options.end; i++) {\n    const task = options.tasks[i]\n    if (task.kind === OperationKind.DOWNLOAD) {\n      ranges += `${task.start}-${task.end - 1}, `\n      partIndexToTaskIndex.set(partCount, i)\n      partCount++\n      partIndexToLength.push(task.end - task.start)\n    }\n  }\n\n  if (partCount <= 1) {\n    // the only remote range - copy\n    const w = (index: number): void => {\n      if (index >= options.end) {\n        resolve()\n        return\n      }\n\n      const task = options.tasks[index++]\n\n      if (task.kind === OperationKind.COPY) {\n        copyData(task, out, options.oldFileFd, reject, () => w(index))\n      } else {\n        const requestOptions = differentialDownloader.createRequestOptions()\n        requestOptions.headers!.Range = `bytes=${task.start}-${task.end - 1}`\n        const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {\n          if (!checkIsRangesSupported(response, reject)) {\n            return\n          }\n\n          response.pipe(out, {\n            end: false,\n          })\n          response.once(\"end\", () => w(index))\n        })\n        differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n        request.end()\n      }\n    }\n\n    w(options.start)\n    return\n  }\n\n  const requestOptions = differentialDownloader.createRequestOptions()\n  requestOptions.headers!.Range = ranges.substring(0, ranges.length - 2)\n  const request = differentialDownloader.httpExecutor.createRequest(requestOptions, response => {\n    if (!checkIsRangesSupported(response, reject)) {\n      return\n    }\n\n    const contentType = safeGetHeader(response, \"content-type\")\n    const m = /^multipart\\/.+?(?:; boundary=(?:(?:\"(.+)\")|(?:([^\\s]+))))$/i.exec(contentType)\n    if (m == null) {\n      reject(new Error(`Content-Type \"multipart/byteranges\" is expected, but got \"${contentType}\"`))\n      return\n    }\n\n    const dicer = new DataSplitter(out, options, partIndexToTaskIndex, m[1] || m[2], partIndexToLength, resolve)\n    dicer.on(\"error\", reject)\n    response.pipe(dicer)\n\n    response.on(\"end\", () => {\n      setTimeout(() => {\n        request.abort()\n        reject(new Error(\"Response ends without calling any handlers\"))\n      }, 10000)\n    })\n  })\n  differentialDownloader.httpExecutor.addErrorAndTimeoutHandlers(request, reject)\n  request.end()\n}\n\nexport function checkIsRangesSupported(response: IncomingMessage, reject: (error: Error) => void): boolean {\n  // Electron net handles redirects automatically, our NodeJS test server doesn't use redirects - so, we don't check 3xx codes.\n  if (response.statusCode! >= 400) {\n    reject(createHttpError(response))\n    return false\n  }\n\n  if (response.statusCode !== 206) {\n    const acceptRanges = safeGetHeader(response, \"accept-ranges\")\n    if (acceptRanges == null || acceptRanges === \"none\") {\n      reject(new Error(`Server doesn't support Accept-Ranges (response code ${response.statusCode})`))\n      return false\n    }\n  }\n  return true\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ElectronHttpExecutor = exports.NET_SESSION_NAME = void 0;
exports.getNetSession = getNetSession;
const builder_util_runtime_1 = require("builder-util-runtime");
exports.NET_SESSION_NAME = "electron-updater";
function getNetSession() {
    return require("electron").session.fromPartition(exports.NET_SESSION_NAME, {
        cache: false,
    });
}
class ElectronHttpExecutor extends builder_util_runtime_1.HttpExecutor {
    constructor(proxyLoginCallback) {
        super();
        this.proxyLoginCallback = proxyLoginCallback;
        this.cachedSession = null;
    }
    async download(url, destination, options) {
        return await options.cancellationToken.createPromise((resolve, reject, onCancel) => {
            const requestOptions = {
                headers: options.headers || undefined,
                redirect: "manual",
            };
            (0, builder_util_runtime_1.configureRequestUrl)(url, requestOptions);
            (0, builder_util_runtime_1.configureRequestOptions)(requestOptions);
            this.doDownload(requestOptions, {
                destination,
                options,
                onCancel,
                callback: error => {
                    if (error == null) {
                        resolve(destination);
                    }
                    else {
                        reject(error);
                    }
                },
                responseHandler: null,
            }, 0);
        });
    }
    createRequest(options, callback) {
        // fix (node 7+) for making electron updater work when using AWS private buckets, check if headers contain Host property
        if (options.headers && options.headers.Host) {
            // set host value from headers.Host
            options.host = options.headers.Host;
            // remove header property 'Host', if not removed causes net::ERR_INVALID_ARGUMENT exception
            delete options.headers.Host;
        }
        // differential downloader can call this method very often, so, better to cache session
        if (this.cachedSession == null) {
            this.cachedSession = getNetSession();
        }
        const request = require("electron").net.request({
            ...options,
            session: this.cachedSession,
        });
        request.on("response", callback);
        if (this.proxyLoginCallback != null) {
            request.on("login", this.proxyLoginCallback);
        }
        return request;
    }
    addRedirectHandlers(request, options, reject, redirectCount, handler) {
        request.on("redirect", (statusCode, method, redirectUrl) => {
            // no way to modify request options, abort old and make a new one
            // https://github.com/electron/electron/issues/11505
            request.abort();
            if (redirectCount > this.maxRedirects) {
                reject(this.createMaxRedirectError());
            }
            else {
                handler(builder_util_runtime_1.HttpExecutor.prepareRedirectUrlOptions(redirectUrl, options));
            }
        });
    }
}
exports.ElectronHttpExecutor = ElectronHttpExecutor;
//# sourceMappingURL=electronHttpExecutor.js.map{"version":3,"file":"electronHttpExecutor.js","sourceRoot":"","sources":["../src/electronHttpExecutor.ts"],"names":[],"mappings":"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","sourcesContent":["import { DownloadOptions, HttpExecutor, configureRequestOptions, configureRequestUrl } from \"builder-util-runtime\"\nimport type { AuthInfo } from \"electron\"\nimport { RequestOptions } from \"http\"\nimport Session = Electron.Session\nimport ClientRequest = Electron.ClientRequest\n\nexport type LoginCallback = (username: string, password: string) => void\nexport const NET_SESSION_NAME = \"electron-updater\"\n\nexport function getNetSession(): Session {\n  return require(\"electron\").session.fromPartition(NET_SESSION_NAME, {\n    cache: false,\n  })\n}\n\nexport class ElectronHttpExecutor extends HttpExecutor<Electron.ClientRequest> {\n  private cachedSession: Session | null = null\n\n  constructor(private readonly proxyLoginCallback?: (authInfo: AuthInfo, callback: LoginCallback) => void) {\n    super()\n  }\n\n  async download(url: URL, destination: string, options: DownloadOptions): Promise<string> {\n    return await options.cancellationToken.createPromise<string>((resolve, reject, onCancel) => {\n      const requestOptions = {\n        headers: options.headers || undefined,\n        redirect: \"manual\",\n      }\n      configureRequestUrl(url, requestOptions)\n      configureRequestOptions(requestOptions)\n      this.doDownload(\n        requestOptions,\n        {\n          destination,\n          options,\n          onCancel,\n          callback: error => {\n            if (error == null) {\n              resolve(destination)\n            } else {\n              reject(error)\n            }\n          },\n          responseHandler: null,\n        },\n        0\n      )\n    })\n  }\n\n  createRequest(options: any, callback: (response: any) => void): Electron.ClientRequest {\n    // fix (node 7+) for making electron updater work when using AWS private buckets, check if headers contain Host property\n    if (options.headers && options.headers.Host) {\n      // set host value from headers.Host\n      options.host = options.headers.Host\n      // remove header property 'Host', if not removed causes net::ERR_INVALID_ARGUMENT exception\n      delete options.headers.Host\n    }\n\n    // differential downloader can call this method very often, so, better to cache session\n    if (this.cachedSession == null) {\n      this.cachedSession = getNetSession()\n    }\n\n    const request = require(\"electron\").net.request({\n      ...options,\n      session: this.cachedSession,\n    })\n    request.on(\"response\", callback)\n    if (this.proxyLoginCallback != null) {\n      request.on(\"login\", this.proxyLoginCallback)\n    }\n    return request\n  }\n\n  protected addRedirectHandlers(\n    request: ClientRequest,\n    options: RequestOptions,\n    reject: (error: Error) => void,\n    redirectCount: number,\n    handler: (options: RequestOptions) => void\n  ): void {\n    request.on(\"redirect\", (statusCode: number, method: string, redirectUrl: string) => {\n      // no way to modify request options, abort old and make a new one\n      // https://github.com/electron/electron/issues/11505\n      request.abort()\n\n      if (redirectCount > this.maxRedirects) {\n        reject(this.createMaxRedirectError())\n      } else {\n        handler(HttpExecutor.prepareRedirectUrlOptions(redirectUrl, options))\n      }\n    })\n  }\n}\n"]}"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.NsisUpdater = exports.MacUpdater = exports.RpmUpdater = exports.PacmanUpdater = exports.DebUpdater = exports.AppImageUpdater = exports.Provider = exports.NoOpLogger = exports.AppUpdater = exports.BaseUpdater = void 0;
const fs_extra_1 = require("fs-extra");
const path = require("path");
var BaseUpdater_1 = require("./BaseUpdater");
Object.defineProperty(exports, "BaseUpdater", { enumerable: true, get: function () { return BaseUpdater_1.BaseUpdater; } });
var AppUpdater_1 = require("./AppUpdater");
Object.defineProperty(exports, "AppUpdater", { enumerable: true, get: function () { return AppUpdater_1.AppUpdater; } });
Object.defineProperty(exports, "NoOpLogger", { enumerable: true, get: function () { return AppUpdater_1.NoOpLogger; } });
var Provider_1 = require("./providers/Provider");
Object.defineProperty(exports, "Provider", { enumerable: true, get: function () { return Provider_1.Provider; } });
var AppImageUpdater_1 = require("./AppImageUpdater");
Object.defineProperty(exports, "AppImageUpdater", { enumerable: true, get: function () { return AppImageUpdater_1.AppImageUpdater; } });
var DebUpdater_1 = require("./DebUpdater");
Object.defineProperty(exports, "DebUpdater", { enumerable: true, get: function () { return DebUpdater_1.DebUpdater; } });
var PacmanUpdater_1 = require("./PacmanUpdater");
Object.defineProperty(exports, "PacmanUpdater", { enumerable: true, get: function () { return PacmanUpdater_1.PacmanUpdater; } });
var RpmUpdater_1 = require("./RpmUpdater");
Object.defineProperty(exports, "RpmUpdater", { enumerable: true, get: function () { return RpmUpdater_1.RpmUpdater; } });
var MacUpdater_1 = require("./MacUpdater");
Object.defineProperty(exports, "MacUpdater", { enumerable: true, get: function () { return MacUpdater_1.MacUpdater; } });
var NsisUpdater_1 = require("./NsisUpdater");
Object.defineProperty(exports, "NsisUpdater", { enumerable: true, get: function () { return NsisUpdater_1.NsisUpdater; } });
__exportStar(require("./types"), exports);
// autoUpdater to mimic electron bundled autoUpdater
let _autoUpdater;
function doLoadAutoUpdater() {
    // tslint:disable:prefer-conditional-expression
    if (process.platform === "win32") {
        _autoUpdater = new (require("./NsisUpdater").NsisUpdater)();
    }
    else if (process.platform === "darwin") {
        _autoUpdater = new (require("./MacUpdater").MacUpdater)();
    }
    else {
        _autoUpdater = new (require("./AppImageUpdater").AppImageUpdater)();
        try {
            const identity = path.join(process.resourcesPath, "package-type");
            if (!(0, fs_extra_1.existsSync)(identity)) {
                return _autoUpdater;
            }
            console.info("Checking for beta autoupdate feature for deb/rpm distributions");
            const fileType = (0, fs_extra_1.readFileSync)(identity).toString().trim();
            console.info("Found package-type:", fileType);
            switch (fileType) {
                case "deb":
                    _autoUpdater = new (require("./DebUpdater").DebUpdater)();
                    break;
                case "rpm":
                    _autoUpdater = new (require("./RpmUpdater").RpmUpdater)();
                    break;
                case "pacman":
                    _autoUpdater = new (require("./PacmanUpdater").PacmanUpdater)();
                    break;
                default:
                    break;
            }
        }
        catch (error) {
            console.warn("Unable to detect 'package-type' for autoUpdater (beta rpm/deb support). If you'd like to expand support, please consider contributing to electron-builder", error.message);
        }
    }
    return _autoUpdater;
}
Object.defineProperty(exports, "autoUpdater", {
    enumerable: true,
    get: () => {
        return _autoUpdater || doLoadAutoUpdater();
    },
});
//# sourceMappingURL=main.js.map{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uCAAmD;AACnD,6BAA4B;AAI5B,6CAA2C;AAAlC,0GAAA,WAAW,OAAA;AACpB,2CAAqD;AAA5C,wGAAA,UAAU,OAAA;AAAE,wGAAA,UAAU,OAAA;AAC/B,iDAA+C;AAAtC,oGAAA,QAAQ,OAAA;AACjB,qDAAmD;AAA1C,kHAAA,eAAe,OAAA;AACxB,2CAAyC;AAAhC,wGAAA,UAAU,OAAA;AACnB,iDAA+C;AAAtC,8GAAA,aAAa,OAAA;AACtB,2CAAyC;AAAhC,wGAAA,UAAU,OAAA;AACnB,2CAAyC;AAAhC,wGAAA,UAAU,OAAA;AACnB,6CAA2C;AAAlC,0GAAA,WAAW,OAAA;AAEpB,0CAAuB;AAEvB,oDAAoD;AACpD,IAAI,YAAiB,CAAA;AAKrB,SAAS,iBAAiB;IACxB,+CAA+C;IAC/C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,WAAW,CAAC,EAAE,CAAA;IAC7D,CAAC;SAAM,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACzC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,EAAE,CAAA;IAC3D,CAAC;SAAM,CAAC;QACN,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,eAAe,CAAC,EAAE,CAAA;QACnE,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,cAAc,CAAC,CAAA;YACjE,IAAI,CAAC,IAAA,qBAAU,EAAC,QAAQ,CAAC,EAAE,CAAC;gBAC1B,OAAO,YAAY,CAAA;YACrB,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAA;YAC9E,MAAM,QAAQ,GAAG,IAAA,uBAAY,EAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAA;YACzD,OAAO,CAAC,IAAI,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAAA;YAC7C,QAAQ,QAAQ,EAAE,CAAC;gBACjB,KAAK,KAAK;oBACR,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,EAAE,CAAA;oBACzD,MAAK;gBACP,KAAK,KAAK;oBACR,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,EAAE,CAAA;oBACzD,MAAK;gBACP,KAAK,QAAQ;oBACX,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,aAAa,CAAC,EAAE,CAAA;oBAC/D,MAAK;gBACP;oBACE,MAAK;YACT,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CACV,2JAA2J,EAC3J,KAAK,CAAC,OAAO,CACd,CAAA;QACH,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAA;AACrB,CAAC;AAED,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE;IAC5C,UAAU,EAAE,IAAI;IAChB,GAAG,EAAE,GAAG,EAAE;QACR,OAAO,YAAY,IAAI,iBAAiB,EAAE,CAAA;IAC5C,CAAC;CACF,CAAC,CAAA","sourcesContent":["import { existsSync, readFileSync } from \"fs-extra\"\nimport * as path from \"path\"\nimport { AppUpdater } from \"./AppUpdater\"\nimport { UpdateInfo } from \"builder-util-runtime\"\n\nexport { BaseUpdater } from \"./BaseUpdater\"\nexport { AppUpdater, NoOpLogger } from \"./AppUpdater\"\nexport { Provider } from \"./providers/Provider\"\nexport { AppImageUpdater } from \"./AppImageUpdater\"\nexport { DebUpdater } from \"./DebUpdater\"\nexport { PacmanUpdater } from \"./PacmanUpdater\"\nexport { RpmUpdater } from \"./RpmUpdater\"\nexport { MacUpdater } from \"./MacUpdater\"\nexport { NsisUpdater } from \"./NsisUpdater\"\n\nexport * from \"./types\"\n\n// autoUpdater to mimic electron bundled autoUpdater\nlet _autoUpdater: any\n\n// required for jsdoc\nexport declare const autoUpdater: AppUpdater\n\nfunction doLoadAutoUpdater(): AppUpdater {\n  // tslint:disable:prefer-conditional-expression\n  if (process.platform === \"win32\") {\n    _autoUpdater = new (require(\"./NsisUpdater\").NsisUpdater)()\n  } else if (process.platform === \"darwin\") {\n    _autoUpdater = new (require(\"./MacUpdater\").MacUpdater)()\n  } else {\n    _autoUpdater = new (require(\"./AppImageUpdater\").AppImageUpdater)()\n    try {\n      const identity = path.join(process.resourcesPath, \"package-type\")\n      if (!existsSync(identity)) {\n        return _autoUpdater\n      }\n      console.info(\"Checking for beta autoupdate feature for deb/rpm distributions\")\n      const fileType = readFileSync(identity).toString().trim()\n      console.info(\"Found package-type:\", fileType)\n      switch (fileType) {\n        case \"deb\":\n          _autoUpdater = new (require(\"./DebUpdater\").DebUpdater)()\n          break\n        case \"rpm\":\n          _autoUpdater = new (require(\"./RpmUpdater\").RpmUpdater)()\n          break\n        case \"pacman\":\n          _autoUpdater = new (require(\"./PacmanUpdater\").PacmanUpdater)()\n          break\n        default:\n          break\n      }\n    } catch (error: any) {\n      console.warn(\n        \"Unable to detect 'package-type' for autoUpdater (beta rpm/deb support). If you'd like to expand support, please consider contributing to electron-builder\",\n        error.message\n      )\n    }\n  }\n  return _autoUpdater\n}\n\nObject.defineProperty(exports, \"autoUpdater\", {\n  enumerable: true,\n  get: () => {\n    return _autoUpdater || doLoadAutoUpdater()\n  },\n})\n\n/**\n * return null if verify signature succeed\n * return error message if verify signature failed\n */\nexport type VerifyUpdateCodeSignature = (publisherName: string[], path: string) => Promise<string | null>\n\nexport type VerifyUpdateSupport = (updateInfo: UpdateInfo) => boolean | Promise<boolean>\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isUrlProbablySupportMultiRangeRequests = isUrlProbablySupportMultiRangeRequests;
exports.createClient = createClient;
const builder_util_runtime_1 = require("builder-util-runtime");
const BitbucketProvider_1 = require("./providers/BitbucketProvider");
const GenericProvider_1 = require("./providers/GenericProvider");
const GitHubProvider_1 = require("./providers/GitHubProvider");
const KeygenProvider_1 = require("./providers/KeygenProvider");
const PrivateGitHubProvider_1 = require("./providers/PrivateGitHubProvider");
function isUrlProbablySupportMultiRangeRequests(url) {
    return !url.includes("s3.amazonaws.com");
}
function createClient(data, updater, runtimeOptions) {
    // noinspection SuspiciousTypeOfGuard
    if (typeof data === "string") {
        throw (0, builder_util_runtime_1.newError)("Please pass PublishConfiguration object", "ERR_UPDATER_INVALID_PROVIDER_CONFIGURATION");
    }
    const provider = data.provider;
    switch (provider) {
        case "github": {
            const githubOptions = data;
            const token = (githubOptions.private ? process.env["GH_TOKEN"] || process.env["GITHUB_TOKEN"] : null) || githubOptions.token;
            if (token == null) {
                return new GitHubProvider_1.GitHubProvider(githubOptions, updater, runtimeOptions);
            }
            else {
                return new PrivateGitHubProvider_1.PrivateGitHubProvider(githubOptions, updater, token, runtimeOptions);
            }
        }
        case "bitbucket":
            return new BitbucketProvider_1.BitbucketProvider(data, updater, runtimeOptions);
        case "keygen":
            return new KeygenProvider_1.KeygenProvider(data, updater, runtimeOptions);
        case "s3":
        case "spaces":
            return new GenericProvider_1.GenericProvider({
                provider: "generic",
                url: (0, builder_util_runtime_1.getS3LikeProviderBaseUrl)(data),
                channel: data.channel || null,
            }, updater, {
                ...runtimeOptions,
                // https://github.com/minio/minio/issues/5285#issuecomment-350428955
                isUseMultipleRangeRequest: false,
            });
        case "generic": {
            const options = data;
            return new GenericProvider_1.GenericProvider(options, updater, {
                ...runtimeOptions,
                isUseMultipleRangeRequest: options.useMultipleRangeRequest !== false && isUrlProbablySupportMultiRangeRequests(options.url),
            });
        }
        case "custom": {
            const options = data;
            const constructor = options.updateProvider;
            if (!constructor) {
                throw (0, builder_util_runtime_1.newError)("Custom provider not specified", "ERR_UPDATER_INVALID_PROVIDER_CONFIGURATION");
            }
            return new constructor(options, updater, runtimeOptions);
        }
        default:
            throw (0, builder_util_runtime_1.newError)(`Unsupported provider: ${provider}`, "ERR_UPDATER_UNSUPPORTED_PROVIDER");
    }
}
//# sourceMappingURL=providerFactory.js.map{"version":3,"file":"providerFactory.js","sourceRoot":"","sources":["../src/providerFactory.ts"],"names":[],"mappings":";;AAoBA,wFAEC;AAED,oCA4DC;AApFD,+DAW6B;AAE7B,qEAAiE;AACjE,iEAA6D;AAC7D,+DAA2D;AAC3D,+DAA2D;AAC3D,6EAAyE;AAGzE,SAAgB,sCAAsC,CAAC,GAAW;IAChE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAA;AAC1C,CAAC;AAED,SAAgB,YAAY,CAAC,IAA8C,EAAE,OAAmB,EAAE,cAAsC;IACtI,qCAAqC;IACrC,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAA,+BAAQ,EAAC,yCAAyC,EAAE,4CAA4C,CAAC,CAAA;IACzG,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;IAC9B,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,aAAa,GAAG,IAAqB,CAAA;YAC3C,MAAM,KAAK,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,KAAK,CAAA;YAC5H,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;gBAClB,OAAO,IAAI,+BAAc,CAAC,aAAa,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;YACnE,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,6CAAqB,CAAC,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,CAAC,CAAA;YACjF,CAAC;QACH,CAAC;QAED,KAAK,WAAW;YACd,OAAO,IAAI,qCAAiB,CAAC,IAAwB,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;QAEjF,KAAK,QAAQ;YACX,OAAO,IAAI,+BAAc,CAAC,IAAqB,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;QAE3E,KAAK,IAAI,CAAC;QACV,KAAK,QAAQ;YACX,OAAO,IAAI,iCAAe,CACxB;gBACE,QAAQ,EAAE,SAAS;gBACnB,GAAG,EAAE,IAAA,+CAAwB,EAAC,IAAI,CAAC;gBACnC,OAAO,EAAG,IAAsB,CAAC,OAAO,IAAI,IAAI;aACjD,EACD,OAAO,EACP;gBACE,GAAG,cAAc;gBACjB,oEAAoE;gBACpE,yBAAyB,EAAE,KAAK;aACjC,CACF,CAAA;QAEH,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,OAAO,GAAG,IAA4B,CAAA;YAC5C,OAAO,IAAI,iCAAe,CAAC,OAAO,EAAE,OAAO,EAAE;gBAC3C,GAAG,cAAc;gBACjB,yBAAyB,EAAE,OAAO,CAAC,uBAAuB,KAAK,KAAK,IAAI,sCAAsC,CAAC,OAAO,CAAC,GAAG,CAAC;aAC5H,CAAC,CAAA;QACJ,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,OAAO,GAAG,IAA4B,CAAA;YAC5C,MAAM,WAAW,GAAG,OAAO,CAAC,cAAc,CAAA;YAC1C,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,MAAM,IAAA,+BAAQ,EAAC,+BAA+B,EAAE,4CAA4C,CAAC,CAAA;YAC/F,CAAC;YACD,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;QAC1D,CAAC;QAED;YACE,MAAM,IAAA,+BAAQ,EAAC,yBAAyB,QAAQ,EAAE,EAAE,kCAAkC,CAAC,CAAA;IAC3F,CAAC;AACH,CAAC","sourcesContent":["import {\n  AllPublishOptions,\n  BaseS3Options,\n  BitbucketOptions,\n  CustomPublishOptions,\n  GenericServerOptions,\n  getS3LikeProviderBaseUrl,\n  GithubOptions,\n  KeygenOptions,\n  newError,\n  PublishConfiguration,\n} from \"builder-util-runtime\"\nimport { AppUpdater } from \"./AppUpdater\"\nimport { BitbucketProvider } from \"./providers/BitbucketProvider\"\nimport { GenericProvider } from \"./providers/GenericProvider\"\nimport { GitHubProvider } from \"./providers/GitHubProvider\"\nimport { KeygenProvider } from \"./providers/KeygenProvider\"\nimport { PrivateGitHubProvider } from \"./providers/PrivateGitHubProvider\"\nimport { Provider, ProviderRuntimeOptions } from \"./providers/Provider\"\n\nexport function isUrlProbablySupportMultiRangeRequests(url: string): boolean {\n  return !url.includes(\"s3.amazonaws.com\")\n}\n\nexport function createClient(data: PublishConfiguration | AllPublishOptions, updater: AppUpdater, runtimeOptions: ProviderRuntimeOptions): Provider<any> {\n  // noinspection SuspiciousTypeOfGuard\n  if (typeof data === \"string\") {\n    throw newError(\"Please pass PublishConfiguration object\", \"ERR_UPDATER_INVALID_PROVIDER_CONFIGURATION\")\n  }\n\n  const provider = data.provider\n  switch (provider) {\n    case \"github\": {\n      const githubOptions = data as GithubOptions\n      const token = (githubOptions.private ? process.env[\"GH_TOKEN\"] || process.env[\"GITHUB_TOKEN\"] : null) || githubOptions.token\n      if (token == null) {\n        return new GitHubProvider(githubOptions, updater, runtimeOptions)\n      } else {\n        return new PrivateGitHubProvider(githubOptions, updater, token, runtimeOptions)\n      }\n    }\n\n    case \"bitbucket\":\n      return new BitbucketProvider(data as BitbucketOptions, updater, runtimeOptions)\n\n    case \"keygen\":\n      return new KeygenProvider(data as KeygenOptions, updater, runtimeOptions)\n\n    case \"s3\":\n    case \"spaces\":\n      return new GenericProvider(\n        {\n          provider: \"generic\",\n          url: getS3LikeProviderBaseUrl(data),\n          channel: (data as BaseS3Options).channel || null,\n        },\n        updater,\n        {\n          ...runtimeOptions,\n          // https://github.com/minio/minio/issues/5285#issuecomment-350428955\n          isUseMultipleRangeRequest: false,\n        }\n      )\n\n    case \"generic\": {\n      const options = data as GenericServerOptions\n      return new GenericProvider(options, updater, {\n        ...runtimeOptions,\n        isUseMultipleRangeRequest: options.useMultipleRangeRequest !== false && isUrlProbablySupportMultiRangeRequests(options.url),\n      })\n    }\n\n    case \"custom\": {\n      const options = data as CustomPublishOptions\n      const constructor = options.updateProvider\n      if (!constructor) {\n        throw newError(\"Custom provider not specified\", \"ERR_UPDATER_INVALID_PROVIDER_CONFIGURATION\")\n      }\n      return new constructor(options, updater, runtimeOptions)\n    }\n\n    default:\n      throw newError(`Unsupported provider: ${provider}`, \"ERR_UPDATER_UNSUPPORTED_PROVIDER\")\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BitbucketProvider = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const util_1 = require("../util");
const Provider_1 = require("./Provider");
class BitbucketProvider extends Provider_1.Provider {
    constructor(configuration, updater, runtimeOptions) {
        super({
            ...runtimeOptions,
            isUseMultipleRangeRequest: false,
        });
        this.configuration = configuration;
        this.updater = updater;
        const { owner, slug } = configuration;
        this.baseUrl = (0, util_1.newBaseUrl)(`https://api.bitbucket.org/2.0/repositories/${owner}/${slug}/downloads`);
    }
    get channel() {
        return this.updater.channel || this.configuration.channel || "latest";
    }
    async getLatestVersion() {
        const cancellationToken = new builder_util_runtime_1.CancellationToken();
        const channelFile = (0, util_1.getChannelFilename)(this.getCustomChannelName(this.channel));
        const channelUrl = (0, util_1.newUrlFromBase)(channelFile, this.baseUrl, this.updater.isAddNoCacheQuery);
        try {
            const updateInfo = await this.httpRequest(channelUrl, undefined, cancellationToken);
            return (0, Provider_1.parseUpdateInfo)(updateInfo, channelFile, channelUrl);
        }
        catch (e) {
            throw (0, builder_util_runtime_1.newError)(`Unable to find latest version on ${this.toString()}, please ensure release exists: ${e.stack || e.message}`, "ERR_UPDATER_LATEST_VERSION_NOT_FOUND");
        }
    }
    resolveFiles(updateInfo) {
        return (0, Provider_1.resolveFiles)(updateInfo, this.baseUrl);
    }
    toString() {
        const { owner, slug } = this.configuration;
        return `Bitbucket (owner: ${owner}, slug: ${slug}, channel: ${this.channel})`;
    }
}
exports.BitbucketProvider = BitbucketProvider;
//# sourceMappingURL=BitbucketProvider.js.map{"version":3,"file":"BitbucketProvider.js","sourceRoot":"","sources":["../../src/providers/BitbucketProvider.ts"],"names":[],"mappings":";;;AAAA,+DAAgG;AAGhG,kCAAwE;AACxE,yCAA4F;AAE5F,MAAa,iBAAkB,SAAQ,mBAAoB;IAGzD,YACmB,aAA+B,EAC/B,OAAmB,EACpC,cAAsC;QAEtC,KAAK,CAAC;YACJ,GAAG,cAAc;YACjB,yBAAyB,EAAE,KAAK;SACjC,CAAC,CAAA;QAPe,kBAAa,GAAb,aAAa,CAAkB;QAC/B,YAAO,GAAP,OAAO,CAAY;QAOpC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,aAAa,CAAA;QACrC,IAAI,CAAC,OAAO,GAAG,IAAA,iBAAU,EAAC,8CAA8C,KAAK,IAAI,IAAI,YAAY,CAAC,CAAA;IACpG,CAAC;IAED,IAAY,OAAO;QACjB,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,IAAI,QAAQ,CAAA;IACvE,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,iBAAiB,GAAG,IAAI,wCAAiB,EAAE,CAAA;QACjD,MAAM,WAAW,GAAG,IAAA,yBAAkB,EAAC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;QAC/E,MAAM,UAAU,GAAG,IAAA,qBAAc,EAAC,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAA;QAC5F,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,SAAS,EAAE,iBAAiB,CAAC,CAAA;YACnF,OAAO,IAAA,0BAAe,EAAC,UAAU,EAAE,WAAW,EAAE,UAAU,CAAC,CAAA;QAC7D,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,MAAM,IAAA,+BAAQ,EAAC,oCAAoC,IAAI,CAAC,QAAQ,EAAE,mCAAmC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,sCAAsC,CAAC,CAAA;QACtK,CAAC;IACH,CAAC;IAED,YAAY,CAAC,UAAsB;QACjC,OAAO,IAAA,uBAAY,EAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IAC/C,CAAC;IAED,QAAQ;QACN,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,aAAa,CAAA;QAC1C,OAAO,qBAAqB,KAAK,WAAW,IAAI,cAAc,IAAI,CAAC,OAAO,GAAG,CAAA;IAC/E,CAAC;CACF;AAxCD,8CAwCC","sourcesContent":["import { CancellationToken, BitbucketOptions, newError, UpdateInfo } from \"builder-util-runtime\"\nimport { AppUpdater } from \"../AppUpdater\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { getChannelFilename, newBaseUrl, newUrlFromBase } from \"../util\"\nimport { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from \"./Provider\"\n\nexport class BitbucketProvider extends Provider<UpdateInfo> {\n  private readonly baseUrl: URL\n\n  constructor(\n    private readonly configuration: BitbucketOptions,\n    private readonly updater: AppUpdater,\n    runtimeOptions: ProviderRuntimeOptions\n  ) {\n    super({\n      ...runtimeOptions,\n      isUseMultipleRangeRequest: false,\n    })\n    const { owner, slug } = configuration\n    this.baseUrl = newBaseUrl(`https://api.bitbucket.org/2.0/repositories/${owner}/${slug}/downloads`)\n  }\n\n  private get channel(): string {\n    return this.updater.channel || this.configuration.channel || \"latest\"\n  }\n\n  async getLatestVersion(): Promise<UpdateInfo> {\n    const cancellationToken = new CancellationToken()\n    const channelFile = getChannelFilename(this.getCustomChannelName(this.channel))\n    const channelUrl = newUrlFromBase(channelFile, this.baseUrl, this.updater.isAddNoCacheQuery)\n    try {\n      const updateInfo = await this.httpRequest(channelUrl, undefined, cancellationToken)\n      return parseUpdateInfo(updateInfo, channelFile, channelUrl)\n    } catch (e: any) {\n      throw newError(`Unable to find latest version on ${this.toString()}, please ensure release exists: ${e.stack || e.message}`, \"ERR_UPDATER_LATEST_VERSION_NOT_FOUND\")\n    }\n  }\n\n  resolveFiles(updateInfo: UpdateInfo): Array<ResolvedUpdateFileInfo> {\n    return resolveFiles(updateInfo, this.baseUrl)\n  }\n\n  toString() {\n    const { owner, slug } = this.configuration\n    return `Bitbucket (owner: ${owner}, slug: ${slug}, channel: ${this.channel})`\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GenericProvider = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const util_1 = require("../util");
const Provider_1 = require("./Provider");
class GenericProvider extends Provider_1.Provider {
    constructor(configuration, updater, runtimeOptions) {
        super(runtimeOptions);
        this.configuration = configuration;
        this.updater = updater;
        this.baseUrl = (0, util_1.newBaseUrl)(this.configuration.url);
    }
    get channel() {
        const result = this.updater.channel || this.configuration.channel;
        return result == null ? this.getDefaultChannelName() : this.getCustomChannelName(result);
    }
    async getLatestVersion() {
        const channelFile = (0, util_1.getChannelFilename)(this.channel);
        const channelUrl = (0, util_1.newUrlFromBase)(channelFile, this.baseUrl, this.updater.isAddNoCacheQuery);
        for (let attemptNumber = 0;; attemptNumber++) {
            try {
                return (0, Provider_1.parseUpdateInfo)(await this.httpRequest(channelUrl), channelFile, channelUrl);
            }
            catch (e) {
                if (e instanceof builder_util_runtime_1.HttpError && e.statusCode === 404) {
                    throw (0, builder_util_runtime_1.newError)(`Cannot find channel "${channelFile}" update info: ${e.stack || e.message}`, "ERR_UPDATER_CHANNEL_FILE_NOT_FOUND");
                }
                else if (e.code === "ECONNREFUSED") {
                    if (attemptNumber < 3) {
                        await new Promise((resolve, reject) => {
                            try {
                                setTimeout(resolve, 1000 * attemptNumber);
                            }
                            catch (e) {
                                reject(e);
                            }
                        });
                        continue;
                    }
                }
                throw e;
            }
        }
    }
    resolveFiles(updateInfo) {
        return (0, Provider_1.resolveFiles)(updateInfo, this.baseUrl);
    }
}
exports.GenericProvider = GenericProvider;
//# sourceMappingURL=GenericProvider.js.map{"version":3,"file":"GenericProvider.js","sourceRoot":"","sources":["../../src/providers/GenericProvider.ts"],"names":[],"mappings":";;;AAAA,+DAA4F;AAG5F,kCAAwE;AACxE,yCAA4F;AAE5F,MAAa,eAAgB,SAAQ,mBAAoB;IAGvD,YACmB,aAAmC,EACnC,OAAmB,EACpC,cAAsC;QAEtC,KAAK,CAAC,cAAc,CAAC,CAAA;QAJJ,kBAAa,GAAb,aAAa,CAAsB;QACnC,YAAO,GAAP,OAAO,CAAY;QAJrB,YAAO,GAAG,IAAA,iBAAU,EAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IAQ7D,CAAC;IAED,IAAY,OAAO;QACjB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,CAAA;QACjE,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAA;IAC1F,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,WAAW,GAAG,IAAA,yBAAkB,EAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACpD,MAAM,UAAU,GAAG,IAAA,qBAAc,EAAC,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAA;QAC5F,KAAK,IAAI,aAAa,GAAG,CAAC,GAAI,aAAa,EAAE,EAAE,CAAC;YAC9C,IAAI,CAAC;gBACH,OAAO,IAAA,0BAAe,EAAC,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,CAAA;YACrF,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,IAAI,CAAC,YAAY,gCAAS,IAAI,CAAC,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;oBACnD,MAAM,IAAA,+BAAQ,EAAC,wBAAwB,WAAW,kBAAkB,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,oCAAoC,CAAC,CAAA;gBACnI,CAAC;qBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;oBACrC,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;wBACtB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;4BACpC,IAAI,CAAC;gCACH,UAAU,CAAC,OAAO,EAAE,IAAI,GAAG,aAAa,CAAC,CAAA;4BAC3C,CAAC;4BAAC,OAAO,CAAM,EAAE,CAAC;gCAChB,MAAM,CAAC,CAAC,CAAC,CAAA;4BACX,CAAC;wBACH,CAAC,CAAC,CAAA;wBACF,SAAQ;oBACV,CAAC;gBACH,CAAC;gBACD,MAAM,CAAC,CAAA;YACT,CAAC;QACH,CAAC;IACH,CAAC;IAED,YAAY,CAAC,UAAsB;QACjC,OAAO,IAAA,uBAAY,EAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IAC/C,CAAC;CACF;AA7CD,0CA6CC","sourcesContent":["import { GenericServerOptions, HttpError, newError, UpdateInfo } from \"builder-util-runtime\"\nimport { AppUpdater } from \"../AppUpdater\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { getChannelFilename, newBaseUrl, newUrlFromBase } from \"../util\"\nimport { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from \"./Provider\"\n\nexport class GenericProvider extends Provider<UpdateInfo> {\n  private readonly baseUrl = newBaseUrl(this.configuration.url)\n\n  constructor(\n    private readonly configuration: GenericServerOptions,\n    private readonly updater: AppUpdater,\n    runtimeOptions: ProviderRuntimeOptions\n  ) {\n    super(runtimeOptions)\n  }\n\n  private get channel(): string {\n    const result = this.updater.channel || this.configuration.channel\n    return result == null ? this.getDefaultChannelName() : this.getCustomChannelName(result)\n  }\n\n  async getLatestVersion(): Promise<UpdateInfo> {\n    const channelFile = getChannelFilename(this.channel)\n    const channelUrl = newUrlFromBase(channelFile, this.baseUrl, this.updater.isAddNoCacheQuery)\n    for (let attemptNumber = 0; ; attemptNumber++) {\n      try {\n        return parseUpdateInfo(await this.httpRequest(channelUrl), channelFile, channelUrl)\n      } catch (e: any) {\n        if (e instanceof HttpError && e.statusCode === 404) {\n          throw newError(`Cannot find channel \"${channelFile}\" update info: ${e.stack || e.message}`, \"ERR_UPDATER_CHANNEL_FILE_NOT_FOUND\")\n        } else if (e.code === \"ECONNREFUSED\") {\n          if (attemptNumber < 3) {\n            await new Promise((resolve, reject) => {\n              try {\n                setTimeout(resolve, 1000 * attemptNumber)\n              } catch (e: any) {\n                reject(e)\n              }\n            })\n            continue\n          }\n        }\n        throw e\n      }\n    }\n  }\n\n  resolveFiles(updateInfo: UpdateInfo): Array<ResolvedUpdateFileInfo> {\n    return resolveFiles(updateInfo, this.baseUrl)\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GitHubProvider = exports.BaseGitHubProvider = void 0;
exports.computeReleaseNotes = computeReleaseNotes;
const builder_util_runtime_1 = require("builder-util-runtime");
const semver = require("semver");
const url_1 = require("url");
const util_1 = require("../util");
const Provider_1 = require("./Provider");
const hrefRegExp = /\/tag\/([^/]+)$/;
class BaseGitHubProvider extends Provider_1.Provider {
    constructor(options, defaultHost, runtimeOptions) {
        super({
            ...runtimeOptions,
            /* because GitHib uses S3 */
            isUseMultipleRangeRequest: false,
        });
        this.options = options;
        this.baseUrl = (0, util_1.newBaseUrl)((0, builder_util_runtime_1.githubUrl)(options, defaultHost));
        const apiHost = defaultHost === "github.com" ? "api.github.com" : defaultHost;
        this.baseApiUrl = (0, util_1.newBaseUrl)((0, builder_util_runtime_1.githubUrl)(options, apiHost));
    }
    computeGithubBasePath(result) {
        // https://github.com/electron-userland/electron-builder/issues/1903#issuecomment-320881211
        const host = this.options.host;
        return host && !["github.com", "api.github.com"].includes(host) ? `/api/v3${result}` : result;
    }
}
exports.BaseGitHubProvider = BaseGitHubProvider;
class GitHubProvider extends BaseGitHubProvider {
    constructor(options, updater, runtimeOptions) {
        super(options, "github.com", runtimeOptions);
        this.options = options;
        this.updater = updater;
    }
    get channel() {
        const result = this.updater.channel || this.options.channel;
        return result == null ? this.getDefaultChannelName() : this.getCustomChannelName(result);
    }
    async getLatestVersion() {
        var _a, _b, _c, _d, _e;
        const cancellationToken = new builder_util_runtime_1.CancellationToken();
        const feedXml = (await this.httpRequest((0, util_1.newUrlFromBase)(`${this.basePath}.atom`, this.baseUrl), {
            accept: "application/xml, application/atom+xml, text/xml, */*",
        }, cancellationToken));
        const feed = (0, builder_util_runtime_1.parseXml)(feedXml);
        // noinspection TypeScriptValidateJSTypes
        let latestRelease = feed.element("entry", false, `No published versions on GitHub`);
        let tag = null;
        try {
            if (this.updater.allowPrerelease) {
                const currentChannel = ((_a = this.updater) === null || _a === void 0 ? void 0 : _a.channel) || ((_b = semver.prerelease(this.updater.currentVersion)) === null || _b === void 0 ? void 0 : _b[0]) || null;
                if (currentChannel === null) {
                    // noinspection TypeScriptValidateJSTypes
                    tag = hrefRegExp.exec(latestRelease.element("link").attribute("href"))[1];
                }
                else {
                    for (const element of feed.getElements("entry")) {
                        // noinspection TypeScriptValidateJSTypes
                        const hrefElement = hrefRegExp.exec(element.element("link").attribute("href"));
                        // If this is null then something is wrong and skip this release
                        if (hrefElement === null)
                            continue;
                        // This Release's Tag
                        const hrefTag = hrefElement[1];
                        //Get Channel from this release's tag
                        const hrefChannel = ((_c = semver.prerelease(hrefTag)) === null || _c === void 0 ? void 0 : _c[0]) || null;
                        const shouldFetchVersion = !currentChannel || ["alpha", "beta"].includes(currentChannel);
                        const isCustomChannel = hrefChannel !== null && !["alpha", "beta"].includes(String(hrefChannel));
                        // Allow moving from alpha to beta but not down
                        const channelMismatch = currentChannel === "beta" && hrefChannel === "alpha";
                        if (shouldFetchVersion && !isCustomChannel && !channelMismatch) {
                            tag = hrefTag;
                            break;
                        }
                        const isNextPreRelease = hrefChannel && hrefChannel === currentChannel;
                        if (isNextPreRelease) {
                            tag = hrefTag;
                            break;
                        }
                    }
                }
            }
            else {
                tag = await this.getLatestTagName(cancellationToken);
                for (const element of feed.getElements("entry")) {
                    // noinspection TypeScriptValidateJSTypes
                    if (hrefRegExp.exec(element.element("link").attribute("href"))[1] === tag) {
                        latestRelease = element;
                        break;
                    }
                }
            }
        }
        catch (e) {
            throw (0, builder_util_runtime_1.newError)(`Cannot parse releases feed: ${e.stack || e.message},\nXML:\n${feedXml}`, "ERR_UPDATER_INVALID_RELEASE_FEED");
        }
        if (tag == null) {
            throw (0, builder_util_runtime_1.newError)(`No published versions on GitHub`, "ERR_UPDATER_NO_PUBLISHED_VERSIONS");
        }
        let rawData;
        let channelFile = "";
        let channelFileUrl = "";
        const fetchData = async (channelName) => {
            channelFile = (0, util_1.getChannelFilename)(channelName);
            channelFileUrl = (0, util_1.newUrlFromBase)(this.getBaseDownloadPath(String(tag), channelFile), this.baseUrl);
            const requestOptions = this.createRequestOptions(channelFileUrl);
            try {
                return (await this.executor.request(requestOptions, cancellationToken));
            }
            catch (e) {
                if (e instanceof builder_util_runtime_1.HttpError && e.statusCode === 404) {
                    throw (0, builder_util_runtime_1.newError)(`Cannot find ${channelFile} in the latest release artifacts (${channelFileUrl}): ${e.stack || e.message}`, "ERR_UPDATER_CHANNEL_FILE_NOT_FOUND");
                }
                throw e;
            }
        };
        try {
            let channel = this.channel;
            if (this.updater.allowPrerelease && ((_d = semver.prerelease(tag)) === null || _d === void 0 ? void 0 : _d[0])) {
                channel = this.getCustomChannelName(String((_e = semver.prerelease(tag)) === null || _e === void 0 ? void 0 : _e[0]));
            }
            rawData = await fetchData(channel);
        }
        catch (e) {
            if (this.updater.allowPrerelease) {
                // Allow fallback to `latest.yml`
                rawData = await fetchData(this.getDefaultChannelName());
            }
            else {
                throw e;
            }
        }
        const result = (0, Provider_1.parseUpdateInfo)(rawData, channelFile, channelFileUrl);
        if (result.releaseName == null) {
            result.releaseName = latestRelease.elementValueOrEmpty("title");
        }
        if (result.releaseNotes == null) {
            result.releaseNotes = computeReleaseNotes(this.updater.currentVersion, this.updater.fullChangelog, feed, latestRelease);
        }
        return {
            tag: tag,
            ...result,
        };
    }
    async getLatestTagName(cancellationToken) {
        const options = this.options;
        // do not use API for GitHub to avoid limit, only for custom host or GitHub Enterprise
        const url = options.host == null || options.host === "github.com"
            ? (0, util_1.newUrlFromBase)(`${this.basePath}/latest`, this.baseUrl)
            : new url_1.URL(`${this.computeGithubBasePath(`/repos/${options.owner}/${options.repo}/releases`)}/latest`, this.baseApiUrl);
        try {
            const rawData = await this.httpRequest(url, { Accept: "application/json" }, cancellationToken);
            if (rawData == null) {
                return null;
            }
            const releaseInfo = JSON.parse(rawData);
            return releaseInfo.tag_name;
        }
        catch (e) {
            throw (0, builder_util_runtime_1.newError)(`Unable to find latest version on GitHub (${url}), please ensure a production release exists: ${e.stack || e.message}`, "ERR_UPDATER_LATEST_VERSION_NOT_FOUND");
        }
    }
    get basePath() {
        return `/${this.options.owner}/${this.options.repo}/releases`;
    }
    resolveFiles(updateInfo) {
        // still replace space to - due to backward compatibility
        return (0, Provider_1.resolveFiles)(updateInfo, this.baseUrl, p => this.getBaseDownloadPath(updateInfo.tag, p.replace(/ /g, "-")));
    }
    getBaseDownloadPath(tag, fileName) {
        return `${this.basePath}/download/${tag}/${fileName}`;
    }
}
exports.GitHubProvider = GitHubProvider;
function getNoteValue(parent) {
    const result = parent.elementValueOrEmpty("content");
    // GitHub reports empty notes as <content>No content.</content>
    return result === "No content." ? "" : result;
}
function computeReleaseNotes(currentVersion, isFullChangelog, feed, latestRelease) {
    if (!isFullChangelog) {
        return getNoteValue(latestRelease);
    }
    const releaseNotes = [];
    for (const release of feed.getElements("entry")) {
        // noinspection TypeScriptValidateJSTypes
        const versionRelease = /\/tag\/v?([^/]+)$/.exec(release.element("link").attribute("href"))[1];
        if (semver.lt(currentVersion, versionRelease)) {
            releaseNotes.push({
                version: versionRelease,
                note: getNoteValue(release),
            });
        }
    }
    return releaseNotes.sort((a, b) => semver.rcompare(a.version, b.version));
}
//# sourceMappingURL=GitHubProvider.js.map{"version":3,"file":"GitHubProvider.js","sourceRoot":"","sources":["../../src/providers/GitHubProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { CancellationToken, GithubOptions, githubUrl, HttpError, newError, parseXml, ReleaseNoteInfo, UpdateInfo, XElement } from \"builder-util-runtime\"\nimport * as semver from \"semver\"\nimport { URL } from \"url\"\nimport { AppUpdater } from \"../AppUpdater\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { getChannelFilename, newBaseUrl, newUrlFromBase } from \"../util\"\nimport { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from \"./Provider\"\n\nconst hrefRegExp = /\\/tag\\/([^/]+)$/\n\ninterface GithubUpdateInfo extends UpdateInfo {\n  tag: string\n}\nexport abstract class BaseGitHubProvider<T extends UpdateInfo> extends Provider<T> {\n  // so, we don't need to parse port (because node http doesn't support host as url does)\n  protected readonly baseUrl: URL\n  protected readonly baseApiUrl: URL\n\n  protected constructor(\n    protected readonly options: GithubOptions,\n    defaultHost: string,\n    runtimeOptions: ProviderRuntimeOptions\n  ) {\n    super({\n      ...runtimeOptions,\n      /* because GitHib uses S3 */\n      isUseMultipleRangeRequest: false,\n    })\n\n    this.baseUrl = newBaseUrl(githubUrl(options, defaultHost))\n    const apiHost = defaultHost === \"github.com\" ? \"api.github.com\" : defaultHost\n    this.baseApiUrl = newBaseUrl(githubUrl(options, apiHost))\n  }\n\n  protected computeGithubBasePath(result: string): string {\n    // https://github.com/electron-userland/electron-builder/issues/1903#issuecomment-320881211\n    const host = this.options.host\n    return host && ![\"github.com\", \"api.github.com\"].includes(host) ? `/api/v3${result}` : result\n  }\n}\n\nexport class GitHubProvider extends BaseGitHubProvider<GithubUpdateInfo> {\n  constructor(\n    protected readonly options: GithubOptions,\n    private readonly updater: AppUpdater,\n    runtimeOptions: ProviderRuntimeOptions\n  ) {\n    super(options, \"github.com\", runtimeOptions)\n  }\n\n  private get channel(): string {\n    const result = this.updater.channel || this.options.channel\n    return result == null ? this.getDefaultChannelName() : this.getCustomChannelName(result)\n  }\n\n  async getLatestVersion(): Promise<GithubUpdateInfo> {\n    const cancellationToken = new CancellationToken()\n\n    const feedXml: string = (await this.httpRequest(\n      newUrlFromBase(`${this.basePath}.atom`, this.baseUrl),\n      {\n        accept: \"application/xml, application/atom+xml, text/xml, */*\",\n      },\n      cancellationToken\n    ))!\n\n    const feed = parseXml(feedXml)\n    // noinspection TypeScriptValidateJSTypes\n    let latestRelease = feed.element(\"entry\", false, `No published versions on GitHub`)\n    let tag: string | null = null\n    try {\n      if (this.updater.allowPrerelease) {\n        const currentChannel = this.updater?.channel || (semver.prerelease(this.updater.currentVersion)?.[0] as string) || null\n\n        if (currentChannel === null) {\n          // noinspection TypeScriptValidateJSTypes\n          tag = hrefRegExp.exec(latestRelease.element(\"link\").attribute(\"href\"))![1]\n        } else {\n          for (const element of feed.getElements(\"entry\")) {\n            // noinspection TypeScriptValidateJSTypes\n            const hrefElement = hrefRegExp.exec(element.element(\"link\").attribute(\"href\"))!\n\n            // If this is null then something is wrong and skip this release\n            if (hrefElement === null) continue\n\n            // This Release's Tag\n            const hrefTag = hrefElement[1]\n            //Get Channel from this release's tag\n            const hrefChannel = (semver.prerelease(hrefTag)?.[0] as string) || null\n\n            const shouldFetchVersion = !currentChannel || [\"alpha\", \"beta\"].includes(currentChannel)\n            const isCustomChannel = hrefChannel !== null && ![\"alpha\", \"beta\"].includes(String(hrefChannel))\n            // Allow moving from alpha to beta but not down\n            const channelMismatch = currentChannel === \"beta\" && hrefChannel === \"alpha\"\n\n            if (shouldFetchVersion && !isCustomChannel && !channelMismatch) {\n              tag = hrefTag\n              break\n            }\n\n            const isNextPreRelease = hrefChannel && hrefChannel === currentChannel\n            if (isNextPreRelease) {\n              tag = hrefTag\n              break\n            }\n          }\n        }\n      } else {\n        tag = await this.getLatestTagName(cancellationToken)\n        for (const element of feed.getElements(\"entry\")) {\n          // noinspection TypeScriptValidateJSTypes\n          if (hrefRegExp.exec(element.element(\"link\").attribute(\"href\"))![1] === tag) {\n            latestRelease = element\n            break\n          }\n        }\n      }\n    } catch (e: any) {\n      throw newError(`Cannot parse releases feed: ${e.stack || e.message},\\nXML:\\n${feedXml}`, \"ERR_UPDATER_INVALID_RELEASE_FEED\")\n    }\n\n    if (tag == null) {\n      throw newError(`No published versions on GitHub`, \"ERR_UPDATER_NO_PUBLISHED_VERSIONS\")\n    }\n\n    let rawData: string\n    let channelFile = \"\"\n    let channelFileUrl: any = \"\"\n    const fetchData = async (channelName: string) => {\n      channelFile = getChannelFilename(channelName)\n      channelFileUrl = newUrlFromBase(this.getBaseDownloadPath(String(tag), channelFile), this.baseUrl)\n      const requestOptions = this.createRequestOptions(channelFileUrl)\n      try {\n        return (await this.executor.request(requestOptions, cancellationToken))!\n      } catch (e: any) {\n        if (e instanceof HttpError && e.statusCode === 404) {\n          throw newError(`Cannot find ${channelFile} in the latest release artifacts (${channelFileUrl}): ${e.stack || e.message}`, \"ERR_UPDATER_CHANNEL_FILE_NOT_FOUND\")\n        }\n        throw e\n      }\n    }\n\n    try {\n      let channel = this.channel\n      if (this.updater.allowPrerelease && semver.prerelease(tag)?.[0]) {\n        channel = this.getCustomChannelName(String(semver.prerelease(tag)?.[0]))\n      }\n      rawData = await fetchData(channel)\n    } catch (e: any) {\n      if (this.updater.allowPrerelease) {\n        // Allow fallback to `latest.yml`\n        rawData = await fetchData(this.getDefaultChannelName())\n      } else {\n        throw e\n      }\n    }\n\n    const result = parseUpdateInfo(rawData, channelFile, channelFileUrl)\n    if (result.releaseName == null) {\n      result.releaseName = latestRelease.elementValueOrEmpty(\"title\")\n    }\n\n    if (result.releaseNotes == null) {\n      result.releaseNotes = computeReleaseNotes(this.updater.currentVersion, this.updater.fullChangelog, feed, latestRelease)\n    }\n    return {\n      tag: tag,\n      ...result,\n    }\n  }\n\n  private async getLatestTagName(cancellationToken: CancellationToken): Promise<string | null> {\n    const options = this.options\n    // do not use API for GitHub to avoid limit, only for custom host or GitHub Enterprise\n    const url =\n      options.host == null || options.host === \"github.com\"\n        ? newUrlFromBase(`${this.basePath}/latest`, this.baseUrl)\n        : new URL(`${this.computeGithubBasePath(`/repos/${options.owner}/${options.repo}/releases`)}/latest`, this.baseApiUrl)\n    try {\n      const rawData = await this.httpRequest(url, { Accept: \"application/json\" }, cancellationToken)\n      if (rawData == null) {\n        return null\n      }\n\n      const releaseInfo: GithubReleaseInfo = JSON.parse(rawData)\n      return releaseInfo.tag_name\n    } catch (e: any) {\n      throw newError(`Unable to find latest version on GitHub (${url}), please ensure a production release exists: ${e.stack || e.message}`, \"ERR_UPDATER_LATEST_VERSION_NOT_FOUND\")\n    }\n  }\n\n  private get basePath(): string {\n    return `/${this.options.owner}/${this.options.repo}/releases`\n  }\n\n  resolveFiles(updateInfo: GithubUpdateInfo): Array<ResolvedUpdateFileInfo> {\n    // still replace space to - due to backward compatibility\n    return resolveFiles(updateInfo, this.baseUrl, p => this.getBaseDownloadPath(updateInfo.tag, p.replace(/ /g, \"-\")))\n  }\n\n  private getBaseDownloadPath(tag: string, fileName: string): string {\n    return `${this.basePath}/download/${tag}/${fileName}`\n  }\n}\n\ninterface GithubReleaseInfo {\n  readonly tag_name: string\n}\n\nfunction getNoteValue(parent: XElement): string {\n  const result = parent.elementValueOrEmpty(\"content\")\n  // GitHub reports empty notes as <content>No content.</content>\n  return result === \"No content.\" ? \"\" : result\n}\n\nexport function computeReleaseNotes(currentVersion: semver.SemVer, isFullChangelog: boolean, feed: XElement, latestRelease: any): string | Array<ReleaseNoteInfo> | null {\n  if (!isFullChangelog) {\n    return getNoteValue(latestRelease)\n  }\n\n  const releaseNotes: Array<ReleaseNoteInfo> = []\n  for (const release of feed.getElements(\"entry\")) {\n    // noinspection TypeScriptValidateJSTypes\n    const versionRelease = /\\/tag\\/v?([^/]+)$/.exec(release.element(\"link\").attribute(\"href\"))![1]\n    if (semver.lt(currentVersion, versionRelease)) {\n      releaseNotes.push({\n        version: versionRelease,\n        note: getNoteValue(release),\n      })\n    }\n  }\n  return releaseNotes.sort((a, b) => semver.rcompare(a.version, b.version))\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.KeygenProvider = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const util_1 = require("../util");
const Provider_1 = require("./Provider");
class KeygenProvider extends Provider_1.Provider {
    constructor(configuration, updater, runtimeOptions) {
        super({
            ...runtimeOptions,
            isUseMultipleRangeRequest: false,
        });
        this.configuration = configuration;
        this.updater = updater;
        this.defaultHostname = "api.keygen.sh";
        const host = this.configuration.host || this.defaultHostname;
        this.baseUrl = (0, util_1.newBaseUrl)(`https://${host}/v1/accounts/${this.configuration.account}/artifacts?product=${this.configuration.product}`);
    }
    get channel() {
        return this.updater.channel || this.configuration.channel || "stable";
    }
    async getLatestVersion() {
        const cancellationToken = new builder_util_runtime_1.CancellationToken();
        const channelFile = (0, util_1.getChannelFilename)(this.getCustomChannelName(this.channel));
        const channelUrl = (0, util_1.newUrlFromBase)(channelFile, this.baseUrl, this.updater.isAddNoCacheQuery);
        try {
            const updateInfo = await this.httpRequest(channelUrl, {
                Accept: "application/vnd.api+json",
                "Keygen-Version": "1.1",
            }, cancellationToken);
            return (0, Provider_1.parseUpdateInfo)(updateInfo, channelFile, channelUrl);
        }
        catch (e) {
            throw (0, builder_util_runtime_1.newError)(`Unable to find latest version on ${this.toString()}, please ensure release exists: ${e.stack || e.message}`, "ERR_UPDATER_LATEST_VERSION_NOT_FOUND");
        }
    }
    resolveFiles(updateInfo) {
        return (0, Provider_1.resolveFiles)(updateInfo, this.baseUrl);
    }
    toString() {
        const { account, product, platform } = this.configuration;
        return `Keygen (account: ${account}, product: ${product}, platform: ${platform}, channel: ${this.channel})`;
    }
}
exports.KeygenProvider = KeygenProvider;
//# sourceMappingURL=KeygenProvider.js.map{"version":3,"file":"KeygenProvider.js","sourceRoot":"","sources":["../../src/providers/KeygenProvider.ts"],"names":[],"mappings":";;;AAAA,+DAA6F;AAG7F,kCAAwE;AACxE,yCAA4F;AAE5F,MAAa,cAAe,SAAQ,mBAAoB;IAItD,YACmB,aAA4B,EAC5B,OAAmB,EACpC,cAAsC;QAEtC,KAAK,CAAC;YACJ,GAAG,cAAc;YACjB,yBAAyB,EAAE,KAAK;SACjC,CAAC,CAAA;QAPe,kBAAa,GAAb,aAAa,CAAe;QAC5B,YAAO,GAAP,OAAO,CAAY;QALrB,oBAAe,GAAG,eAAe,CAAA;QAYhD,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,IAAI,IAAI,CAAC,eAAe,CAAA;QAC5D,IAAI,CAAC,OAAO,GAAG,IAAA,iBAAU,EAAC,WAAW,IAAI,gBAAgB,IAAI,CAAC,aAAa,CAAC,OAAO,sBAAsB,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAA;IACxI,CAAC;IAED,IAAY,OAAO;QACjB,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,IAAI,QAAQ,CAAA;IACvE,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,iBAAiB,GAAG,IAAI,wCAAiB,EAAE,CAAA;QACjD,MAAM,WAAW,GAAG,IAAA,yBAAkB,EAAC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;QAC/E,MAAM,UAAU,GAAG,IAAA,qBAAc,EAAC,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAA;QAC5F,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,WAAW,CACvC,UAAU,EACV;gBACE,MAAM,EAAE,0BAA0B;gBAClC,gBAAgB,EAAE,KAAK;aACxB,EACD,iBAAiB,CAClB,CAAA;YACD,OAAO,IAAA,0BAAe,EAAC,UAAU,EAAE,WAAW,EAAE,UAAU,CAAC,CAAA;QAC7D,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,MAAM,IAAA,+BAAQ,EAAC,oCAAoC,IAAI,CAAC,QAAQ,EAAE,mCAAmC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,sCAAsC,CAAC,CAAA;QACtK,CAAC;IACH,CAAC;IAED,YAAY,CAAC,UAAsB;QACjC,OAAO,IAAA,uBAAY,EAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;IAC/C,CAAC;IAED,QAAQ;QACN,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,aAAa,CAAA;QACzD,OAAO,oBAAoB,OAAO,cAAc,OAAO,eAAe,QAAQ,cAAc,IAAI,CAAC,OAAO,GAAG,CAAA;IAC7G,CAAC;CACF;AAhDD,wCAgDC","sourcesContent":["import { CancellationToken, KeygenOptions, newError, UpdateInfo } from \"builder-util-runtime\"\nimport { AppUpdater } from \"../AppUpdater\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { getChannelFilename, newBaseUrl, newUrlFromBase } from \"../util\"\nimport { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from \"./Provider\"\n\nexport class KeygenProvider extends Provider<UpdateInfo> {\n  private readonly defaultHostname = \"api.keygen.sh\"\n  private readonly baseUrl: URL\n\n  constructor(\n    private readonly configuration: KeygenOptions,\n    private readonly updater: AppUpdater,\n    runtimeOptions: ProviderRuntimeOptions\n  ) {\n    super({\n      ...runtimeOptions,\n      isUseMultipleRangeRequest: false,\n    })\n    const host = this.configuration.host || this.defaultHostname\n    this.baseUrl = newBaseUrl(`https://${host}/v1/accounts/${this.configuration.account}/artifacts?product=${this.configuration.product}`)\n  }\n\n  private get channel(): string {\n    return this.updater.channel || this.configuration.channel || \"stable\"\n  }\n\n  async getLatestVersion(): Promise<UpdateInfo> {\n    const cancellationToken = new CancellationToken()\n    const channelFile = getChannelFilename(this.getCustomChannelName(this.channel))\n    const channelUrl = newUrlFromBase(channelFile, this.baseUrl, this.updater.isAddNoCacheQuery)\n    try {\n      const updateInfo = await this.httpRequest(\n        channelUrl,\n        {\n          Accept: \"application/vnd.api+json\",\n          \"Keygen-Version\": \"1.1\",\n        },\n        cancellationToken\n      )\n      return parseUpdateInfo(updateInfo, channelFile, channelUrl)\n    } catch (e: any) {\n      throw newError(`Unable to find latest version on ${this.toString()}, please ensure release exists: ${e.stack || e.message}`, \"ERR_UPDATER_LATEST_VERSION_NOT_FOUND\")\n    }\n  }\n\n  resolveFiles(updateInfo: UpdateInfo): Array<ResolvedUpdateFileInfo> {\n    return resolveFiles(updateInfo, this.baseUrl)\n  }\n\n  toString() {\n    const { account, product, platform } = this.configuration\n    return `Keygen (account: ${account}, product: ${product}, platform: ${platform}, channel: ${this.channel})`\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PrivateGitHubProvider = void 0;
const builder_util_runtime_1 = require("builder-util-runtime");
const js_yaml_1 = require("js-yaml");
const path = require("path");
const url_1 = require("url");
const util_1 = require("../util");
const GitHubProvider_1 = require("./GitHubProvider");
const Provider_1 = require("./Provider");
class PrivateGitHubProvider extends GitHubProvider_1.BaseGitHubProvider {
    constructor(options, updater, token, runtimeOptions) {
        super(options, "api.github.com", runtimeOptions);
        this.updater = updater;
        this.token = token;
    }
    createRequestOptions(url, headers) {
        const result = super.createRequestOptions(url, headers);
        result.redirect = "manual";
        return result;
    }
    async getLatestVersion() {
        const cancellationToken = new builder_util_runtime_1.CancellationToken();
        const channelFile = (0, util_1.getChannelFilename)(this.getDefaultChannelName());
        const releaseInfo = await this.getLatestVersionInfo(cancellationToken);
        const asset = releaseInfo.assets.find(it => it.name === channelFile);
        if (asset == null) {
            // html_url must be always, but just to be sure
            throw (0, builder_util_runtime_1.newError)(`Cannot find ${channelFile} in the release ${releaseInfo.html_url || releaseInfo.name}`, "ERR_UPDATER_CHANNEL_FILE_NOT_FOUND");
        }
        const url = new url_1.URL(asset.url);
        let result;
        try {
            result = (0, js_yaml_1.load)((await this.httpRequest(url, this.configureHeaders("application/octet-stream"), cancellationToken)));
        }
        catch (e) {
            if (e instanceof builder_util_runtime_1.HttpError && e.statusCode === 404) {
                throw (0, builder_util_runtime_1.newError)(`Cannot find ${channelFile} in the latest release artifacts (${url}): ${e.stack || e.message}`, "ERR_UPDATER_CHANNEL_FILE_NOT_FOUND");
            }
            throw e;
        }
        ;
        result.assets = releaseInfo.assets;
        return result;
    }
    get fileExtraDownloadHeaders() {
        return this.configureHeaders("application/octet-stream");
    }
    configureHeaders(accept) {
        return {
            accept,
            authorization: `token ${this.token}`,
        };
    }
    async getLatestVersionInfo(cancellationToken) {
        const allowPrerelease = this.updater.allowPrerelease;
        let basePath = this.basePath;
        if (!allowPrerelease) {
            basePath = `${basePath}/latest`;
        }
        const url = (0, util_1.newUrlFromBase)(basePath, this.baseUrl);
        try {
            const version = JSON.parse((await this.httpRequest(url, this.configureHeaders("application/vnd.github.v3+json"), cancellationToken)));
            if (allowPrerelease) {
                return version.find(it => it.prerelease) || version[0];
            }
            else {
                return version;
            }
        }
        catch (e) {
            throw (0, builder_util_runtime_1.newError)(`Unable to find latest version on GitHub (${url}), please ensure a production release exists: ${e.stack || e.message}`, "ERR_UPDATER_LATEST_VERSION_NOT_FOUND");
        }
    }
    get basePath() {
        return this.computeGithubBasePath(`/repos/${this.options.owner}/${this.options.repo}/releases`);
    }
    resolveFiles(updateInfo) {
        return (0, Provider_1.getFileList)(updateInfo).map(it => {
            const name = path.posix.basename(it.url).replace(/ /g, "-");
            const asset = updateInfo.assets.find(it => it != null && it.name === name);
            if (asset == null) {
                throw (0, builder_util_runtime_1.newError)(`Cannot find asset "${name}" in: ${JSON.stringify(updateInfo.assets, null, 2)}`, "ERR_UPDATER_ASSET_NOT_FOUND");
            }
            return {
                url: new url_1.URL(asset.url),
                info: it,
            };
        });
    }
}
exports.PrivateGitHubProvider = PrivateGitHubProvider;
//# sourceMappingURL=PrivateGitHubProvider.js.map{"version":3,"file":"PrivateGitHubProvider.js","sourceRoot":"","sources":["../../src/providers/PrivateGitHubProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import { CancellationToken, GithubOptions, HttpError, newError, UpdateInfo } from \"builder-util-runtime\"\nimport { OutgoingHttpHeaders, RequestOptions } from \"http\"\nimport { load } from \"js-yaml\"\nimport * as path from \"path\"\nimport { AppUpdater } from \"../AppUpdater\"\nimport { URL } from \"url\"\nimport { getChannelFilename, newUrlFromBase } from \"../util\"\nimport { BaseGitHubProvider } from \"./GitHubProvider\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { getFileList, ProviderRuntimeOptions } from \"./Provider\"\n\nexport interface PrivateGitHubUpdateInfo extends UpdateInfo {\n  assets: Array<Asset>\n}\n\nexport class PrivateGitHubProvider extends BaseGitHubProvider<PrivateGitHubUpdateInfo> {\n  constructor(\n    options: GithubOptions,\n    private readonly updater: AppUpdater,\n    private readonly token: string,\n    runtimeOptions: ProviderRuntimeOptions\n  ) {\n    super(options, \"api.github.com\", runtimeOptions)\n  }\n\n  protected createRequestOptions(url: URL, headers?: OutgoingHttpHeaders | null): RequestOptions {\n    const result = super.createRequestOptions(url, headers)\n    ;(result as any).redirect = \"manual\"\n    return result\n  }\n\n  async getLatestVersion(): Promise<PrivateGitHubUpdateInfo> {\n    const cancellationToken = new CancellationToken()\n    const channelFile = getChannelFilename(this.getDefaultChannelName())\n\n    const releaseInfo = await this.getLatestVersionInfo(cancellationToken)\n    const asset = releaseInfo.assets.find(it => it.name === channelFile)\n    if (asset == null) {\n      // html_url must be always, but just to be sure\n      throw newError(`Cannot find ${channelFile} in the release ${releaseInfo.html_url || releaseInfo.name}`, \"ERR_UPDATER_CHANNEL_FILE_NOT_FOUND\")\n    }\n\n    const url = new URL(asset.url)\n    let result: any\n    try {\n      result = load((await this.httpRequest(url, this.configureHeaders(\"application/octet-stream\"), cancellationToken))!)\n    } catch (e: any) {\n      if (e instanceof HttpError && e.statusCode === 404) {\n        throw newError(`Cannot find ${channelFile} in the latest release artifacts (${url}): ${e.stack || e.message}`, \"ERR_UPDATER_CHANNEL_FILE_NOT_FOUND\")\n      }\n      throw e\n    }\n\n    ;(result as PrivateGitHubUpdateInfo).assets = releaseInfo.assets\n    return result\n  }\n\n  get fileExtraDownloadHeaders(): OutgoingHttpHeaders | null {\n    return this.configureHeaders(\"application/octet-stream\")\n  }\n\n  private configureHeaders(accept: string) {\n    return {\n      accept,\n      authorization: `token ${this.token}`,\n    }\n  }\n\n  private async getLatestVersionInfo(cancellationToken: CancellationToken): Promise<ReleaseInfo> {\n    const allowPrerelease = this.updater.allowPrerelease\n    let basePath = this.basePath\n    if (!allowPrerelease) {\n      basePath = `${basePath}/latest`\n    }\n\n    const url = newUrlFromBase(basePath, this.baseUrl)\n    try {\n      const version = JSON.parse((await this.httpRequest(url, this.configureHeaders(\"application/vnd.github.v3+json\"), cancellationToken))!)\n      if (allowPrerelease) {\n        return (version as Array<{ prerelease: boolean }>).find(it => it.prerelease) || version[0]\n      } else {\n        return version\n      }\n    } catch (e: any) {\n      throw newError(`Unable to find latest version on GitHub (${url}), please ensure a production release exists: ${e.stack || e.message}`, \"ERR_UPDATER_LATEST_VERSION_NOT_FOUND\")\n    }\n  }\n\n  private get basePath(): string {\n    return this.computeGithubBasePath(`/repos/${this.options.owner}/${this.options.repo}/releases`)\n  }\n\n  resolveFiles(updateInfo: PrivateGitHubUpdateInfo): Array<ResolvedUpdateFileInfo> {\n    return getFileList(updateInfo).map(it => {\n      const name = path.posix.basename(it.url).replace(/ /g, \"-\")\n      const asset = updateInfo.assets.find(it => it != null && it.name === name)\n      if (asset == null) {\n        throw newError(`Cannot find asset \"${name}\" in: ${JSON.stringify(updateInfo.assets, null, 2)}`, \"ERR_UPDATER_ASSET_NOT_FOUND\")\n      }\n\n      return {\n        url: new URL(asset.url),\n        info: it,\n      }\n    })\n  }\n}\n\ninterface ReleaseInfo {\n  name: string\n  html_url: string\n  assets: Array<Asset>\n}\n\nexport interface Asset {\n  name: string\n  url: string\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Provider = void 0;
exports.findFile = findFile;
exports.parseUpdateInfo = parseUpdateInfo;
exports.getFileList = getFileList;
exports.resolveFiles = resolveFiles;
const builder_util_runtime_1 = require("builder-util-runtime");
const js_yaml_1 = require("js-yaml");
const util_1 = require("../util");
class Provider {
    constructor(runtimeOptions) {
        this.runtimeOptions = runtimeOptions;
        this.requestHeaders = null;
        this.executor = runtimeOptions.executor;
    }
    get isUseMultipleRangeRequest() {
        return this.runtimeOptions.isUseMultipleRangeRequest !== false;
    }
    getChannelFilePrefix() {
        if (this.runtimeOptions.platform === "linux") {
            const arch = process.env["TEST_UPDATER_ARCH"] || process.arch;
            const archSuffix = arch === "x64" ? "" : `-${arch}`;
            return "-linux" + archSuffix;
        }
        else {
            return this.runtimeOptions.platform === "darwin" ? "-mac" : "";
        }
    }
    // due to historical reasons for windows we use channel name without platform specifier
    getDefaultChannelName() {
        return this.getCustomChannelName("latest");
    }
    getCustomChannelName(channel) {
        return `${channel}${this.getChannelFilePrefix()}`;
    }
    get fileExtraDownloadHeaders() {
        return null;
    }
    setRequestHeaders(value) {
        this.requestHeaders = value;
    }
    /**
     * Method to perform API request only to resolve update info, but not to download update.
     */
    httpRequest(url, headers, cancellationToken) {
        return this.executor.request(this.createRequestOptions(url, headers), cancellationToken);
    }
    createRequestOptions(url, headers) {
        const result = {};
        if (this.requestHeaders == null) {
            if (headers != null) {
                result.headers = headers;
            }
        }
        else {
            result.headers = headers == null ? this.requestHeaders : { ...this.requestHeaders, ...headers };
        }
        (0, builder_util_runtime_1.configureRequestUrl)(url, result);
        return result;
    }
}
exports.Provider = Provider;
function findFile(files, extension, not) {
    if (files.length === 0) {
        throw (0, builder_util_runtime_1.newError)("No files provided", "ERR_UPDATER_NO_FILES_PROVIDED");
    }
    const result = files.find(it => it.url.pathname.toLowerCase().endsWith(`.${extension}`));
    if (result != null) {
        return result;
    }
    else if (not == null) {
        return files[0];
    }
    else {
        return files.find(fileInfo => !not.some(ext => fileInfo.url.pathname.toLowerCase().endsWith(`.${ext}`)));
    }
}
function parseUpdateInfo(rawData, channelFile, channelFileUrl) {
    if (rawData == null) {
        throw (0, builder_util_runtime_1.newError)(`Cannot parse update info from ${channelFile} in the latest release artifacts (${channelFileUrl}): rawData: null`, "ERR_UPDATER_INVALID_UPDATE_INFO");
    }
    let result;
    try {
        result = (0, js_yaml_1.load)(rawData);
    }
    catch (e) {
        throw (0, builder_util_runtime_1.newError)(`Cannot parse update info from ${channelFile} in the latest release artifacts (${channelFileUrl}): ${e.stack || e.message}, rawData: ${rawData}`, "ERR_UPDATER_INVALID_UPDATE_INFO");
    }
    return result;
}
function getFileList(updateInfo) {
    const files = updateInfo.files;
    if (files != null && files.length > 0) {
        return files;
    }
    // noinspection JSDeprecatedSymbols
    if (updateInfo.path != null) {
        // noinspection JSDeprecatedSymbols
        return [
            {
                url: updateInfo.path,
                sha2: updateInfo.sha2,
                sha512: updateInfo.sha512,
            },
        ];
    }
    else {
        throw (0, builder_util_runtime_1.newError)(`No files provided: ${(0, builder_util_runtime_1.safeStringifyJson)(updateInfo)}`, "ERR_UPDATER_NO_FILES_PROVIDED");
    }
}
function resolveFiles(updateInfo, baseUrl, pathTransformer = (p) => p) {
    const files = getFileList(updateInfo);
    const result = files.map(fileInfo => {
        if (fileInfo.sha2 == null && fileInfo.sha512 == null) {
            throw (0, builder_util_runtime_1.newError)(`Update info doesn't contain nor sha256 neither sha512 checksum: ${(0, builder_util_runtime_1.safeStringifyJson)(fileInfo)}`, "ERR_UPDATER_NO_CHECKSUM");
        }
        return {
            url: (0, util_1.newUrlFromBase)(pathTransformer(fileInfo.url), baseUrl),
            info: fileInfo,
        };
    });
    const packages = updateInfo.packages;
    const packageInfo = packages == null ? null : packages[process.arch] || packages.ia32;
    if (packageInfo != null) {
        ;
        result[0].packageInfo = {
            ...packageInfo,
            path: (0, util_1.newUrlFromBase)(pathTransformer(packageInfo.path), baseUrl).href,
        };
    }
    return result;
}
//# sourceMappingURL=Provider.js.map{"version":3,"file":"Provider.js","sourceRoot":"","sources":["../../src/providers/Provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { CancellationToken, configureRequestUrl, newError, safeStringifyJson, UpdateFileInfo, UpdateInfo, WindowsUpdateInfo } from \"builder-util-runtime\"\nimport { OutgoingHttpHeaders, RequestOptions } from \"http\"\nimport { load } from \"js-yaml\"\nimport { URL } from \"url\"\nimport { ElectronHttpExecutor } from \"../electronHttpExecutor\"\nimport { ResolvedUpdateFileInfo } from \"../types\"\nimport { newUrlFromBase } from \"../util\"\n\nexport type ProviderPlatform = \"darwin\" | \"linux\" | \"win32\"\n\nexport interface ProviderRuntimeOptions {\n  isUseMultipleRangeRequest: boolean\n  platform: ProviderPlatform\n\n  executor: ElectronHttpExecutor\n}\n\nexport abstract class Provider<T extends UpdateInfo> {\n  private requestHeaders: OutgoingHttpHeaders | null = null\n  protected readonly executor: ElectronHttpExecutor\n\n  protected constructor(private readonly runtimeOptions: ProviderRuntimeOptions) {\n    this.executor = runtimeOptions.executor\n  }\n\n  get isUseMultipleRangeRequest(): boolean {\n    return this.runtimeOptions.isUseMultipleRangeRequest !== false\n  }\n\n  private getChannelFilePrefix(): string {\n    if (this.runtimeOptions.platform === \"linux\") {\n      const arch = process.env[\"TEST_UPDATER_ARCH\"] || process.arch\n      const archSuffix = arch === \"x64\" ? \"\" : `-${arch}`\n      return \"-linux\" + archSuffix\n    } else {\n      return this.runtimeOptions.platform === \"darwin\" ? \"-mac\" : \"\"\n    }\n  }\n\n  // due to historical reasons for windows we use channel name without platform specifier\n  protected getDefaultChannelName(): string {\n    return this.getCustomChannelName(\"latest\")\n  }\n\n  protected getCustomChannelName(channel: string): string {\n    return `${channel}${this.getChannelFilePrefix()}`\n  }\n\n  get fileExtraDownloadHeaders(): OutgoingHttpHeaders | null {\n    return null\n  }\n\n  setRequestHeaders(value: OutgoingHttpHeaders | null): void {\n    this.requestHeaders = value\n  }\n\n  abstract getLatestVersion(): Promise<T>\n\n  abstract resolveFiles(updateInfo: T): Array<ResolvedUpdateFileInfo>\n\n  /**\n   * Method to perform API request only to resolve update info, but not to download update.\n   */\n  protected httpRequest(url: URL, headers?: OutgoingHttpHeaders | null, cancellationToken?: CancellationToken): Promise<string | null> {\n    return this.executor.request(this.createRequestOptions(url, headers), cancellationToken)\n  }\n\n  protected createRequestOptions(url: URL, headers?: OutgoingHttpHeaders | null): RequestOptions {\n    const result: RequestOptions = {}\n    if (this.requestHeaders == null) {\n      if (headers != null) {\n        result.headers = headers\n      }\n    } else {\n      result.headers = headers == null ? this.requestHeaders : { ...this.requestHeaders, ...headers }\n    }\n\n    configureRequestUrl(url, result)\n    return result\n  }\n}\n\nexport function findFile(files: Array<ResolvedUpdateFileInfo>, extension: string, not?: Array<string>): ResolvedUpdateFileInfo | null | undefined {\n  if (files.length === 0) {\n    throw newError(\"No files provided\", \"ERR_UPDATER_NO_FILES_PROVIDED\")\n  }\n\n  const result = files.find(it => it.url.pathname.toLowerCase().endsWith(`.${extension}`))\n  if (result != null) {\n    return result\n  } else if (not == null) {\n    return files[0]\n  } else {\n    return files.find(fileInfo => !not.some(ext => fileInfo.url.pathname.toLowerCase().endsWith(`.${ext}`)))\n  }\n}\n\nexport function parseUpdateInfo(rawData: string | null, channelFile: string, channelFileUrl: URL): UpdateInfo {\n  if (rawData == null) {\n    throw newError(`Cannot parse update info from ${channelFile} in the latest release artifacts (${channelFileUrl}): rawData: null`, \"ERR_UPDATER_INVALID_UPDATE_INFO\")\n  }\n\n  let result: UpdateInfo\n  try {\n    result = load(rawData) as UpdateInfo\n  } catch (e: any) {\n    throw newError(\n      `Cannot parse update info from ${channelFile} in the latest release artifacts (${channelFileUrl}): ${e.stack || e.message}, rawData: ${rawData}`,\n      \"ERR_UPDATER_INVALID_UPDATE_INFO\"\n    )\n  }\n  return result\n}\n\nexport function getFileList(updateInfo: UpdateInfo): Array<UpdateFileInfo> {\n  const files = updateInfo.files\n  if (files != null && files.length > 0) {\n    return files\n  }\n\n  // noinspection JSDeprecatedSymbols\n  if (updateInfo.path != null) {\n    // noinspection JSDeprecatedSymbols\n    return [\n      {\n        url: updateInfo.path,\n        sha2: (updateInfo as any).sha2,\n        sha512: updateInfo.sha512,\n      } as any,\n    ]\n  } else {\n    throw newError(`No files provided: ${safeStringifyJson(updateInfo)}`, \"ERR_UPDATER_NO_FILES_PROVIDED\")\n  }\n}\n\nexport function resolveFiles(updateInfo: UpdateInfo, baseUrl: URL, pathTransformer: (p: string) => string = (p: string): string => p): Array<ResolvedUpdateFileInfo> {\n  const files = getFileList(updateInfo)\n  const result: Array<ResolvedUpdateFileInfo> = files.map(fileInfo => {\n    if ((fileInfo as any).sha2 == null && fileInfo.sha512 == null) {\n      throw newError(`Update info doesn't contain nor sha256 neither sha512 checksum: ${safeStringifyJson(fileInfo)}`, \"ERR_UPDATER_NO_CHECKSUM\")\n    }\n    return {\n      url: newUrlFromBase(pathTransformer(fileInfo.url), baseUrl),\n      info: fileInfo,\n    }\n  })\n\n  const packages = (updateInfo as WindowsUpdateInfo).packages\n  const packageInfo = packages == null ? null : packages[process.arch] || packages.ia32\n  if (packageInfo != null) {\n    ;(result[0] as any).packageInfo = {\n      ...packageInfo,\n      path: newUrlFromBase(pathTransformer(packageInfo.path), baseUrl).href,\n    }\n  }\n  return result\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UpdaterSignal = exports.UPDATE_DOWNLOADED = exports.DOWNLOAD_PROGRESS = exports.CancellationToken = void 0;
exports.addHandler = addHandler;
const builder_util_runtime_1 = require("builder-util-runtime");
Object.defineProperty(exports, "CancellationToken", { enumerable: true, get: function () { return builder_util_runtime_1.CancellationToken; } });
exports.DOWNLOAD_PROGRESS = "download-progress";
exports.UPDATE_DOWNLOADED = "update-downloaded";
class UpdaterSignal {
    constructor(emitter) {
        this.emitter = emitter;
    }
    /**
     * Emitted when an authenticating proxy is [asking for user credentials](https://github.com/electron/electron/blob/master/docs/api/client-request.md#event-login).
     */
    login(handler) {
        addHandler(this.emitter, "login", handler);
    }
    progress(handler) {
        addHandler(this.emitter, exports.DOWNLOAD_PROGRESS, handler);
    }
    updateDownloaded(handler) {
        addHandler(this.emitter, exports.UPDATE_DOWNLOADED, handler);
    }
    updateCancelled(handler) {
        addHandler(this.emitter, "update-cancelled", handler);
    }
}
exports.UpdaterSignal = UpdaterSignal;
const isLogEvent = false;
function addHandler(emitter, event, handler) {
    if (isLogEvent) {
        emitter.on(event, (...args) => {
            console.log("%s %s", event, args);
            handler(...args);
        });
    }
    else {
        emitter.on(event, handler);
    }
}
//# sourceMappingURL=types.js.map{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AA6CA,gCASC;AAtDD,+DAAmH;AAK1G,kGALA,wCAAiB,OAKA;AAEb,QAAA,iBAAiB,GAAG,mBAAmB,CAAA;AACvC,QAAA,iBAAiB,GAAG,mBAAmB,CAAA;AAYpD,MAAa,aAAa;IACxB,YAAoB,OAAqB;QAArB,YAAO,GAAP,OAAO,CAAc;IAAG,CAAC;IAE7C;;OAEG;IACH,KAAK,CAAC,OAAqB;QACzB,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IAC5C,CAAC;IAED,QAAQ,CAAC,OAAqC;QAC5C,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,yBAAiB,EAAE,OAAO,CAAC,CAAA;IACtD,CAAC;IAED,gBAAgB,CAAC,OAA8C;QAC7D,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,yBAAiB,EAAE,OAAO,CAAC,CAAA;IACtD,CAAC;IAED,eAAe,CAAC,OAAmC;QACjD,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAA;IACvD,CAAC;CACF;AArBD,sCAqBC;AAED,MAAM,UAAU,GAAG,KAAK,CAAA;AAExB,SAAgB,UAAU,CAAC,OAAqB,EAAE,KAAoB,EAAE,OAAsC;IAC5G,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,IAAgB,EAAE,EAAE;YACxC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;YACjC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;QAClB,CAAC,CAAC,CAAA;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAC5B,CAAC;AACH,CAAC","sourcesContent":["import { CancellationToken, PackageFileInfo, ProgressInfo, UpdateFileInfo, UpdateInfo } from \"builder-util-runtime\"\nimport { EventEmitter } from \"events\"\nimport { URL } from \"url\"\nimport { LoginCallback } from \"./electronHttpExecutor\"\n\nexport { CancellationToken, PackageFileInfo, ProgressInfo, UpdateFileInfo, UpdateInfo }\n\nexport const DOWNLOAD_PROGRESS = \"download-progress\"\nexport const UPDATE_DOWNLOADED = \"update-downloaded\"\n\nexport interface Logger {\n  info(message?: any): void\n\n  warn(message?: any): void\n\n  error(message?: any): void\n\n  debug?(message: string): void\n}\n\nexport class UpdaterSignal {\n  constructor(private emitter: EventEmitter) {}\n\n  /**\n   * Emitted when an authenticating proxy is [asking for user credentials](https://github.com/electron/electron/blob/master/docs/api/client-request.md#event-login).\n   */\n  login(handler: LoginHandler): void {\n    addHandler(this.emitter, \"login\", handler)\n  }\n\n  progress(handler: (info: ProgressInfo) => void): void {\n    addHandler(this.emitter, DOWNLOAD_PROGRESS, handler)\n  }\n\n  updateDownloaded(handler: (info: UpdateDownloadedEvent) => void): void {\n    addHandler(this.emitter, UPDATE_DOWNLOADED, handler)\n  }\n\n  updateCancelled(handler: (info: UpdateInfo) => void): void {\n    addHandler(this.emitter, \"update-cancelled\", handler)\n  }\n}\n\nconst isLogEvent = false\n\nexport function addHandler(emitter: EventEmitter, event: UpdaterEvents, handler: (...args: Array<any>) => void): void {\n  if (isLogEvent) {\n    emitter.on(event, (...args: Array<any>) => {\n      console.log(\"%s %s\", event, args)\n      handler(...args)\n    })\n  } else {\n    emitter.on(event, handler)\n  }\n}\n\nexport interface UpdateCheckResult {\n  readonly isUpdateAvailable: boolean\n\n  readonly updateInfo: UpdateInfo\n\n  readonly downloadPromise?: Promise<Array<string>> | null\n\n  readonly cancellationToken?: CancellationToken\n\n  /** @deprecated */\n  readonly versionInfo: UpdateInfo\n}\n\nexport interface UpdateDownloadedEvent extends UpdateInfo {\n  downloadedFile: string\n}\n\nexport interface ResolvedUpdateFileInfo {\n  readonly url: URL\n  readonly info: UpdateFileInfo\n\n  packageInfo?: PackageFileInfo\n}\n\nexport type UpdaterEvents = \"login\" | \"checking-for-update\" | \"update-available\" | \"update-not-available\" | \"update-cancelled\" | \"download-progress\" | \"update-downloaded\" | \"error\"\n\nexport type LoginHandler = (authInfo: any, callback: LoginCallback) => void\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.newBaseUrl = newBaseUrl;
exports.newUrlFromBase = newUrlFromBase;
exports.getChannelFilename = getChannelFilename;
exports.blockmapFiles = blockmapFiles;
// if baseUrl path doesn't ends with /, this path will be not prepended to passed pathname for new URL(input, base)
const url_1 = require("url");
// @ts-ignore
const escapeRegExp = require("lodash.escaperegexp");
/** @internal */
function newBaseUrl(url) {
    const result = new url_1.URL(url);
    if (!result.pathname.endsWith("/")) {
        result.pathname += "/";
    }
    return result;
}
// addRandomQueryToAvoidCaching is false by default because in most cases URL already contains version number,
// so, it makes sense only for Generic Provider for channel files
function newUrlFromBase(pathname, baseUrl, addRandomQueryToAvoidCaching = false) {
    const result = new url_1.URL(pathname, baseUrl);
    // search is not propagated (search is an empty string if not specified)
    const search = baseUrl.search;
    if (search != null && search.length !== 0) {
        result.search = search;
    }
    else if (addRandomQueryToAvoidCaching) {
        result.search = `noCache=${Date.now().toString(32)}`;
    }
    return result;
}
function getChannelFilename(channel) {
    return `${channel}.yml`;
}
function blockmapFiles(baseUrl, oldVersion, newVersion) {
    const newBlockMapUrl = newUrlFromBase(`${baseUrl.pathname}.blockmap`, baseUrl);
    const oldBlockMapUrl = newUrlFromBase(`${baseUrl.pathname.replace(new RegExp(escapeRegExp(newVersion), "g"), oldVersion)}.blockmap`, baseUrl);
    return [oldBlockMapUrl, newBlockMapUrl];
}
//# sourceMappingURL=util.js.map{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;AAMA,gCAMC;AAID,wCAUC;AAED,gDAEC;AAED,sCAIC;AApCD,mHAAmH;AACnH,6BAAyB;AACzB,aAAa;AACb,oDAAmD;AAEnD,gBAAgB;AAChB,SAAgB,UAAU,CAAC,GAAW;IACpC,MAAM,MAAM,GAAG,IAAI,SAAG,CAAC,GAAG,CAAC,CAAA;IAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,QAAQ,IAAI,GAAG,CAAA;IACxB,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,8GAA8G;AAC9G,iEAAiE;AACjE,SAAgB,cAAc,CAAC,QAAgB,EAAE,OAAY,EAAE,4BAA4B,GAAG,KAAK;IACjG,MAAM,MAAM,GAAG,IAAI,SAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IACzC,wEAAwE;IACxE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IAC7B,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1C,MAAM,CAAC,MAAM,GAAG,MAAM,CAAA;IACxB,CAAC;SAAM,IAAI,4BAA4B,EAAE,CAAC;QACxC,MAAM,CAAC,MAAM,GAAG,WAAW,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAA;IACtD,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAgB,kBAAkB,CAAC,OAAe;IAChD,OAAO,GAAG,OAAO,MAAM,CAAA;AACzB,CAAC;AAED,SAAgB,aAAa,CAAC,OAAY,EAAE,UAAkB,EAAE,UAAkB;IAChF,MAAM,cAAc,GAAG,cAAc,CAAC,GAAG,OAAO,CAAC,QAAQ,WAAW,EAAE,OAAO,CAAC,CAAA;IAC9E,MAAM,cAAc,GAAG,cAAc,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;IAC7I,OAAO,CAAC,cAAc,EAAE,cAAc,CAAC,CAAA;AACzC,CAAC","sourcesContent":["// if baseUrl path doesn't ends with /, this path will be not prepended to passed pathname for new URL(input, base)\nimport { URL } from \"url\"\n// @ts-ignore\nimport * as escapeRegExp from \"lodash.escaperegexp\"\n\n/** @internal */\nexport function newBaseUrl(url: string): URL {\n  const result = new URL(url)\n  if (!result.pathname.endsWith(\"/\")) {\n    result.pathname += \"/\"\n  }\n  return result\n}\n\n// addRandomQueryToAvoidCaching is false by default because in most cases URL already contains version number,\n// so, it makes sense only for Generic Provider for channel files\nexport function newUrlFromBase(pathname: string, baseUrl: URL, addRandomQueryToAvoidCaching = false): URL {\n  const result = new URL(pathname, baseUrl)\n  // search is not propagated (search is an empty string if not specified)\n  const search = baseUrl.search\n  if (search != null && search.length !== 0) {\n    result.search = search\n  } else if (addRandomQueryToAvoidCaching) {\n    result.search = `noCache=${Date.now().toString(32)}`\n  }\n  return result\n}\n\nexport function getChannelFilename(channel: string): string {\n  return `${channel}.yml`\n}\n\nexport function blockmapFiles(baseUrl: URL, oldVersion: string, newVersion: string): URL[] {\n  const newBlockMapUrl = newUrlFromBase(`${baseUrl.pathname}.blockmap`, baseUrl)\n  const oldBlockMapUrl = newUrlFromBase(`${baseUrl.pathname.replace(new RegExp(escapeRegExp(newVersion), \"g\"), oldVersion)}.blockmap`, baseUrl)\n  return [oldBlockMapUrl, newBlockMapUrl]\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifySignature = verifySignature;
const builder_util_runtime_1 = require("builder-util-runtime");
const child_process_1 = require("child_process");
const os = require("os");
const path = require("path");
// $certificateInfo = (Get-AuthenticodeSignature 'xxx\yyy.exe'
// | where {$_.Status.Equals([System.Management.Automation.SignatureStatus]::Valid) -and $_.SignerCertificate.Subject.Contains("CN=siemens.com")})
// | Out-String ; if ($certificateInfo) { exit 0 } else { exit 1 }
function verifySignature(publisherNames, unescapedTempUpdateFile, logger) {
    return new Promise((resolve, reject) => {
        // Escape quotes and backticks in filenames to prevent user from breaking the
        // arguments and perform a remote command injection.
        //
        // Consider example powershell command:
        // ```powershell
        // Get-AuthenticodeSignature 'C:\\path\\my-bad-';calc;'filename.exe'
        // ```
        // The above would work expected and find the file name, however, it will also execute `;calc;`
        // command and start the calculator app.
        //
        // From Powershell quoting rules:
        // https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7
        // * Double quotes `"` are treated literally within single-quoted strings;
        // * Single quotes can be escaped by doubling them: 'don''t' -> don't;
        //
        // Also note that at this point the file has already been written to the disk, thus we are
        // guaranteed that the path will not contain any illegal characters like <>:"/\|?*
        // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
        const tempUpdateFile = unescapedTempUpdateFile.replace(/'/g, "''");
        logger.info(`Verifying signature ${tempUpdateFile}`);
        // https://github.com/electron-userland/electron-builder/issues/2421
        // https://github.com/electron-userland/electron-builder/issues/2535
        // Resetting PSModulePath is necessary https://github.com/electron-userland/electron-builder/issues/7127
        // semicolon wont terminate the set command and run chcp thus leading to verification errors on certificats with special chars like german umlauts, so rather
        //   join commands using & https://github.com/electron-userland/electron-builder/issues/8162
        (0, child_process_1.execFile)(`set "PSModulePath=" & chcp 65001 >NUL & powershell.exe`, ["-NoProfile", "-NonInteractive", "-InputFormat", "None", "-Command", `"Get-AuthenticodeSignature -LiteralPath '${tempUpdateFile}' | ConvertTo-Json -Compress"`], {
            shell: true,
            timeout: 20 * 1000,
        }, (error, stdout, stderr) => {
            var _a;
            try {
                if (error != null || stderr) {
                    handleError(logger, error, stderr, reject);
                    resolve(null);
                    return;
                }
                const data = parseOut(stdout);
                if (data.Status === 0) {
                    try {
                        const normlaizedUpdateFilePath = path.normalize(data.Path);
                        const normalizedTempUpdateFile = path.normalize(unescapedTempUpdateFile);
                        logger.info(`LiteralPath: ${normlaizedUpdateFilePath}. Update Path: ${normalizedTempUpdateFile}`);
                        if (normlaizedUpdateFilePath !== normalizedTempUpdateFile) {
                            handleError(logger, new Error(`LiteralPath of ${normlaizedUpdateFilePath} is different than ${normalizedTempUpdateFile}`), stderr, reject);
                            resolve(null);
                            return;
                        }
                    }
                    catch (error) {
                        logger.warn(`Unable to verify LiteralPath of update asset due to missing data.Path. Skipping this step of validation. Message: ${(_a = error.message) !== null && _a !== void 0 ? _a : error.stack}`);
                    }
                    const subject = (0, builder_util_runtime_1.parseDn)(data.SignerCertificate.Subject);
                    let match = false;
                    for (const name of publisherNames) {
                        const dn = (0, builder_util_runtime_1.parseDn)(name);
                        if (dn.size) {
                            // if we have a full DN, compare all values
                            const allKeys = Array.from(dn.keys());
                            match = allKeys.every(key => {
                                return dn.get(key) === subject.get(key);
                            });
                        }
                        else if (name === subject.get("CN")) {
                            logger.warn(`Signature validated using only CN ${name}. Please add your full Distinguished Name (DN) to publisherNames configuration`);
                            match = true;
                        }
                        if (match) {
                            resolve(null);
                            return;
                        }
                    }
                }
                const result = `publisherNames: ${publisherNames.join(" | ")}, raw info: ` + JSON.stringify(data, (name, value) => (name === "RawData" ? undefined : value), 2);
                logger.warn(`Sign verification failed, installer signed with incorrect certificate: ${result}`);
                resolve(result);
            }
            catch (e) {
                handleError(logger, e, null, reject);
                resolve(null);
                return;
            }
        });
    });
}
function parseOut(out) {
    const data = JSON.parse(out);
    delete data.PrivateKey;
    delete data.IsOSBinary;
    delete data.SignatureType;
    const signerCertificate = data.SignerCertificate;
    if (signerCertificate != null) {
        delete signerCertificate.Archived;
        delete signerCertificate.Extensions;
        delete signerCertificate.Handle;
        delete signerCertificate.HasPrivateKey;
        // duplicates data.SignerCertificate (contains RawData)
        delete signerCertificate.SubjectName;
    }
    return data;
}
function handleError(logger, error, stderr, reject) {
    if (isOldWin6()) {
        logger.warn(`Cannot execute Get-AuthenticodeSignature: ${error || stderr}. Ignoring signature validation due to unsupported powershell version. Please upgrade to powershell 3 or higher.`);
        return;
    }
    try {
        (0, child_process_1.execFileSync)("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", "ConvertTo-Json test"], { timeout: 10 * 1000 });
    }
    catch (testError) {
        logger.warn(`Cannot execute ConvertTo-Json: ${testError.message}. Ignoring signature validation due to unsupported powershell version. Please upgrade to powershell 3 or higher.`);
        return;
    }
    if (error != null) {
        reject(error);
    }
    if (stderr) {
        reject(new Error(`Cannot execute Get-AuthenticodeSignature, stderr: ${stderr}. Failing signature validation due to unknown stderr.`));
    }
}
function isOldWin6() {
    const winVersion = os.release();
    return winVersion.startsWith("6.") && !winVersion.startsWith("6.3");
}
//# sourceMappingURL=windowsExecutableCodeSignatureVerifier.js.map{"version":3,"file":"windowsExecutableCodeSignatureVerifier.js","sourceRoot":"","sources":["../src/windowsExecutableCodeSignatureVerifier.ts"],"names":[],"mappings":"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","sourcesContent":["import { parseDn } from \"builder-util-runtime\"\nimport { execFile, execFileSync } from \"child_process\"\nimport * as os from \"os\"\nimport { Logger } from \"./types\"\nimport * as path from \"path\"\n\n// $certificateInfo = (Get-AuthenticodeSignature 'xxx\\yyy.exe'\n// | where {$_.Status.Equals([System.Management.Automation.SignatureStatus]::Valid) -and $_.SignerCertificate.Subject.Contains(\"CN=siemens.com\")})\n// | Out-String ; if ($certificateInfo) { exit 0 } else { exit 1 }\nexport function verifySignature(publisherNames: Array<string>, unescapedTempUpdateFile: string, logger: Logger): Promise<string | null> {\n  return new Promise<string | null>((resolve, reject) => {\n    // Escape quotes and backticks in filenames to prevent user from breaking the\n    // arguments and perform a remote command injection.\n    //\n    // Consider example powershell command:\n    // ```powershell\n    // Get-AuthenticodeSignature 'C:\\\\path\\\\my-bad-';calc;'filename.exe'\n    // ```\n    // The above would work expected and find the file name, however, it will also execute `;calc;`\n    // command and start the calculator app.\n    //\n    // From Powershell quoting rules:\n    // https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules?view=powershell-7\n    // * Double quotes `\"` are treated literally within single-quoted strings;\n    // * Single quotes can be escaped by doubling them: 'don''t' -> don't;\n    //\n    // Also note that at this point the file has already been written to the disk, thus we are\n    // guaranteed that the path will not contain any illegal characters like <>:\"/\\|?*\n    // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file\n    const tempUpdateFile = unescapedTempUpdateFile.replace(/'/g, \"''\")\n    logger.info(`Verifying signature ${tempUpdateFile}`)\n\n    // https://github.com/electron-userland/electron-builder/issues/2421\n    // https://github.com/electron-userland/electron-builder/issues/2535\n    // Resetting PSModulePath is necessary https://github.com/electron-userland/electron-builder/issues/7127\n    // semicolon wont terminate the set command and run chcp thus leading to verification errors on certificats with special chars like german umlauts, so rather\n    //   join commands using & https://github.com/electron-userland/electron-builder/issues/8162\n    execFile(\n      `set \"PSModulePath=\" & chcp 65001 >NUL & powershell.exe`,\n      [\"-NoProfile\", \"-NonInteractive\", \"-InputFormat\", \"None\", \"-Command\", `\"Get-AuthenticodeSignature -LiteralPath '${tempUpdateFile}' | ConvertTo-Json -Compress\"`],\n      {\n        shell: true,\n        timeout: 20 * 1000,\n      },\n      (error, stdout, stderr) => {\n        try {\n          if (error != null || stderr) {\n            handleError(logger, error, stderr, reject)\n            resolve(null)\n            return\n          }\n          const data = parseOut(stdout)\n          if (data.Status === 0) {\n            try {\n              const normlaizedUpdateFilePath = path.normalize(data.Path)\n              const normalizedTempUpdateFile = path.normalize(unescapedTempUpdateFile)\n              logger.info(`LiteralPath: ${normlaizedUpdateFilePath}. Update Path: ${normalizedTempUpdateFile}`)\n              if (normlaizedUpdateFilePath !== normalizedTempUpdateFile) {\n                handleError(logger, new Error(`LiteralPath of ${normlaizedUpdateFilePath} is different than ${normalizedTempUpdateFile}`), stderr, reject)\n                resolve(null)\n                return\n              }\n            } catch (error: any) {\n              logger.warn(`Unable to verify LiteralPath of update asset due to missing data.Path. Skipping this step of validation. Message: ${error.message ?? error.stack}`)\n            }\n            const subject = parseDn(data.SignerCertificate.Subject)\n            let match = false\n            for (const name of publisherNames) {\n              const dn = parseDn(name)\n              if (dn.size) {\n                // if we have a full DN, compare all values\n                const allKeys = Array.from(dn.keys())\n                match = allKeys.every(key => {\n                  return dn.get(key) === subject.get(key)\n                })\n              } else if (name === subject.get(\"CN\")!) {\n                logger.warn(`Signature validated using only CN ${name}. Please add your full Distinguished Name (DN) to publisherNames configuration`)\n                match = true\n              }\n              if (match) {\n                resolve(null)\n                return\n              }\n            }\n          }\n\n          const result = `publisherNames: ${publisherNames.join(\" | \")}, raw info: ` + JSON.stringify(data, (name, value) => (name === \"RawData\" ? undefined : value), 2)\n          logger.warn(`Sign verification failed, installer signed with incorrect certificate: ${result}`)\n          resolve(result)\n        } catch (e: any) {\n          handleError(logger, e, null, reject)\n          resolve(null)\n          return\n        }\n      }\n    )\n  })\n}\n\nfunction parseOut(out: string): any {\n  const data = JSON.parse(out)\n  delete data.PrivateKey\n  delete data.IsOSBinary\n  delete data.SignatureType\n  const signerCertificate = data.SignerCertificate\n  if (signerCertificate != null) {\n    delete signerCertificate.Archived\n    delete signerCertificate.Extensions\n    delete signerCertificate.Handle\n    delete signerCertificate.HasPrivateKey\n    // duplicates data.SignerCertificate (contains RawData)\n    delete signerCertificate.SubjectName\n  }\n  return data\n}\n\nfunction handleError(logger: Logger, error: Error | null, stderr: string | null, reject: (reason: any) => void): void {\n  if (isOldWin6()) {\n    logger.warn(\n      `Cannot execute Get-AuthenticodeSignature: ${error || stderr}. Ignoring signature validation due to unsupported powershell version. Please upgrade to powershell 3 or higher.`\n    )\n    return\n  }\n\n  try {\n    execFileSync(\"powershell.exe\", [\"-NoProfile\", \"-NonInteractive\", \"-Command\", \"ConvertTo-Json test\"], { timeout: 10 * 1000 } as any)\n  } catch (testError: any) {\n    logger.warn(\n      `Cannot execute ConvertTo-Json: ${testError.message}. Ignoring signature validation due to unsupported powershell version. Please upgrade to powershell 3 or higher.`\n    )\n    return\n  }\n\n  if (error != null) {\n    reject(error)\n  }\n\n  if (stderr) {\n    reject(new Error(`Cannot execute Get-AuthenticodeSignature, stderr: ${stderr}. Failing signature validation due to unknown stderr.`))\n  }\n}\n\nfunction isOldWin6(): boolean {\n  const winVersion = os.release()\n  return winVersion.startsWith(\"6.\") && !winVersion.startsWith(\"6.3\")\n}\n"]}{
  "name": "electron-updater",
  "version": "6.6.2",
  "description": "Cross platform updater for electron applications",
  "main": "out/main.js",
  "author": "Vladimir Krivosheev",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/electron-userland/electron-builder.git",
    "directory": "packages/electron-updater"
  },
  "homepage": "https://github.com/electron-userland/electron-builder",
  "files": [
    "out"
  ],
  "dependencies": {
    "fs-extra": "^10.1.0",
    "js-yaml": "^4.1.0",
    "lazy-val": "^1.0.5",
    "lodash.escaperegexp": "^4.1.2",
    "lodash.isequal": "^4.5.0",
    "semver": "^7.6.3",
    "tiny-typed-emitter": "^2.1.0",
    "builder-util-runtime": "9.3.1"
  },
  "devDependencies": {
    "@types/fs-extra": "9.0.13",
    "@types/js-yaml": "4.0.3",
    "@types/lodash.escaperegexp": "4.1.6",
    "@types/lodash.isequal": "4.5.5",
    "@types/semver": "^7.3.13",
    "electron": "^31.2.1"
  },
  "typings": "./out/main.d.ts",
  "publishConfig": {
    "tag": "next"
  }
}The MIT License (MIT)

Copyright (c) 2015 Loopline Systems

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CancellationError = exports.CancellationToken = void 0;
const events_1 = require("events");
class CancellationToken extends events_1.EventEmitter {
    get cancelled() {
        return this._cancelled || (this._parent != null && this._parent.cancelled);
    }
    set parent(value) {
        this.removeParentCancelHandler();
        this._parent = value;
        this.parentCancelHandler = () => this.cancel();
        this._parent.onCancel(this.parentCancelHandler);
    }
    // babel cannot compile ... correctly for super calls
    constructor(parent) {
        super();
        this.parentCancelHandler = null;
        this._parent = null;
        this._cancelled = false;
        if (parent != null) {
            this.parent = parent;
        }
    }
    cancel() {
        this._cancelled = true;
        this.emit("cancel");
    }
    onCancel(handler) {
        if (this.cancelled) {
            handler();
        }
        else {
            this.once("cancel", handler);
        }
    }
    createPromise(callback) {
        if (this.cancelled) {
            return Promise.reject(new CancellationError());
        }
        const finallyHandler = () => {
            if (cancelHandler != null) {
                try {
                    this.removeListener("cancel", cancelHandler);
                    cancelHandler = null;
                }
                catch (_ignore) {
                    // ignore
                }
            }
        };
        let cancelHandler = null;
        return new Promise((resolve, reject) => {
            let addedCancelHandler = null;
            cancelHandler = () => {
                try {
                    if (addedCancelHandler != null) {
                        addedCancelHandler();
                        addedCancelHandler = null;
                    }
                }
                finally {
                    reject(new CancellationError());
                }
            };
            if (this.cancelled) {
                cancelHandler();
                return;
            }
            this.onCancel(cancelHandler);
            callback(resolve, reject, (callback) => {
                addedCancelHandler = callback;
            });
        })
            .then(it => {
            finallyHandler();
            return it;
        })
            .catch((e) => {
            finallyHandler();
            throw e;
        });
    }
    removeParentCancelHandler() {
        const parent = this._parent;
        if (parent != null && this.parentCancelHandler != null) {
            parent.removeListener("cancel", this.parentCancelHandler);
            this.parentCancelHandler = null;
        }
    }
    dispose() {
        try {
            this.removeParentCancelHandler();
        }
        finally {
            this.removeAllListeners();
            this._parent = null;
        }
    }
}
exports.CancellationToken = CancellationToken;
class CancellationError extends Error {
    constructor() {
        super("cancelled");
    }
}
exports.CancellationError = CancellationError;
//# sourceMappingURL=CancellationToken.js.map{"version":3,"file":"CancellationToken.js","sourceRoot":"","sources":["../src/CancellationToken.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"events\"\n\nexport class CancellationToken extends EventEmitter {\n  private parentCancelHandler: (() => any) | null = null\n\n  private _cancelled: boolean\n  get cancelled(): boolean {\n    return this._cancelled || (this._parent != null && this._parent.cancelled)\n  }\n\n  private _parent: CancellationToken | null = null\n  set parent(value: CancellationToken) {\n    this.removeParentCancelHandler()\n\n    this._parent = value\n    this.parentCancelHandler = () => this.cancel()\n    this._parent.onCancel(this.parentCancelHandler)\n  }\n\n  // babel cannot compile ... correctly for super calls\n  constructor(parent?: CancellationToken) {\n    super()\n\n    this._cancelled = false\n    if (parent != null) {\n      this.parent = parent\n    }\n  }\n\n  cancel() {\n    this._cancelled = true\n    this.emit(\"cancel\")\n  }\n\n  private onCancel(handler: () => any) {\n    if (this.cancelled) {\n      handler()\n    } else {\n      this.once(\"cancel\", handler)\n    }\n  }\n\n  createPromise<R>(\n    callback: (resolve: (thenableOrResult: R | PromiseLike<R>) => void, reject: (error: Error) => void, onCancel: (callback: () => void) => void) => void\n  ): Promise<R> {\n    if (this.cancelled) {\n      return Promise.reject<R>(new CancellationError())\n    }\n\n    const finallyHandler = () => {\n      if (cancelHandler != null) {\n        try {\n          this.removeListener(\"cancel\", cancelHandler)\n          cancelHandler = null\n        } catch (_ignore) {\n          // ignore\n        }\n      }\n    }\n\n    let cancelHandler: (() => void) | null = null\n    return new Promise<R>((resolve, reject) => {\n      let addedCancelHandler: (() => void) | null = null\n\n      cancelHandler = () => {\n        try {\n          if (addedCancelHandler != null) {\n            addedCancelHandler()\n            addedCancelHandler = null\n          }\n        } finally {\n          reject(new CancellationError())\n        }\n      }\n\n      if (this.cancelled) {\n        cancelHandler()\n        return\n      }\n\n      this.onCancel(cancelHandler)\n\n      callback(resolve, reject, (callback: () => void) => {\n        addedCancelHandler = callback\n      })\n    })\n      .then(it => {\n        finallyHandler()\n        return it\n      })\n      .catch((e: any) => {\n        finallyHandler()\n        throw e\n      })\n  }\n\n  private removeParentCancelHandler() {\n    const parent = this._parent\n    if (parent != null && this.parentCancelHandler != null) {\n      parent.removeListener(\"cancel\", this.parentCancelHandler)\n      this.parentCancelHandler = null\n    }\n  }\n\n  dispose() {\n    try {\n      this.removeParentCancelHandler()\n    } finally {\n      this.removeAllListeners()\n      this._parent = null\n    }\n  }\n}\n\nexport class CancellationError extends Error {\n  constructor() {\n    super(\"cancelled\")\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MemoLazy = void 0;
class MemoLazy {
    constructor(selector, creator) {
        this.selector = selector;
        this.creator = creator;
        this.selected = undefined;
        this._value = undefined;
    }
    get hasValue() {
        return this._value !== undefined;
    }
    get value() {
        const selected = this.selector();
        if (this._value !== undefined && equals(this.selected, selected)) {
            // value exists and selected hasn't changed, so return the cached value
            return this._value;
        }
        this.selected = selected;
        const result = this.creator(selected);
        this.value = result;
        return result;
    }
    set value(value) {
        this._value = value;
    }
}
exports.MemoLazy = MemoLazy;
function equals(firstValue, secondValue) {
    const isFirstObject = typeof firstValue === "object" && firstValue !== null;
    const isSecondObject = typeof secondValue === "object" && secondValue !== null;
    // do a shallow comparison of objects, arrays etc.
    if (isFirstObject && isSecondObject) {
        const keys1 = Object.keys(firstValue);
        const keys2 = Object.keys(secondValue);
        return keys1.length === keys2.length && keys1.every((key) => equals(firstValue[key], secondValue[key]));
    }
    // otherwise just compare the values directly
    return firstValue === secondValue;
}
//# sourceMappingURL=MemoLazy.js.map{"version":3,"file":"MemoLazy.js","sourceRoot":"","sources":["../src/MemoLazy.ts"],"names":[],"mappings":";;;AAAA,MAAa,QAAQ;IAInB,YACU,QAAiB,EACjB,OAAoC;QADpC,aAAQ,GAAR,QAAQ,CAAS;QACjB,YAAO,GAAP,OAAO,CAA6B;QALtC,aAAQ,GAAkB,SAAS,CAAA;QACnC,WAAM,GAA2B,SAAS,CAAA;IAK/C,CAAC;IAEJ,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS,CAAA;IAClC,CAAC;IAED,IAAI,KAAK;QACP,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;QAChC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;YACjE,uEAAuE;YACvE,OAAO,IAAI,CAAC,MAAM,CAAA;QACpB,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACrC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAA;QAEnB,OAAO,MAAM,CAAA;IACf,CAAC;IAED,IAAI,KAAK,CAAC,KAAiB;QACzB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;IACrB,CAAC;CACF;AA9BD,4BA8BC;AAED,SAAS,MAAM,CAAC,UAAe,EAAE,WAAgB;IAC/C,MAAM,aAAa,GAAG,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI,CAAA;IAC3E,MAAM,cAAc,GAAG,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,KAAK,IAAI,CAAA;IAE9E,kDAAkD;IAClD,IAAI,aAAa,IAAI,cAAc,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACrC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAEtC,OAAO,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IAC9G,CAAC;IAED,6CAA6C;IAC7C,OAAO,UAAU,KAAK,WAAW,CAAA;AACnC,CAAC","sourcesContent":["export class MemoLazy<S, V> {\n  private selected: S | undefined = undefined\n  private _value: Promise<V> | undefined = undefined\n\n  constructor(\n    private selector: () => S,\n    private creator: (selected: S) => Promise<V>\n  ) {}\n\n  get hasValue() {\n    return this._value !== undefined\n  }\n\n  get value(): Promise<V> {\n    const selected = this.selector()\n    if (this._value !== undefined && equals(this.selected, selected)) {\n      // value exists and selected hasn't changed, so return the cached value\n      return this._value\n    }\n\n    this.selected = selected\n    const result = this.creator(selected)\n    this.value = result\n\n    return result\n  }\n\n  set value(value: Promise<V>) {\n    this._value = value\n  }\n}\n\nfunction equals(firstValue: any, secondValue: any): boolean {\n  const isFirstObject = typeof firstValue === \"object\" && firstValue !== null\n  const isSecondObject = typeof secondValue === \"object\" && secondValue !== null\n\n  // do a shallow comparison of objects, arrays etc.\n  if (isFirstObject && isSecondObject) {\n    const keys1 = Object.keys(firstValue)\n    const keys2 = Object.keys(secondValue)\n\n    return keys1.length === keys2.length && keys1.every((key: any) => equals(firstValue[key], secondValue[key]))\n  }\n\n  // otherwise just compare the values directly\n  return firstValue === secondValue\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProgressCallbackTransform = void 0;
const stream_1 = require("stream");
class ProgressCallbackTransform extends stream_1.Transform {
    constructor(total, cancellationToken, onProgress) {
        super();
        this.total = total;
        this.cancellationToken = cancellationToken;
        this.onProgress = onProgress;
        this.start = Date.now();
        this.transferred = 0;
        this.delta = 0;
        this.nextUpdate = this.start + 1000;
    }
    _transform(chunk, encoding, callback) {
        if (this.cancellationToken.cancelled) {
            callback(new Error("cancelled"), null);
            return;
        }
        this.transferred += chunk.length;
        this.delta += chunk.length;
        const now = Date.now();
        if (now >= this.nextUpdate && this.transferred !== this.total /* will be emitted on _flush */) {
            this.nextUpdate = now + 1000;
            this.onProgress({
                total: this.total,
                delta: this.delta,
                transferred: this.transferred,
                percent: (this.transferred / this.total) * 100,
                bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000)),
            });
            this.delta = 0;
        }
        callback(null, chunk);
    }
    _flush(callback) {
        if (this.cancellationToken.cancelled) {
            callback(new Error("cancelled"));
            return;
        }
        this.onProgress({
            total: this.total,
            delta: this.delta,
            transferred: this.total,
            percent: 100,
            bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000)),
        });
        this.delta = 0;
        callback(null);
    }
}
exports.ProgressCallbackTransform = ProgressCallbackTransform;
//# sourceMappingURL=ProgressCallbackTransform.js.map{"version":3,"file":"ProgressCallbackTransform.js","sourceRoot":"","sources":["../src/ProgressCallbackTransform.ts"],"names":[],"mappings":";;;AAAA,mCAAkC;AAWlC,MAAa,yBAA0B,SAAQ,kBAAS;IAOtD,YACmB,KAAa,EACb,iBAAoC,EACpC,UAAuC;QAExD,KAAK,EAAE,CAAA;QAJU,UAAK,GAAL,KAAK,CAAQ;QACb,sBAAiB,GAAjB,iBAAiB,CAAmB;QACpC,eAAU,GAAV,UAAU,CAA6B;QATlD,UAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAClB,gBAAW,GAAG,CAAC,CAAA;QACf,UAAK,GAAG,CAAC,CAAA;QAET,eAAU,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IAQtC,CAAC;IAED,UAAU,CAAC,KAAU,EAAE,QAAgB,EAAE,QAAa;QACpD,IAAI,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC;YACrC,QAAQ,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,CAAA;YACtC,OAAM;QACR,CAAC;QAED,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,MAAM,CAAA;QAChC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,CAAA;QAE1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,KAAK,CAAC,+BAA+B,EAAE,CAAC;YAC9F,IAAI,CAAC,UAAU,GAAG,GAAG,GAAG,IAAI,CAAA;YAE5B,IAAI,CAAC,UAAU,CAAC;gBACd,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,OAAO,EAAE,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG;gBAC9C,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;aAC3E,CAAC,CAAA;YACF,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;QAChB,CAAC;QAED,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACvB,CAAC;IAED,MAAM,CAAC,QAAa;QAClB,IAAI,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC;YACrC,QAAQ,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAA;YAChC,OAAM;QACR,CAAC;QAED,IAAI,CAAC,UAAU,CAAC;YACd,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,IAAI,CAAC,KAAK;YACvB,OAAO,EAAE,GAAG;YACZ,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;SAClF,CAAC,CAAA;QACF,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;QAEd,QAAQ,CAAC,IAAI,CAAC,CAAA;IAChB,CAAC;CACF;AA1DD,8DA0DC","sourcesContent":["import { Transform } from \"stream\"\nimport { CancellationToken } from \"./CancellationToken\"\n\nexport interface ProgressInfo {\n  total: number\n  delta: number\n  transferred: number\n  percent: number\n  bytesPerSecond: number\n}\n\nexport class ProgressCallbackTransform extends Transform {\n  private start = Date.now()\n  private transferred = 0\n  private delta = 0\n\n  private nextUpdate = this.start + 1000\n\n  constructor(\n    private readonly total: number,\n    private readonly cancellationToken: CancellationToken,\n    private readonly onProgress: (info: ProgressInfo) => any\n  ) {\n    super()\n  }\n\n  _transform(chunk: any, encoding: string, callback: any) {\n    if (this.cancellationToken.cancelled) {\n      callback(new Error(\"cancelled\"), null)\n      return\n    }\n\n    this.transferred += chunk.length\n    this.delta += chunk.length\n\n    const now = Date.now()\n    if (now >= this.nextUpdate && this.transferred !== this.total /* will be emitted on _flush */) {\n      this.nextUpdate = now + 1000\n\n      this.onProgress({\n        total: this.total,\n        delta: this.delta,\n        transferred: this.transferred,\n        percent: (this.transferred / this.total) * 100,\n        bytesPerSecond: Math.round(this.transferred / ((now - this.start) / 1000)),\n      })\n      this.delta = 0\n    }\n\n    callback(null, chunk)\n  }\n\n  _flush(callback: any): void {\n    if (this.cancellationToken.cancelled) {\n      callback(new Error(\"cancelled\"))\n      return\n    }\n\n    this.onProgress({\n      total: this.total,\n      delta: this.delta,\n      transferred: this.total,\n      percent: 100,\n      bytesPerSecond: Math.round(this.transferred / ((Date.now() - this.start) / 1000)),\n    })\n    this.delta = 0\n\n    callback(null)\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=blockMapApi.js.map{"version":3,"file":"blockMapApi.js","sourceRoot":"","sources":["../src/blockMapApi.ts"],"names":[],"mappings":"","sourcesContent":["export interface FileChunks {\n  checksums: Array<string>\n  sizes: Array<number>\n}\n\nexport interface BlockMap {\n  version: \"1\" | \"2\"\n  files: Array<BlockMapFile>\n}\n\nexport interface BlockMapFile extends FileChunks {\n  name: string\n  offset: number\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.newError = newError;
function newError(message, code) {
    const error = new Error(message);
    error.code = code;
    return error;
}
//# sourceMappingURL=error.js.map{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":";;AAAA,4BAIC;AAJD,SAAgB,QAAQ,CAAC,OAAe,EAAE,IAAY;IACpD,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,CAC/B;IAAC,KAA+B,CAAC,IAAI,GAAG,IAAI,CAAA;IAC7C,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["export function newError(message: string, code: string) {\n  const error = new Error(message)\n  ;(error as NodeJS.ErrnoException).code = code\n  return error\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DigestTransform = exports.HttpExecutor = exports.HttpError = void 0;
exports.createHttpError = createHttpError;
exports.parseJson = parseJson;
exports.configureRequestOptionsFromUrl = configureRequestOptionsFromUrl;
exports.configureRequestUrl = configureRequestUrl;
exports.safeGetHeader = safeGetHeader;
exports.configureRequestOptions = configureRequestOptions;
exports.safeStringifyJson = safeStringifyJson;
const crypto_1 = require("crypto");
const debug_1 = require("debug");
const fs_1 = require("fs");
const stream_1 = require("stream");
const url_1 = require("url");
const CancellationToken_1 = require("./CancellationToken");
const error_1 = require("./error");
const ProgressCallbackTransform_1 = require("./ProgressCallbackTransform");
const debug = (0, debug_1.default)("electron-builder");
function createHttpError(response, description = null) {
    return new HttpError(response.statusCode || -1, `${response.statusCode} ${response.statusMessage}` +
        (description == null ? "" : "\n" + JSON.stringify(description, null, "  ")) +
        "\nHeaders: " +
        safeStringifyJson(response.headers), description);
}
const HTTP_STATUS_CODES = new Map([
    [429, "Too many requests"],
    [400, "Bad request"],
    [403, "Forbidden"],
    [404, "Not found"],
    [405, "Method not allowed"],
    [406, "Not acceptable"],
    [408, "Request timeout"],
    [413, "Request entity too large"],
    [500, "Internal server error"],
    [502, "Bad gateway"],
    [503, "Service unavailable"],
    [504, "Gateway timeout"],
    [505, "HTTP version not supported"],
]);
class HttpError extends Error {
    constructor(statusCode, message = `HTTP error: ${HTTP_STATUS_CODES.get(statusCode) || statusCode}`, description = null) {
        super(message);
        this.statusCode = statusCode;
        this.description = description;
        this.name = "HttpError";
        this.code = `HTTP_ERROR_${statusCode}`;
    }
    isServerError() {
        return this.statusCode >= 500 && this.statusCode <= 599;
    }
}
exports.HttpError = HttpError;
function parseJson(result) {
    return result.then(it => (it == null || it.length === 0 ? null : JSON.parse(it)));
}
class HttpExecutor {
    constructor() {
        this.maxRedirects = 10;
    }
    request(options, cancellationToken = new CancellationToken_1.CancellationToken(), data) {
        configureRequestOptions(options);
        const json = data == null ? undefined : JSON.stringify(data);
        const encodedData = json ? Buffer.from(json) : undefined;
        if (encodedData != null) {
            debug(json);
            const { headers, ...opts } = options;
            options = {
                method: "post",
                headers: {
                    "Content-Type": "application/json",
                    "Content-Length": encodedData.length,
                    ...headers,
                },
                ...opts,
            };
        }
        return this.doApiRequest(options, cancellationToken, it => it.end(encodedData));
    }
    doApiRequest(options, cancellationToken, requestProcessor, redirectCount = 0) {
        if (debug.enabled) {
            debug(`Request: ${safeStringifyJson(options)}`);
        }
        return cancellationToken.createPromise((resolve, reject, onCancel) => {
            const request = this.createRequest(options, (response) => {
                try {
                    this.handleResponse(response, options, cancellationToken, resolve, reject, redirectCount, requestProcessor);
                }
                catch (e) {
                    reject(e);
                }
            });
            this.addErrorAndTimeoutHandlers(request, reject, options.timeout);
            this.addRedirectHandlers(request, options, reject, redirectCount, options => {
                this.doApiRequest(options, cancellationToken, requestProcessor, redirectCount).then(resolve).catch(reject);
            });
            requestProcessor(request, reject);
            onCancel(() => request.abort());
        });
    }
    // noinspection JSUnusedLocalSymbols
    // eslint-disable-next-line
    addRedirectHandlers(request, options, reject, redirectCount, handler) {
        // not required for NodeJS
    }
    addErrorAndTimeoutHandlers(request, reject, timeout = 60 * 1000) {
        this.addTimeOutHandler(request, reject, timeout);
        request.on("error", reject);
        request.on("aborted", () => {
            reject(new Error("Request has been aborted by the server"));
        });
    }
    handleResponse(response, options, cancellationToken, resolve, reject, redirectCount, requestProcessor) {
        var _a;
        if (debug.enabled) {
            debug(`Response: ${response.statusCode} ${response.statusMessage}, request options: ${safeStringifyJson(options)}`);
        }
        // we handle any other >= 400 error on request end (read detailed message in the response body)
        if (response.statusCode === 404) {
            // error is clear, we don't need to read detailed error description
            reject(createHttpError(response, `method: ${options.method || "GET"} url: ${options.protocol || "https:"}//${options.hostname}${options.port ? `:${options.port}` : ""}${options.path}

Please double check that your authentication token is correct. Due to security reasons, actual status maybe not reported, but 404.
`));
            return;
        }
        else if (response.statusCode === 204) {
            // on DELETE request
            resolve();
            return;
        }
        const code = (_a = response.statusCode) !== null && _a !== void 0 ? _a : 0;
        const shouldRedirect = code >= 300 && code < 400;
        const redirectUrl = safeGetHeader(response, "location");
        if (shouldRedirect && redirectUrl != null) {
            if (redirectCount > this.maxRedirects) {
                reject(this.createMaxRedirectError());
                return;
            }
            this.doApiRequest(HttpExecutor.prepareRedirectUrlOptions(redirectUrl, options), cancellationToken, requestProcessor, redirectCount).then(resolve).catch(reject);
            return;
        }
        response.setEncoding("utf8");
        let data = "";
        response.on("error", reject);
        response.on("data", (chunk) => (data += chunk));
        response.on("end", () => {
            try {
                if (response.statusCode != null && response.statusCode >= 400) {
                    const contentType = safeGetHeader(response, "content-type");
                    const isJson = contentType != null && (Array.isArray(contentType) ? contentType.find(it => it.includes("json")) != null : contentType.includes("json"));
                    reject(createHttpError(response, `method: ${options.method || "GET"} url: ${options.protocol || "https:"}//${options.hostname}${options.port ? `:${options.port}` : ""}${options.path}

          Data:
          ${isJson ? JSON.stringify(JSON.parse(data)) : data}
          `));
                }
                else {
                    resolve(data.length === 0 ? null : data);
                }
            }
            catch (e) {
                reject(e);
            }
        });
    }
    async downloadToBuffer(url, options) {
        return await options.cancellationToken.createPromise((resolve, reject, onCancel) => {
            const responseChunks = [];
            const requestOptions = {
                headers: options.headers || undefined,
                // because PrivateGitHubProvider requires HttpExecutor.prepareRedirectUrlOptions logic, so, we need to redirect manually
                redirect: "manual",
            };
            configureRequestUrl(url, requestOptions);
            configureRequestOptions(requestOptions);
            this.doDownload(requestOptions, {
                destination: null,
                options,
                onCancel,
                callback: error => {
                    if (error == null) {
                        resolve(Buffer.concat(responseChunks));
                    }
                    else {
                        reject(error);
                    }
                },
                responseHandler: (response, callback) => {
                    let receivedLength = 0;
                    response.on("data", (chunk) => {
                        receivedLength += chunk.length;
                        if (receivedLength > 524288000) {
                            callback(new Error("Maximum allowed size is 500 MB"));
                            return;
                        }
                        responseChunks.push(chunk);
                    });
                    response.on("end", () => {
                        callback(null);
                    });
                },
            }, 0);
        });
    }
    doDownload(requestOptions, options, redirectCount) {
        const request = this.createRequest(requestOptions, (response) => {
            if (response.statusCode >= 400) {
                options.callback(new Error(`Cannot download "${requestOptions.protocol || "https:"}//${requestOptions.hostname}${requestOptions.path}", status ${response.statusCode}: ${response.statusMessage}`));
                return;
            }
            // It is possible for the response stream to fail, e.g. when a network is lost while
            // response stream is in progress. Stop waiting and reject so consumer can catch the error.
            response.on("error", options.callback);
            // this code not relevant for Electron (redirect event instead handled)
            const redirectUrl = safeGetHeader(response, "location");
            if (redirectUrl != null) {
                if (redirectCount < this.maxRedirects) {
                    this.doDownload(HttpExecutor.prepareRedirectUrlOptions(redirectUrl, requestOptions), options, redirectCount++);
                }
                else {
                    options.callback(this.createMaxRedirectError());
                }
                return;
            }
            if (options.responseHandler == null) {
                configurePipes(options, response);
            }
            else {
                options.responseHandler(response, options.callback);
            }
        });
        this.addErrorAndTimeoutHandlers(request, options.callback, requestOptions.timeout);
        this.addRedirectHandlers(request, requestOptions, options.callback, redirectCount, requestOptions => {
            this.doDownload(requestOptions, options, redirectCount++);
        });
        request.end();
    }
    createMaxRedirectError() {
        return new Error(`Too many redirects (> ${this.maxRedirects})`);
    }
    addTimeOutHandler(request, callback, timeout) {
        request.on("socket", (socket) => {
            socket.setTimeout(timeout, () => {
                request.abort();
                callback(new Error("Request timed out"));
            });
        });
    }
    static prepareRedirectUrlOptions(redirectUrl, options) {
        const newOptions = configureRequestOptionsFromUrl(redirectUrl, { ...options });
        const headers = newOptions.headers;
        if (headers === null || headers === void 0 ? void 0 : headers.authorization) {
            const parsedNewUrl = new url_1.URL(redirectUrl);
            if (parsedNewUrl.hostname.endsWith(".amazonaws.com") || parsedNewUrl.searchParams.has("X-Amz-Credential")) {
                delete headers.authorization;
            }
        }
        return newOptions;
    }
    static retryOnServerError(task, maxRetries = 3) {
        for (let attemptNumber = 0;; attemptNumber++) {
            try {
                return task();
            }
            catch (e) {
                if (attemptNumber < maxRetries && ((e instanceof HttpError && e.isServerError()) || e.code === "EPIPE")) {
                    continue;
                }
                throw e;
            }
        }
    }
}
exports.HttpExecutor = HttpExecutor;
function configureRequestOptionsFromUrl(url, options) {
    const result = configureRequestOptions(options);
    configureRequestUrl(new url_1.URL(url), result);
    return result;
}
function configureRequestUrl(url, options) {
    options.protocol = url.protocol;
    options.hostname = url.hostname;
    if (url.port) {
        options.port = url.port;
    }
    else if (options.port) {
        delete options.port;
    }
    options.path = url.pathname + url.search;
}
class DigestTransform extends stream_1.Transform {
    // noinspection JSUnusedGlobalSymbols
    get actual() {
        return this._actual;
    }
    constructor(expected, algorithm = "sha512", encoding = "base64") {
        super();
        this.expected = expected;
        this.algorithm = algorithm;
        this.encoding = encoding;
        this._actual = null;
        this.isValidateOnEnd = true;
        this.digester = (0, crypto_1.createHash)(algorithm);
    }
    // noinspection JSUnusedGlobalSymbols
    _transform(chunk, encoding, callback) {
        this.digester.update(chunk);
        callback(null, chunk);
    }
    // noinspection JSUnusedGlobalSymbols
    _flush(callback) {
        this._actual = this.digester.digest(this.encoding);
        if (this.isValidateOnEnd) {
            try {
                this.validate();
            }
            catch (e) {
                callback(e);
                return;
            }
        }
        callback(null);
    }
    validate() {
        if (this._actual == null) {
            throw (0, error_1.newError)("Not finished yet", "ERR_STREAM_NOT_FINISHED");
        }
        if (this._actual !== this.expected) {
            throw (0, error_1.newError)(`${this.algorithm} checksum mismatch, expected ${this.expected}, got ${this._actual}`, "ERR_CHECKSUM_MISMATCH");
        }
        return null;
    }
}
exports.DigestTransform = DigestTransform;
function checkSha2(sha2Header, sha2, callback) {
    if (sha2Header != null && sha2 != null && sha2Header !== sha2) {
        callback(new Error(`checksum mismatch: expected ${sha2} but got ${sha2Header} (X-Checksum-Sha2 header)`));
        return false;
    }
    return true;
}
function safeGetHeader(response, headerKey) {
    const value = response.headers[headerKey];
    if (value == null) {
        return null;
    }
    else if (Array.isArray(value)) {
        // electron API
        return value.length === 0 ? null : value[value.length - 1];
    }
    else {
        return value;
    }
}
function configurePipes(options, response) {
    if (!checkSha2(safeGetHeader(response, "X-Checksum-Sha2"), options.options.sha2, options.callback)) {
        return;
    }
    const streams = [];
    if (options.options.onProgress != null) {
        const contentLength = safeGetHeader(response, "content-length");
        if (contentLength != null) {
            streams.push(new ProgressCallbackTransform_1.ProgressCallbackTransform(parseInt(contentLength, 10), options.options.cancellationToken, options.options.onProgress));
        }
    }
    const sha512 = options.options.sha512;
    if (sha512 != null) {
        streams.push(new DigestTransform(sha512, "sha512", sha512.length === 128 && !sha512.includes("+") && !sha512.includes("Z") && !sha512.includes("=") ? "hex" : "base64"));
    }
    else if (options.options.sha2 != null) {
        streams.push(new DigestTransform(options.options.sha2, "sha256", "hex"));
    }
    const fileOut = (0, fs_1.createWriteStream)(options.destination);
    streams.push(fileOut);
    let lastStream = response;
    for (const stream of streams) {
        stream.on("error", (error) => {
            fileOut.close();
            if (!options.options.cancellationToken.cancelled) {
                options.callback(error);
            }
        });
        lastStream = lastStream.pipe(stream);
    }
    fileOut.on("finish", () => {
        ;
        fileOut.close(options.callback);
    });
}
function configureRequestOptions(options, token, method) {
    if (method != null) {
        options.method = method;
    }
    options.headers = { ...options.headers };
    const headers = options.headers;
    if (token != null) {
        ;
        headers.authorization = token.startsWith("Basic") || token.startsWith("Bearer") ? token : `token ${token}`;
    }
    if (headers["User-Agent"] == null) {
        headers["User-Agent"] = "electron-builder";
    }
    if (method == null || method === "GET" || headers["Cache-Control"] == null) {
        headers["Cache-Control"] = "no-cache";
    }
    // do not specify for node (in any case we use https module)
    if (options.protocol == null && process.versions.electron != null) {
        options.protocol = "https:";
    }
    return options;
}
function safeStringifyJson(data, skippedNames) {
    return JSON.stringify(data, (name, value) => {
        if (name.endsWith("Authorization") ||
            name.endsWith("authorization") ||
            name.endsWith("Password") ||
            name.endsWith("PASSWORD") ||
            name.endsWith("Token") ||
            name.includes("password") ||
            name.includes("token") ||
            (skippedNames != null && skippedNames.has(name))) {
            return "<stripped sensitive data>";
        }
        return value;
    }, 2);
}
//# sourceMappingURL=httpExecutor.js.map{"version":3,"file":"httpExecutor.js","sourceRoot":"","sources":["../src/httpExecutor.ts"],"names":[],"mappings":"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","sourcesContent":["import { BinaryToTextEncoding, createHash, Hash } from \"crypto\"\nimport _debug from \"debug\"\nimport { createWriteStream } from \"fs\"\nimport { IncomingMessage, OutgoingHttpHeader, OutgoingHttpHeaders, RequestOptions } from \"http\"\nimport { Socket } from \"net\"\nimport { Transform } from \"stream\"\nimport { URL } from \"url\"\nimport { Nullish } from \".\"\nimport { CancellationToken } from \"./CancellationToken\"\nimport { newError } from \"./error\"\nimport { ProgressCallbackTransform, ProgressInfo } from \"./ProgressCallbackTransform\"\n\nconst debug = _debug(\"electron-builder\")\n\nexport interface RequestHeaders extends OutgoingHttpHeaders {\n  [key: string]: OutgoingHttpHeader | undefined\n}\n\nexport interface DownloadOptions {\n  readonly headers?: OutgoingHttpHeaders | null\n  readonly sha2?: string | null\n  readonly sha512?: string | null\n\n  readonly cancellationToken: CancellationToken\n\n  // noinspection JSUnusedLocalSymbols\n  onProgress?: (progress: ProgressInfo) => void\n}\n\nexport function createHttpError(response: IncomingMessage, description: any | null = null) {\n  return new HttpError(\n    response.statusCode || -1,\n    `${response.statusCode} ${response.statusMessage}` +\n      (description == null ? \"\" : \"\\n\" + JSON.stringify(description, null, \"  \")) +\n      \"\\nHeaders: \" +\n      safeStringifyJson(response.headers),\n    description\n  )\n}\n\nconst HTTP_STATUS_CODES = new Map<number, string>([\n  [429, \"Too many requests\"],\n  [400, \"Bad request\"],\n  [403, \"Forbidden\"],\n  [404, \"Not found\"],\n  [405, \"Method not allowed\"],\n  [406, \"Not acceptable\"],\n  [408, \"Request timeout\"],\n  [413, \"Request entity too large\"],\n  [500, \"Internal server error\"],\n  [502, \"Bad gateway\"],\n  [503, \"Service unavailable\"],\n  [504, \"Gateway timeout\"],\n  [505, \"HTTP version not supported\"],\n])\n\nexport class HttpError extends Error {\n  constructor(\n    readonly statusCode: number,\n    message = `HTTP error: ${HTTP_STATUS_CODES.get(statusCode) || statusCode}`,\n    readonly description: any | null = null\n  ) {\n    super(message)\n\n    this.name = \"HttpError\"\n    ;(this as NodeJS.ErrnoException).code = `HTTP_ERROR_${statusCode}`\n  }\n\n  isServerError() {\n    return this.statusCode >= 500 && this.statusCode <= 599\n  }\n}\n\nexport function parseJson(result: Promise<string | null>) {\n  return result.then(it => (it == null || it.length === 0 ? null : JSON.parse(it)))\n}\n\ninterface Request {\n  abort: () => void\n  end: (data?: Buffer) => void\n}\nexport abstract class HttpExecutor<T extends Request> {\n  protected readonly maxRedirects = 10\n\n  request(options: RequestOptions, cancellationToken: CancellationToken = new CancellationToken(), data?: { [name: string]: any } | null): Promise<string | null> {\n    configureRequestOptions(options)\n    const json = data == null ? undefined : JSON.stringify(data)\n    const encodedData = json ? Buffer.from(json) : undefined\n    if (encodedData != null) {\n      debug(json!)\n      const { headers, ...opts } = options\n      options = {\n        method: \"post\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          \"Content-Length\": encodedData.length,\n          ...headers,\n        },\n        ...opts,\n      }\n    }\n    return this.doApiRequest(options, cancellationToken, it => it.end(encodedData))\n  }\n\n  doApiRequest(\n    options: RequestOptions,\n    cancellationToken: CancellationToken,\n    requestProcessor: (request: T, reject: (error: Error) => void) => void,\n    redirectCount = 0\n  ): Promise<string> {\n    if (debug.enabled) {\n      debug(`Request: ${safeStringifyJson(options)}`)\n    }\n\n    return cancellationToken.createPromise<string>((resolve, reject, onCancel) => {\n      const request = this.createRequest(options, (response: any) => {\n        try {\n          this.handleResponse(response, options, cancellationToken, resolve, reject, redirectCount, requestProcessor)\n        } catch (e: any) {\n          reject(e)\n        }\n      })\n      this.addErrorAndTimeoutHandlers(request, reject, options.timeout)\n      this.addRedirectHandlers(request, options, reject, redirectCount, options => {\n        this.doApiRequest(options, cancellationToken, requestProcessor, redirectCount).then(resolve).catch(reject)\n      })\n      requestProcessor(request, reject)\n      onCancel(() => request.abort())\n    })\n  }\n\n  // noinspection JSUnusedLocalSymbols\n  // eslint-disable-next-line\n  protected addRedirectHandlers(request: any, options: RequestOptions, reject: (error: Error) => void, redirectCount: number, handler: (options: RequestOptions) => void) {\n    // not required for NodeJS\n  }\n\n  addErrorAndTimeoutHandlers(request: any, reject: (error: Error) => void, timeout = 60 * 1000) {\n    this.addTimeOutHandler(request, reject, timeout)\n    request.on(\"error\", reject)\n    request.on(\"aborted\", () => {\n      reject(new Error(\"Request has been aborted by the server\"))\n    })\n  }\n\n  private handleResponse(\n    response: IncomingMessage,\n    options: RequestOptions,\n    cancellationToken: CancellationToken,\n    resolve: (data?: any) => void,\n    reject: (error: Error) => void,\n    redirectCount: number,\n    requestProcessor: (request: T, reject: (error: Error) => void) => void\n  ) {\n    if (debug.enabled) {\n      debug(`Response: ${response.statusCode} ${response.statusMessage}, request options: ${safeStringifyJson(options)}`)\n    }\n\n    // we handle any other >= 400 error on request end (read detailed message in the response body)\n    if (response.statusCode === 404) {\n      // error is clear, we don't need to read detailed error description\n      reject(\n        createHttpError(\n          response,\n          `method: ${options.method || \"GET\"} url: ${options.protocol || \"https:\"}//${options.hostname}${options.port ? `:${options.port}` : \"\"}${options.path}\n\nPlease double check that your authentication token is correct. Due to security reasons, actual status maybe not reported, but 404.\n`\n        )\n      )\n      return\n    } else if (response.statusCode === 204) {\n      // on DELETE request\n      resolve()\n      return\n    }\n\n    const code = response.statusCode ?? 0\n    const shouldRedirect = code >= 300 && code < 400\n    const redirectUrl = safeGetHeader(response, \"location\")\n    if (shouldRedirect && redirectUrl != null) {\n      if (redirectCount > this.maxRedirects) {\n        reject(this.createMaxRedirectError())\n        return\n      }\n\n      this.doApiRequest(HttpExecutor.prepareRedirectUrlOptions(redirectUrl, options), cancellationToken, requestProcessor, redirectCount).then(resolve).catch(reject)\n      return\n    }\n\n    response.setEncoding(\"utf8\")\n\n    let data = \"\"\n    response.on(\"error\", reject)\n    response.on(\"data\", (chunk: string) => (data += chunk))\n    response.on(\"end\", () => {\n      try {\n        if (response.statusCode != null && response.statusCode >= 400) {\n          const contentType = safeGetHeader(response, \"content-type\")\n          const isJson = contentType != null && (Array.isArray(contentType) ? contentType.find(it => it.includes(\"json\")) != null : contentType.includes(\"json\"))\n          reject(\n            createHttpError(\n              response,\n              `method: ${options.method || \"GET\"} url: ${options.protocol || \"https:\"}//${options.hostname}${options.port ? `:${options.port}` : \"\"}${options.path}\n\n          Data:\n          ${isJson ? JSON.stringify(JSON.parse(data)) : data}\n          `\n            )\n          )\n        } else {\n          resolve(data.length === 0 ? null : data)\n        }\n      } catch (e: any) {\n        reject(e)\n      }\n    })\n  }\n\n  // noinspection JSUnusedLocalSymbols\n  abstract createRequest(options: RequestOptions, callback: (response: any) => void): T\n\n  async downloadToBuffer(url: URL, options: DownloadOptions): Promise<Buffer> {\n    return await options.cancellationToken.createPromise<Buffer>((resolve, reject, onCancel) => {\n      const responseChunks: Buffer[] = []\n      const requestOptions = {\n        headers: options.headers || undefined,\n        // because PrivateGitHubProvider requires HttpExecutor.prepareRedirectUrlOptions logic, so, we need to redirect manually\n        redirect: \"manual\",\n      }\n      configureRequestUrl(url, requestOptions)\n      configureRequestOptions(requestOptions)\n      this.doDownload(\n        requestOptions,\n        {\n          destination: null,\n          options,\n          onCancel,\n          callback: error => {\n            if (error == null) {\n              resolve(Buffer.concat(responseChunks))\n            } else {\n              reject(error)\n            }\n          },\n          responseHandler: (response, callback) => {\n            let receivedLength = 0\n            response.on(\"data\", (chunk: Buffer) => {\n              receivedLength += chunk.length\n              if (receivedLength > 524288000) {\n                callback(new Error(\"Maximum allowed size is 500 MB\"))\n                return\n              }\n              responseChunks.push(chunk)\n            })\n            response.on(\"end\", () => {\n              callback(null)\n            })\n          },\n        },\n        0\n      )\n    })\n  }\n\n  protected doDownload(requestOptions: RequestOptions, options: DownloadCallOptions, redirectCount: number) {\n    const request = this.createRequest(requestOptions, (response: IncomingMessage) => {\n      if (response.statusCode! >= 400) {\n        options.callback(\n          new Error(\n            `Cannot download \"${requestOptions.protocol || \"https:\"}//${requestOptions.hostname}${requestOptions.path}\", status ${response.statusCode}: ${response.statusMessage}`\n          )\n        )\n        return\n      }\n\n      // It is possible for the response stream to fail, e.g. when a network is lost while\n      // response stream is in progress. Stop waiting and reject so consumer can catch the error.\n      response.on(\"error\", options.callback)\n\n      // this code not relevant for Electron (redirect event instead handled)\n      const redirectUrl = safeGetHeader(response, \"location\")\n      if (redirectUrl != null) {\n        if (redirectCount < this.maxRedirects) {\n          this.doDownload(HttpExecutor.prepareRedirectUrlOptions(redirectUrl, requestOptions), options, redirectCount++)\n        } else {\n          options.callback(this.createMaxRedirectError())\n        }\n        return\n      }\n\n      if (options.responseHandler == null) {\n        configurePipes(options, response)\n      } else {\n        options.responseHandler(response, options.callback)\n      }\n    })\n    this.addErrorAndTimeoutHandlers(request, options.callback, requestOptions.timeout)\n    this.addRedirectHandlers(request, requestOptions, options.callback, redirectCount, requestOptions => {\n      this.doDownload(requestOptions, options, redirectCount++)\n    })\n    request.end()\n  }\n\n  protected createMaxRedirectError() {\n    return new Error(`Too many redirects (> ${this.maxRedirects})`)\n  }\n\n  private addTimeOutHandler(request: any, callback: (error: Error) => void, timeout: number) {\n    request.on(\"socket\", (socket: Socket) => {\n      socket.setTimeout(timeout, () => {\n        request.abort()\n        callback(new Error(\"Request timed out\"))\n      })\n    })\n  }\n\n  static prepareRedirectUrlOptions(redirectUrl: string, options: RequestOptions): RequestOptions {\n    const newOptions = configureRequestOptionsFromUrl(redirectUrl, { ...options })\n    const headers = newOptions.headers\n    if (headers?.authorization) {\n      const parsedNewUrl = new URL(redirectUrl)\n      if (parsedNewUrl.hostname.endsWith(\".amazonaws.com\") || parsedNewUrl.searchParams.has(\"X-Amz-Credential\")) {\n        delete headers.authorization\n      }\n    }\n    return newOptions\n  }\n\n  static retryOnServerError(task: () => Promise<any>, maxRetries = 3) {\n    for (let attemptNumber = 0; ; attemptNumber++) {\n      try {\n        return task()\n      } catch (e: any) {\n        if (attemptNumber < maxRetries && ((e instanceof HttpError && e.isServerError()) || e.code === \"EPIPE\")) {\n          continue\n        }\n        throw e\n      }\n    }\n  }\n}\n\nexport interface DownloadCallOptions {\n  responseHandler: ((response: IncomingMessage, callback: (error: Error | null) => void) => void) | null\n  onCancel: (callback: () => void) => void\n  callback: (error: Error | null) => void\n\n  options: DownloadOptions\n\n  destination: string | null\n}\n\nexport function configureRequestOptionsFromUrl(url: string, options: RequestOptions) {\n  const result = configureRequestOptions(options)\n  configureRequestUrl(new URL(url), result)\n  return result\n}\n\nexport function configureRequestUrl(url: URL, options: RequestOptions): void {\n  options.protocol = url.protocol\n  options.hostname = url.hostname\n  if (url.port) {\n    options.port = url.port\n  } else if (options.port) {\n    delete options.port\n  }\n  options.path = url.pathname + url.search\n}\n\nexport class DigestTransform extends Transform {\n  private readonly digester: Hash\n\n  private _actual: string | null = null\n\n  // noinspection JSUnusedGlobalSymbols\n  get actual() {\n    return this._actual\n  }\n\n  isValidateOnEnd = true\n\n  constructor(\n    readonly expected: string,\n    private readonly algorithm: string = \"sha512\",\n    private readonly encoding: BinaryToTextEncoding = \"base64\"\n  ) {\n    super()\n\n    this.digester = createHash(algorithm)\n  }\n\n  // noinspection JSUnusedGlobalSymbols\n  _transform(chunk: Buffer, encoding: string, callback: any) {\n    this.digester.update(chunk)\n    callback(null, chunk)\n  }\n\n  // noinspection JSUnusedGlobalSymbols\n  _flush(callback: any): void {\n    this._actual = this.digester.digest(this.encoding)\n\n    if (this.isValidateOnEnd) {\n      try {\n        this.validate()\n      } catch (e: any) {\n        callback(e)\n        return\n      }\n    }\n\n    callback(null)\n  }\n\n  validate() {\n    if (this._actual == null) {\n      throw newError(\"Not finished yet\", \"ERR_STREAM_NOT_FINISHED\")\n    }\n\n    if (this._actual !== this.expected) {\n      throw newError(`${this.algorithm} checksum mismatch, expected ${this.expected}, got ${this._actual}`, \"ERR_CHECKSUM_MISMATCH\")\n    }\n\n    return null\n  }\n}\n\nfunction checkSha2(sha2Header: string | Nullish, sha2: string | Nullish, callback: (error: Error | null) => void): boolean {\n  if (sha2Header != null && sha2 != null && sha2Header !== sha2) {\n    callback(new Error(`checksum mismatch: expected ${sha2} but got ${sha2Header} (X-Checksum-Sha2 header)`))\n    return false\n  }\n  return true\n}\n\nexport function safeGetHeader(response: any, headerKey: string) {\n  const value = response.headers[headerKey]\n  if (value == null) {\n    return null\n  } else if (Array.isArray(value)) {\n    // electron API\n    return value.length === 0 ? null : value[value.length - 1]\n  } else {\n    return value\n  }\n}\n\nfunction configurePipes(options: DownloadCallOptions, response: IncomingMessage) {\n  if (!checkSha2(safeGetHeader(response, \"X-Checksum-Sha2\"), options.options.sha2, options.callback)) {\n    return\n  }\n\n  const streams: Array<any> = []\n  if (options.options.onProgress != null) {\n    const contentLength = safeGetHeader(response, \"content-length\")\n    if (contentLength != null) {\n      streams.push(new ProgressCallbackTransform(parseInt(contentLength, 10), options.options.cancellationToken, options.options.onProgress))\n    }\n  }\n\n  const sha512 = options.options.sha512\n  if (sha512 != null) {\n    streams.push(new DigestTransform(sha512, \"sha512\", sha512.length === 128 && !sha512.includes(\"+\") && !sha512.includes(\"Z\") && !sha512.includes(\"=\") ? \"hex\" : \"base64\"))\n  } else if (options.options.sha2 != null) {\n    streams.push(new DigestTransform(options.options.sha2, \"sha256\", \"hex\"))\n  }\n\n  const fileOut = createWriteStream(options.destination!)\n  streams.push(fileOut)\n\n  let lastStream = response\n  for (const stream of streams) {\n    stream.on(\"error\", (error: Error) => {\n      fileOut.close()\n      if (!options.options.cancellationToken.cancelled) {\n        options.callback(error)\n      }\n    })\n    lastStream = lastStream.pipe(stream)\n  }\n\n  fileOut.on(\"finish\", () => {\n    ;(fileOut.close as any)(options.callback)\n  })\n}\n\nexport function configureRequestOptions(options: RequestOptions, token?: string | null, method?: \"GET\" | \"DELETE\" | \"PUT\" | \"POST\"): RequestOptions {\n  if (method != null) {\n    options.method = method\n  }\n\n  options.headers = { ...options.headers }\n  const headers = options.headers\n\n  if (token != null) {\n    ;(headers as any).authorization = token.startsWith(\"Basic\") || token.startsWith(\"Bearer\") ? token : `token ${token}`\n  }\n  if (headers[\"User-Agent\"] == null) {\n    headers[\"User-Agent\"] = \"electron-builder\"\n  }\n\n  if (method == null || method === \"GET\" || headers[\"Cache-Control\"] == null) {\n    headers[\"Cache-Control\"] = \"no-cache\"\n  }\n\n  // do not specify for node (in any case we use https module)\n  if (options.protocol == null && (process.versions as any).electron != null) {\n    options.protocol = \"https:\"\n  }\n  return options\n}\n\nexport function safeStringifyJson(data: any, skippedNames?: Set<string>) {\n  return JSON.stringify(\n    data,\n    (name, value) => {\n      if (\n        name.endsWith(\"Authorization\") ||\n        name.endsWith(\"authorization\") ||\n        name.endsWith(\"Password\") ||\n        name.endsWith(\"PASSWORD\") ||\n        name.endsWith(\"Token\") ||\n        name.includes(\"password\") ||\n        name.includes(\"token\") ||\n        (skippedNames != null && skippedNames.has(name))\n      ) {\n        return \"<stripped sensitive data>\"\n      }\n      return value\n    },\n    2\n  )\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CURRENT_APP_PACKAGE_FILE_NAME = exports.CURRENT_APP_INSTALLER_FILE_NAME = exports.XElement = exports.parseXml = exports.UUID = exports.parseDn = exports.retry = exports.githubUrl = exports.getS3LikeProviderBaseUrl = exports.ProgressCallbackTransform = exports.MemoLazy = exports.safeStringifyJson = exports.safeGetHeader = exports.parseJson = exports.HttpExecutor = exports.HttpError = exports.DigestTransform = exports.createHttpError = exports.configureRequestUrl = exports.configureRequestOptionsFromUrl = exports.configureRequestOptions = exports.newError = exports.CancellationToken = exports.CancellationError = void 0;
exports.asArray = asArray;
var CancellationToken_1 = require("./CancellationToken");
Object.defineProperty(exports, "CancellationError", { enumerable: true, get: function () { return CancellationToken_1.CancellationError; } });
Object.defineProperty(exports, "CancellationToken", { enumerable: true, get: function () { return CancellationToken_1.CancellationToken; } });
var error_1 = require("./error");
Object.defineProperty(exports, "newError", { enumerable: true, get: function () { return error_1.newError; } });
var httpExecutor_1 = require("./httpExecutor");
Object.defineProperty(exports, "configureRequestOptions", { enumerable: true, get: function () { return httpExecutor_1.configureRequestOptions; } });
Object.defineProperty(exports, "configureRequestOptionsFromUrl", { enumerable: true, get: function () { return httpExecutor_1.configureRequestOptionsFromUrl; } });
Object.defineProperty(exports, "configureRequestUrl", { enumerable: true, get: function () { return httpExecutor_1.configureRequestUrl; } });
Object.defineProperty(exports, "createHttpError", { enumerable: true, get: function () { return httpExecutor_1.createHttpError; } });
Object.defineProperty(exports, "DigestTransform", { enumerable: true, get: function () { return httpExecutor_1.DigestTransform; } });
Object.defineProperty(exports, "HttpError", { enumerable: true, get: function () { return httpExecutor_1.HttpError; } });
Object.defineProperty(exports, "HttpExecutor", { enumerable: true, get: function () { return httpExecutor_1.HttpExecutor; } });
Object.defineProperty(exports, "parseJson", { enumerable: true, get: function () { return httpExecutor_1.parseJson; } });
Object.defineProperty(exports, "safeGetHeader", { enumerable: true, get: function () { return httpExecutor_1.safeGetHeader; } });
Object.defineProperty(exports, "safeStringifyJson", { enumerable: true, get: function () { return httpExecutor_1.safeStringifyJson; } });
var MemoLazy_1 = require("./MemoLazy");
Object.defineProperty(exports, "MemoLazy", { enumerable: true, get: function () { return MemoLazy_1.MemoLazy; } });
var ProgressCallbackTransform_1 = require("./ProgressCallbackTransform");
Object.defineProperty(exports, "ProgressCallbackTransform", { enumerable: true, get: function () { return ProgressCallbackTransform_1.ProgressCallbackTransform; } });
var publishOptions_1 = require("./publishOptions");
Object.defineProperty(exports, "getS3LikeProviderBaseUrl", { enumerable: true, get: function () { return publishOptions_1.getS3LikeProviderBaseUrl; } });
Object.defineProperty(exports, "githubUrl", { enumerable: true, get: function () { return publishOptions_1.githubUrl; } });
var retry_1 = require("./retry");
Object.defineProperty(exports, "retry", { enumerable: true, get: function () { return retry_1.retry; } });
var rfc2253Parser_1 = require("./rfc2253Parser");
Object.defineProperty(exports, "parseDn", { enumerable: true, get: function () { return rfc2253Parser_1.parseDn; } });
var uuid_1 = require("./uuid");
Object.defineProperty(exports, "UUID", { enumerable: true, get: function () { return uuid_1.UUID; } });
var xml_1 = require("./xml");
Object.defineProperty(exports, "parseXml", { enumerable: true, get: function () { return xml_1.parseXml; } });
Object.defineProperty(exports, "XElement", { enumerable: true, get: function () { return xml_1.XElement; } });
// nsis
exports.CURRENT_APP_INSTALLER_FILE_NAME = "installer.exe";
// nsis-web
exports.CURRENT_APP_PACKAGE_FILE_NAME = "package.7z";
function asArray(v) {
    if (v == null) {
        return [];
    }
    else if (Array.isArray(v)) {
        return v;
    }
    else {
        return [v];
    }
}
//# sourceMappingURL=index.js.map{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AA8CA,0BAQC;AArDD,yDAA0E;AAAjE,sHAAA,iBAAiB,OAAA;AAAE,sHAAA,iBAAiB,OAAA;AAC7C,iCAAkC;AAAzB,iGAAA,QAAQ,OAAA;AACjB,+CAauB;AAZrB,uHAAA,uBAAuB,OAAA;AACvB,8HAAA,8BAA8B,OAAA;AAC9B,mHAAA,mBAAmB,OAAA;AACnB,+GAAA,eAAe,OAAA;AACf,+GAAA,eAAe,OAAA;AAEf,yGAAA,SAAS,OAAA;AACT,4GAAA,YAAY,OAAA;AACZ,yGAAA,SAAS,OAAA;AAET,6GAAA,aAAa,OAAA;AACb,iHAAA,iBAAiB,OAAA;AAEnB,uCAAqC;AAA5B,oGAAA,QAAQ,OAAA;AACjB,yEAAqF;AAA5E,sIAAA,yBAAyB,OAAA;AAClC,mDAeyB;AATvB,0HAAA,wBAAwB,OAAA;AAExB,2GAAA,SAAS,OAAA;AAQX,iCAA+B;AAAtB,8FAAA,KAAK,OAAA;AACd,iDAAyC;AAAhC,wGAAA,OAAO,OAAA;AAEhB,+BAA6B;AAApB,4FAAA,IAAI,OAAA;AACb,6BAA0C;AAAjC,+FAAA,QAAQ,OAAA;AAAE,+FAAA,QAAQ,OAAA;AAE3B,OAAO;AACM,QAAA,+BAA+B,GAAG,eAAe,CAAA;AAC9D,WAAW;AACE,QAAA,6BAA6B,GAAG,YAAY,CAAA;AAEzD,SAAgB,OAAO,CAAI,CAAyB;IAClD,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QACd,OAAO,EAAE,CAAA;IACX,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,CAAA;IACV,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,CAAC,CAAC,CAAA;IACZ,CAAC;AACH,CAAC","sourcesContent":["export { BlockMap } from \"./blockMapApi\"\nexport { CancellationError, CancellationToken } from \"./CancellationToken\"\nexport { newError } from \"./error\"\nexport {\n  configureRequestOptions,\n  configureRequestOptionsFromUrl,\n  configureRequestUrl,\n  createHttpError,\n  DigestTransform,\n  DownloadOptions,\n  HttpError,\n  HttpExecutor,\n  parseJson,\n  RequestHeaders,\n  safeGetHeader,\n  safeStringifyJson,\n} from \"./httpExecutor\"\nexport { MemoLazy } from \"./MemoLazy\"\nexport { ProgressCallbackTransform, ProgressInfo } from \"./ProgressCallbackTransform\"\nexport {\n  AllPublishOptions,\n  BaseS3Options,\n  BitbucketOptions,\n  CustomPublishOptions,\n  GenericServerOptions,\n  getS3LikeProviderBaseUrl,\n  GithubOptions,\n  githubUrl,\n  KeygenOptions,\n  PublishConfiguration,\n  PublishProvider,\n  S3Options,\n  SnapStoreOptions,\n  SpacesOptions,\n} from \"./publishOptions\"\nexport { retry } from \"./retry\"\nexport { parseDn } from \"./rfc2253Parser\"\nexport { BlockMapDataHolder, PackageFileInfo, ReleaseNoteInfo, UpdateFileInfo, UpdateInfo, WindowsUpdateInfo } from \"./updateInfo\"\nexport { UUID } from \"./uuid\"\nexport { parseXml, XElement } from \"./xml\"\n\n// nsis\nexport const CURRENT_APP_INSTALLER_FILE_NAME = \"installer.exe\"\n// nsis-web\nexport const CURRENT_APP_PACKAGE_FILE_NAME = \"package.7z\"\n\nexport function asArray<T>(v: Nullish | T | Array<T>): Array<T> {\n  if (v == null) {\n    return []\n  } else if (Array.isArray(v)) {\n    return v\n  } else {\n    return [v]\n  }\n}\n\nexport type Nullish = null | undefined\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.githubUrl = githubUrl;
exports.getS3LikeProviderBaseUrl = getS3LikeProviderBaseUrl;
/** @private */
function githubUrl(options, defaultHost = "github.com") {
    return `${options.protocol || "https"}://${options.host || defaultHost}`;
}
function getS3LikeProviderBaseUrl(configuration) {
    const provider = configuration.provider;
    if (provider === "s3") {
        return s3Url(configuration);
    }
    if (provider === "spaces") {
        return spacesUrl(configuration);
    }
    throw new Error(`Not supported provider: ${provider}`);
}
function s3Url(options) {
    let url;
    if (options.accelerate == true) {
        url = `https://${options.bucket}.s3-accelerate.amazonaws.com`;
    }
    else if (options.endpoint != null) {
        url = `${options.endpoint}/${options.bucket}`;
    }
    else if (options.bucket.includes(".")) {
        if (options.region == null) {
            throw new Error(`Bucket name "${options.bucket}" includes a dot, but S3 region is missing`);
        }
        // special case, see http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html#access-bucket-intro
        if (options.region === "us-east-1") {
            url = `https://s3.amazonaws.com/${options.bucket}`;
        }
        else {
            url = `https://s3-${options.region}.amazonaws.com/${options.bucket}`;
        }
    }
    else if (options.region === "cn-north-1") {
        url = `https://${options.bucket}.s3.${options.region}.amazonaws.com.cn`;
    }
    else {
        url = `https://${options.bucket}.s3.amazonaws.com`;
    }
    return appendPath(url, options.path);
}
function appendPath(url, p) {
    if (p != null && p.length > 0) {
        if (!p.startsWith("/")) {
            url += "/";
        }
        url += p;
    }
    return url;
}
function spacesUrl(options) {
    if (options.name == null) {
        throw new Error(`name is missing`);
    }
    if (options.region == null) {
        throw new Error(`region is missing`);
    }
    return appendPath(`https://${options.name}.${options.region}.digitaloceanspaces.com`, options.path);
}
//# sourceMappingURL=publishOptions.js.map{"version":3,"file":"publishOptions.js","sourceRoot":"","sources":["../src/publishOptions.ts"],"names":[],"mappings":";;AA4IA,8BAEC;AA4PD,4DASC;AAxQD,eAAe;AACf,SAAgB,SAAS,CAAC,OAAsB,EAAE,WAAW,GAAG,YAAY;IAC1E,OAAO,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,MAAM,OAAO,CAAC,IAAI,IAAI,WAAW,EAAE,CAAA;AAC1E,CAAC;AA4PD,SAAgB,wBAAwB,CAAC,aAAmC;IAC1E,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAA;IACvC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC,aAA0B,CAAC,CAAA;IAC1C,CAAC;IACD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC,aAA8B,CAAC,CAAA;IAClD,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAA;AACxD,CAAC;AAED,SAAS,KAAK,CAAC,OAAkB;IAC/B,IAAI,GAAW,CAAA;IACf,IAAI,OAAO,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;QAC/B,GAAG,GAAG,WAAW,OAAO,CAAC,MAAM,8BAA8B,CAAA;IAC/D,CAAC;SAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;QACpC,GAAG,GAAG,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,CAAA;IAC/C,CAAC;SAAM,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACxC,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,gBAAgB,OAAO,CAAC,MAAM,4CAA4C,CAAC,CAAA;QAC7F,CAAC;QAED,wGAAwG;QACxG,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACnC,GAAG,GAAG,4BAA4B,OAAO,CAAC,MAAM,EAAE,CAAA;QACpD,CAAC;aAAM,CAAC;YACN,GAAG,GAAG,cAAc,OAAO,CAAC,MAAM,kBAAkB,OAAO,CAAC,MAAM,EAAE,CAAA;QACtE,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QAC3C,GAAG,GAAG,WAAW,OAAO,CAAC,MAAM,OAAO,OAAO,CAAC,MAAM,mBAAmB,CAAA;IACzE,CAAC;SAAM,CAAC;QACN,GAAG,GAAG,WAAW,OAAO,CAAC,MAAM,mBAAmB,CAAA;IACpD,CAAC;IACD,OAAO,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;AACtC,CAAC;AAED,SAAS,UAAU,CAAC,GAAW,EAAE,CAAmB;IAClD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,GAAG,IAAI,GAAG,CAAA;QACZ,CAAC;QACD,GAAG,IAAI,CAAC,CAAA;IACV,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,SAAS,CAAC,OAAsB;IACvC,IAAI,OAAO,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;IACpC,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAA;IACtC,CAAC;IACD,OAAO,UAAU,CAAC,WAAW,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,yBAAyB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;AACrG,CAAC","sourcesContent":["import { OutgoingHttpHeaders } from \"http\"\nimport { Nullish } from \".\"\n\nexport type PublishProvider = \"github\" | \"s3\" | \"spaces\" | \"generic\" | \"custom\" | \"snapStore\" | \"keygen\" | \"bitbucket\"\n\n// typescript-json-schema generates only PublishConfiguration if it is specified in the list, so, it is not added here\nexport type AllPublishOptions =\n  | string\n  | GithubOptions\n  | S3Options\n  | SpacesOptions\n  | GenericServerOptions\n  | CustomPublishOptions\n  | KeygenOptions\n  | SnapStoreOptions\n  | BitbucketOptions\n\nexport interface PublishConfiguration {\n  /**\n   * The provider.\n   */\n  readonly provider: PublishProvider\n\n  /**\n   * @private\n   * win-only\n   */\n  publisherName?: Array<string> | null\n\n  /**\n   * @private\n   * win-only\n   */\n  readonly updaterCacheDirName?: string | null\n\n  /**\n   * Whether to publish auto update info files.\n   *\n   * Auto update relies only on the first provider in the list (you can specify several publishers).\n   * Thus, probably, there`s no need to upload the metadata files for the other configured providers. But by default will be uploaded.\n   *\n   * @default true\n   */\n  readonly publishAutoUpdate?: boolean\n\n  /**\n   * Any custom request headers\n   */\n  readonly requestHeaders?: OutgoingHttpHeaders\n\n  /**\n   * Request timeout in milliseconds. (Default is 2 minutes; O is ignored)\n   *\n   * @default 120000\n   */\n  readonly timeout?: number | null\n}\n\n// https://github.com/electron-userland/electron-builder/issues/3261\nexport interface CustomPublishOptions extends PublishConfiguration {\n  /**\n   * The provider. Must be `custom`.\n   */\n  readonly provider: \"custom\"\n\n  /**\n   * The Provider to provide UpdateInfo regarding available updates.  Required\n   * to use custom providers with electron-updater.\n   */\n  updateProvider?: new (options: CustomPublishOptions, updater: any, runtimeOptions: any) => any\n\n  [index: string]: any\n}\n\n/**\n * [GitHub](https://help.github.com/articles/about-releases/) options.\n *\n * GitHub [personal access token](https://help.github.com/articles/creating-an-access-token-for-command-line-use/) is required. You can generate by going to [https://github.com/settings/tokens/new](https://github.com/settings/tokens/new). The access token should have the repo scope/permission.\n * Define `GH_TOKEN` environment variable.\n */\nexport interface GithubOptions extends PublishConfiguration {\n  /**\n   * The provider. Must be `github`.\n   */\n  readonly provider: \"github\"\n\n  /**\n   * The repository name. [Detected automatically](#github-repository-and-bintray-package).\n   */\n  readonly repo?: string | null\n\n  /**\n   * The owner.\n   */\n  readonly owner?: string | null\n\n  /**\n   * Whether to use `v`-prefixed tag name.\n   * @default true\n   */\n  readonly vPrefixedTagName?: boolean\n\n  /**\n   * The host (including the port if need).\n   * @default github.com\n   */\n  readonly host?: string | null\n\n  /**\n   * The protocol. GitHub Publisher supports only `https`.\n   * @default https\n   */\n  readonly protocol?: \"https\" | \"http\" | null\n\n  /**\n   * The access token to support auto-update from private github repositories. Never specify it in the configuration files. Only for [setFeedURL](./auto-update.md#appupdatersetfeedurloptions).\n   */\n  readonly token?: string | null\n\n  /**\n   * Whether to use private github auto-update provider if `GH_TOKEN` environment variable is defined. See [Private GitHub Update Repo](./auto-update.md#private-github-update-repo).\n   */\n  readonly private?: boolean | null\n\n  /**\n   * The channel.\n   * @default latest\n   */\n  readonly channel?: string | null\n\n  /**\n   * The type of release. By default `draft` release will be created.\n   *\n   * Also you can set release type using environment variable. If `EP_DRAFT`is set to `true` — `draft`, if `EP_PRE_RELEASE`is set to `true` — `prerelease`.\n   * @default draft\n   */\n  releaseType?: \"draft\" | \"prerelease\" | \"release\" | null\n}\n\n/** @private */\nexport function githubUrl(options: GithubOptions, defaultHost = \"github.com\") {\n  return `${options.protocol || \"https\"}://${options.host || defaultHost}`\n}\n\n/**\n * Generic (any HTTP(S) server) options.\n * In all publish options [File Macros](./file-patterns.md#file-macros) are supported.\n */\nexport interface GenericServerOptions extends PublishConfiguration {\n  /**\n   * The provider. Must be `generic`.\n   */\n  readonly provider: \"generic\"\n\n  /**\n   * The base url. e.g. `https://bucket_name.s3.amazonaws.com`.\n   */\n  readonly url: string\n\n  /**\n   * The channel.\n   * @default latest\n   */\n  readonly channel?: string | null\n\n  /**\n   * Whether to use multiple range requests for differential update. Defaults to `true` if `url` doesn't contain `s3.amazonaws.com`.\n   */\n  readonly useMultipleRangeRequest?: boolean\n}\n\n/**\n * Keygen options.\n * https://keygen.sh/\n * Define `KEYGEN_TOKEN` environment variable.\n */\nexport interface KeygenOptions extends PublishConfiguration {\n  /**\n   * The provider. Must be `keygen`.\n   */\n  readonly provider: \"keygen\"\n\n  /**\n   * Keygen host for self-hosted instances\n   * @default \"api.keygen.sh\"\n   */\n  readonly host?: string\n\n  /**\n   * Keygen account's UUID\n   */\n  readonly account: string\n\n  /**\n   * Keygen product's UUID\n   */\n  readonly product: string\n\n  /**\n   * The channel.\n   * @default stable\n   */\n  readonly channel?: \"stable\" | \"rc\" | \"beta\" | \"alpha\" | \"dev\" | null\n\n  /**\n   * The target Platform. Is set programmatically explicitly during publishing.\n   */\n  readonly platform?: string | null\n}\n\n/**\n * Bitbucket options.\n * https://bitbucket.org/\n * Define `BITBUCKET_TOKEN` environment variable.\n *\n * For converting an app password to a usable token, you can utilize this\n```typescript\nconvertAppPassword(owner: string, appPassword: string) {\n  const base64encodedData = Buffer.from(`${owner}:${appPassword.trim()}`).toString(\"base64\")\n  return `Basic ${base64encodedData}`\n}\n```\n */\nexport interface BitbucketOptions extends PublishConfiguration {\n  /**\n   * The provider. Must be `bitbucket`.\n   */\n  readonly provider: \"bitbucket\"\n\n  /**\n   * Repository owner\n   */\n  readonly owner: string\n\n  /**\n   * The [app password](https://bitbucket.org/account/settings/app-passwords) to support auto-update from private bitbucket repositories.\n   */\n  readonly token?: string | null\n\n  /**\n   * The user name to support auto-update from private bitbucket repositories.\n   */\n  readonly username?: string | null\n\n  /**\n   * Repository slug/name\n   */\n  readonly slug: string\n\n  /**\n   * The channel.\n   * @default latest\n   */\n  readonly channel?: string | null\n}\n\n/**\n * [Snap Store](https://snapcraft.io/) options. To publish directly to Snapcraft, see <a href=\"https://snapcraft.io/docs/snapcraft-authentication\">Snapcraft authentication options</a> for local or CI/CD authentication options.\n */\nexport interface SnapStoreOptions extends PublishConfiguration {\n  /**\n   * The provider. Must be `snapStore`.\n   */\n  readonly provider: \"snapStore\"\n\n  /**\n   * snapcraft repo name\n   */\n  readonly repo?: string\n\n  /**\n   * The list of channels the snap would be released.\n   * @default [\"edge\"]\n   */\n  readonly channels?: string | Array<string> | null\n}\n\nexport interface BaseS3Options extends PublishConfiguration {\n  /**\n   * The update channel.\n   * @default latest\n   */\n  channel?: string | null\n\n  /**\n   * The directory path.\n   * @default /\n   */\n  readonly path?: string | null\n\n  /**\n   * The ACL. Set to `null` to not [add](https://github.com/electron-userland/electron-builder/issues/1822).\n   *\n   * @default public-read\n   */\n  readonly acl?: \"private\" | \"public-read\" | null\n}\n\n/**\n * [Amazon S3](https://aws.amazon.com/s3/) options.\n * AWS credentials are required, please see [getting your credentials](http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/getting-your-credentials.html).\n * Define `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` [environment variables](http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-environment.html).\n * Or in the [~/.aws/credentials](http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-shared.html).\n *\n * Example configuration:\n *\n```json\n{\n  \"build\":\n    \"publish\": {\n      \"provider\": \"s3\",\n      \"bucket\": \"bucket-name\"\n    }\n  }\n}\n```\n */\nexport interface S3Options extends BaseS3Options {\n  /**\n   * The provider. Must be `s3`.\n   */\n  readonly provider: \"s3\"\n\n  /**\n   * The bucket name.\n   */\n  readonly bucket: string\n\n  /**\n   * The region. Is determined and set automatically when publishing.\n   */\n  region?: string | null\n\n  /**\n   * The ACL. Set to `null` to not [add](https://github.com/electron-userland/electron-builder/issues/1822).\n   *\n   * Please see [required permissions for the S3 provider](https://github.com/electron-userland/electron-builder/issues/1618#issuecomment-314679128).\n   *\n   * @default public-read\n   */\n  readonly acl?: \"private\" | \"public-read\" | null\n\n  /**\n   * The type of storage to use for the object.\n   * @default STANDARD\n   */\n  readonly storageClass?: \"STANDARD\" | \"REDUCED_REDUNDANCY\" | \"STANDARD_IA\" | null\n\n  /**\n   * Server-side encryption algorithm to use for the object.\n   */\n  readonly encryption?: \"AES256\" | \"aws:kms\" | null\n\n  /**\n   * The endpoint URI to send requests to. The default endpoint is built from the configured region.\n   * The endpoint should be a string like `https://{service}.{region}.amazonaws.com`.\n   */\n  readonly endpoint?: string | null\n\n  /**\n   * If set to true, this will enable the s3 accelerated endpoint\n   * These endpoints have a particular format of:\n   *  ${bucketname}.s3-accelerate.amazonaws.com\n   */\n  readonly accelerate?: boolean\n\n  /**\n   * When true, force a path-style endpoint to be used where the bucket name is part of the path.\n   * [Path-style Access](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#path-style-access)\n   */\n  readonly forcePathStyle?: boolean\n}\n\n/**\n * [DigitalOcean Spaces](https://www.digitalocean.com/community/tutorials/an-introduction-to-digitalocean-spaces) options.\n * Access key is required, define `DO_KEY_ID` and `DO_SECRET_KEY` environment variables.\n */\nexport interface SpacesOptions extends BaseS3Options {\n  /**\n   * The provider. Must be `spaces`.\n   */\n  readonly provider: \"spaces\"\n\n  /**\n   * The space name.\n   */\n  readonly name: string\n\n  /**\n   * The region (e.g. `nyc3`).\n   */\n  readonly region: string\n}\n\nexport function getS3LikeProviderBaseUrl(configuration: PublishConfiguration) {\n  const provider = configuration.provider\n  if (provider === \"s3\") {\n    return s3Url(configuration as S3Options)\n  }\n  if (provider === \"spaces\") {\n    return spacesUrl(configuration as SpacesOptions)\n  }\n  throw new Error(`Not supported provider: ${provider}`)\n}\n\nfunction s3Url(options: S3Options) {\n  let url: string\n  if (options.accelerate == true) {\n    url = `https://${options.bucket}.s3-accelerate.amazonaws.com`\n  } else if (options.endpoint != null) {\n    url = `${options.endpoint}/${options.bucket}`\n  } else if (options.bucket.includes(\".\")) {\n    if (options.region == null) {\n      throw new Error(`Bucket name \"${options.bucket}\" includes a dot, but S3 region is missing`)\n    }\n\n    // special case, see http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html#access-bucket-intro\n    if (options.region === \"us-east-1\") {\n      url = `https://s3.amazonaws.com/${options.bucket}`\n    } else {\n      url = `https://s3-${options.region}.amazonaws.com/${options.bucket}`\n    }\n  } else if (options.region === \"cn-north-1\") {\n    url = `https://${options.bucket}.s3.${options.region}.amazonaws.com.cn`\n  } else {\n    url = `https://${options.bucket}.s3.amazonaws.com`\n  }\n  return appendPath(url, options.path)\n}\n\nfunction appendPath(url: string, p: string | Nullish): string {\n  if (p != null && p.length > 0) {\n    if (!p.startsWith(\"/\")) {\n      url += \"/\"\n    }\n    url += p\n  }\n  return url\n}\n\nfunction spacesUrl(options: SpacesOptions) {\n  if (options.name == null) {\n    throw new Error(`name is missing`)\n  }\n  if (options.region == null) {\n    throw new Error(`region is missing`)\n  }\n  return appendPath(`https://${options.name}.${options.region}.digitaloceanspaces.com`, options.path)\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.retry = retry;
const CancellationToken_1 = require("./CancellationToken");
async function retry(task, retryCount, interval, backoff = 0, attempt = 0, shouldRetry) {
    var _a;
    const cancellationToken = new CancellationToken_1.CancellationToken();
    try {
        return await task();
    }
    catch (error) {
        if (((_a = shouldRetry === null || shouldRetry === void 0 ? void 0 : shouldRetry(error)) !== null && _a !== void 0 ? _a : true) && retryCount > 0 && !cancellationToken.cancelled) {
            await new Promise(resolve => setTimeout(resolve, interval + backoff * attempt));
            return await retry(task, retryCount - 1, interval, backoff, attempt + 1, shouldRetry);
        }
        else {
            throw error;
        }
    }
}
//# sourceMappingURL=retry.js.map{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":";;AAEA,sBAYC;AAdD,2DAAuD;AAEhD,KAAK,UAAU,KAAK,CAAI,IAAsB,EAAE,UAAkB,EAAE,QAAgB,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,WAAiC;;IACtJ,MAAM,iBAAiB,GAAG,IAAI,qCAAiB,EAAE,CAAA;IACjD,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,EAAE,CAAA;IACrB,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,IAAI,CAAC,MAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAG,KAAK,CAAC,mCAAI,IAAI,CAAC,IAAI,UAAU,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC;YACrF,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC,CAAC,CAAA;YAC/E,OAAO,MAAM,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,EAAE,WAAW,CAAC,CAAA;QACvF,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { CancellationToken } from \"./CancellationToken\"\n\nexport async function retry<T>(task: () => Promise<T>, retryCount: number, interval: number, backoff = 0, attempt = 0, shouldRetry?: (e: any) => boolean): Promise<T> {\n  const cancellationToken = new CancellationToken()\n  try {\n    return await task()\n  } catch (error: any) {\n    if ((shouldRetry?.(error) ?? true) && retryCount > 0 && !cancellationToken.cancelled) {\n      await new Promise(resolve => setTimeout(resolve, interval + backoff * attempt))\n      return await retry(task, retryCount - 1, interval, backoff, attempt + 1, shouldRetry)\n    } else {\n      throw error\n    }\n  }\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseDn = parseDn;
function parseDn(seq) {
    let quoted = false;
    let key = null;
    let token = "";
    let nextNonSpace = 0;
    seq = seq.trim();
    const result = new Map();
    for (let i = 0; i <= seq.length; i++) {
        if (i === seq.length) {
            if (key !== null) {
                result.set(key, token);
            }
            break;
        }
        const ch = seq[i];
        if (quoted) {
            if (ch === '"') {
                quoted = false;
                continue;
            }
        }
        else {
            if (ch === '"') {
                quoted = true;
                continue;
            }
            if (ch === "\\") {
                i++;
                const ord = parseInt(seq.slice(i, i + 2), 16);
                if (Number.isNaN(ord)) {
                    token += seq[i];
                }
                else {
                    i++;
                    token += String.fromCharCode(ord);
                }
                continue;
            }
            if (key === null && ch === "=") {
                key = token;
                token = "";
                continue;
            }
            if (ch === "," || ch === ";" || ch === "+") {
                if (key !== null) {
                    result.set(key, token);
                }
                key = null;
                token = "";
                continue;
            }
        }
        if (ch === " " && !quoted) {
            if (token.length === 0) {
                continue;
            }
            if (i > nextNonSpace) {
                let j = i;
                while (seq[j] === " ") {
                    j++;
                }
                nextNonSpace = j;
            }
            if (nextNonSpace >= seq.length ||
                seq[nextNonSpace] === "," ||
                seq[nextNonSpace] === ";" ||
                (key === null && seq[nextNonSpace] === "=") ||
                (key !== null && seq[nextNonSpace] === "+")) {
                i = nextNonSpace - 1;
                continue;
            }
        }
        token += ch;
    }
    return result;
}
//# sourceMappingURL=rfc2253Parser.js.map{"version":3,"file":"rfc2253Parser.js","sourceRoot":"","sources":["../src/rfc2253Parser.ts"],"names":[],"mappings":"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","sourcesContent":["export function parseDn(seq: string): Map<string, string> {\n  let quoted = false\n  let key: string | null = null\n  let token = \"\"\n  let nextNonSpace = 0\n\n  seq = seq.trim()\n  const result = new Map<string, string>()\n  for (let i = 0; i <= seq.length; i++) {\n    if (i === seq.length) {\n      if (key !== null) {\n        result.set(key, token)\n      }\n      break\n    }\n\n    const ch = seq[i]\n    if (quoted) {\n      if (ch === '\"') {\n        quoted = false\n        continue\n      }\n    } else {\n      if (ch === '\"') {\n        quoted = true\n        continue\n      }\n\n      if (ch === \"\\\\\") {\n        i++\n        const ord = parseInt(seq.slice(i, i + 2), 16)\n        if (Number.isNaN(ord)) {\n          token += seq[i]\n        } else {\n          i++\n          token += String.fromCharCode(ord)\n        }\n        continue\n      }\n\n      if (key === null && ch === \"=\") {\n        key = token\n        token = \"\"\n        continue\n      }\n\n      if (ch === \",\" || ch === \";\" || ch === \"+\") {\n        if (key !== null) {\n          result.set(key, token)\n        }\n        key = null\n        token = \"\"\n        continue\n      }\n    }\n\n    if (ch === \" \" && !quoted) {\n      if (token.length === 0) {\n        continue\n      }\n\n      if (i > nextNonSpace) {\n        let j = i\n        while (seq[j] === \" \") {\n          j++\n        }\n        nextNonSpace = j\n      }\n\n      if (\n        nextNonSpace >= seq.length ||\n        seq[nextNonSpace] === \",\" ||\n        seq[nextNonSpace] === \";\" ||\n        (key === null && seq[nextNonSpace] === \"=\") ||\n        (key !== null && seq[nextNonSpace] === \"+\")\n      ) {\n        i = nextNonSpace - 1\n        continue\n      }\n    }\n\n    token += ch\n  }\n\n  return result\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=updateInfo.js.map{"version":3,"file":"updateInfo.js","sourceRoot":"","sources":["../src/updateInfo.ts"],"names":[],"mappings":"","sourcesContent":["export interface ReleaseNoteInfo {\n  /**\n   * The version.\n   */\n  readonly version: string\n\n  /**\n   * The note.\n   */\n  readonly note: string | null\n}\n\nexport interface BlockMapDataHolder {\n  /**\n   * The file size. Used to verify downloaded size (save one HTTP request to get length).\n   * Also used when block map data is embedded into the file (appimage, windows web installer package).\n   */\n  size?: number\n\n  /**\n   * The block map file size. Used when block map data is embedded into the file (appimage, windows web installer package).\n   * This information can be obtained from the file itself, but it requires additional HTTP request,\n   * so, to reduce request count, block map size is specified in the update metadata too.\n   */\n  blockMapSize?: number\n\n  /**\n   * The file checksum.\n   */\n  readonly sha512: string\n\n  readonly isAdminRightsRequired?: boolean\n}\n\nexport interface PackageFileInfo extends BlockMapDataHolder {\n  readonly path: string\n}\n\nexport interface UpdateFileInfo extends BlockMapDataHolder {\n  url: string\n}\n\nexport interface UpdateInfo {\n  /**\n   * The version.\n   */\n  readonly version: string\n\n  readonly files: Array<UpdateFileInfo>\n\n  /** @deprecated */\n  readonly path: string\n\n  /** @deprecated */\n  readonly sha512: string\n\n  /**\n   * The release name.\n   */\n  releaseName?: string | null\n\n  /**\n   * The release notes. List if `updater.fullChangelog` is set to `true`, `string` otherwise.\n   */\n  releaseNotes?: string | Array<ReleaseNoteInfo> | null\n\n  /**\n   * The release date.\n   */\n  releaseDate: string\n\n  /**\n   * The [staged rollout](./auto-update.md#staged-rollouts) percentage, 0-100.\n   */\n  readonly stagingPercentage?: number\n\n  /**\n   * The minimum version of system required for the app to run. Sample value: macOS `23.1.0`, Windows `10.0.22631`.\n   * Same with os.release() value, this is a kernel version.\n   */\n  readonly minimumSystemVersion?: string\n}\n\nexport interface WindowsUpdateInfo extends UpdateInfo {\n  packages?: { [arch: string]: PackageFileInfo } | null\n\n  /**\n   * @deprecated\n   * @private\n   */\n  sha2?: string\n}\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.nil = exports.UUID = void 0;
const crypto_1 = require("crypto");
const error_1 = require("./error");
const invalidName = "options.name must be either a string or a Buffer";
// Node ID according to rfc4122#section-4.5
const randomHost = (0, crypto_1.randomBytes)(16);
randomHost[0] = randomHost[0] | 0x01;
// lookup table hex to byte
const hex2byte = {};
// lookup table byte to hex
const byte2hex = [];
// populate lookup tables
for (let i = 0; i < 256; i++) {
    const hex = (i + 0x100).toString(16).substr(1);
    hex2byte[hex] = i;
    byte2hex[i] = hex;
}
// UUID class
class UUID {
    constructor(uuid) {
        this.ascii = null;
        this.binary = null;
        const check = UUID.check(uuid);
        if (!check) {
            throw new Error("not a UUID");
        }
        this.version = check.version;
        if (check.format === "ascii") {
            this.ascii = uuid;
        }
        else {
            this.binary = uuid;
        }
    }
    static v5(name, namespace) {
        return uuidNamed(name, "sha1", 0x50, namespace);
    }
    toString() {
        if (this.ascii == null) {
            this.ascii = stringify(this.binary);
        }
        return this.ascii;
    }
    inspect() {
        return `UUID v${this.version} ${this.toString()}`;
    }
    static check(uuid, offset = 0) {
        if (typeof uuid === "string") {
            uuid = uuid.toLowerCase();
            if (!/^[a-f0-9]{8}(-[a-f0-9]{4}){3}-([a-f0-9]{12})$/.test(uuid)) {
                return false;
            }
            if (uuid === "00000000-0000-0000-0000-000000000000") {
                return { version: undefined, variant: "nil", format: "ascii" };
            }
            return {
                version: (hex2byte[uuid[14] + uuid[15]] & 0xf0) >> 4,
                variant: getVariant((hex2byte[uuid[19] + uuid[20]] & 0xe0) >> 5),
                format: "ascii",
            };
        }
        if (Buffer.isBuffer(uuid)) {
            if (uuid.length < offset + 16) {
                return false;
            }
            let i = 0;
            for (; i < 16; i++) {
                if (uuid[offset + i] !== 0) {
                    break;
                }
            }
            if (i === 16) {
                return { version: undefined, variant: "nil", format: "binary" };
            }
            return {
                version: (uuid[offset + 6] & 0xf0) >> 4,
                variant: getVariant((uuid[offset + 8] & 0xe0) >> 5),
                format: "binary",
            };
        }
        throw (0, error_1.newError)("Unknown type of uuid", "ERR_UNKNOWN_UUID_TYPE");
    }
    // read stringified uuid into a Buffer
    static parse(input) {
        const buffer = Buffer.allocUnsafe(16);
        let j = 0;
        for (let i = 0; i < 16; i++) {
            buffer[i] = hex2byte[input[j++] + input[j++]];
            if (i === 3 || i === 5 || i === 7 || i === 9) {
                j += 1;
            }
        }
        return buffer;
    }
}
exports.UUID = UUID;
// from rfc4122#appendix-C
UUID.OID = UUID.parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8");
// according to rfc4122#section-4.1.1
function getVariant(bits) {
    switch (bits) {
        case 0:
        case 1:
        case 3:
            return "ncs";
        case 4:
        case 5:
            return "rfc4122";
        case 6:
            return "microsoft";
        default:
            return "future";
    }
}
var UuidEncoding;
(function (UuidEncoding) {
    UuidEncoding[UuidEncoding["ASCII"] = 0] = "ASCII";
    UuidEncoding[UuidEncoding["BINARY"] = 1] = "BINARY";
    UuidEncoding[UuidEncoding["OBJECT"] = 2] = "OBJECT";
})(UuidEncoding || (UuidEncoding = {}));
// v3 + v5
function uuidNamed(name, hashMethod, version, namespace, encoding = UuidEncoding.ASCII) {
    const hash = (0, crypto_1.createHash)(hashMethod);
    const nameIsNotAString = typeof name !== "string";
    if (nameIsNotAString && !Buffer.isBuffer(name)) {
        throw (0, error_1.newError)(invalidName, "ERR_INVALID_UUID_NAME");
    }
    hash.update(namespace);
    hash.update(name);
    const buffer = hash.digest();
    let result;
    switch (encoding) {
        case UuidEncoding.BINARY:
            buffer[6] = (buffer[6] & 0x0f) | version;
            buffer[8] = (buffer[8] & 0x3f) | 0x80;
            result = buffer;
            break;
        case UuidEncoding.OBJECT:
            buffer[6] = (buffer[6] & 0x0f) | version;
            buffer[8] = (buffer[8] & 0x3f) | 0x80;
            result = new UUID(buffer);
            break;
        default:
            result =
                byte2hex[buffer[0]] +
                    byte2hex[buffer[1]] +
                    byte2hex[buffer[2]] +
                    byte2hex[buffer[3]] +
                    "-" +
                    byte2hex[buffer[4]] +
                    byte2hex[buffer[5]] +
                    "-" +
                    byte2hex[(buffer[6] & 0x0f) | version] +
                    byte2hex[buffer[7]] +
                    "-" +
                    byte2hex[(buffer[8] & 0x3f) | 0x80] +
                    byte2hex[buffer[9]] +
                    "-" +
                    byte2hex[buffer[10]] +
                    byte2hex[buffer[11]] +
                    byte2hex[buffer[12]] +
                    byte2hex[buffer[13]] +
                    byte2hex[buffer[14]] +
                    byte2hex[buffer[15]];
            break;
    }
    return result;
}
function stringify(buffer) {
    return (byte2hex[buffer[0]] +
        byte2hex[buffer[1]] +
        byte2hex[buffer[2]] +
        byte2hex[buffer[3]] +
        "-" +
        byte2hex[buffer[4]] +
        byte2hex[buffer[5]] +
        "-" +
        byte2hex[buffer[6]] +
        byte2hex[buffer[7]] +
        "-" +
        byte2hex[buffer[8]] +
        byte2hex[buffer[9]] +
        "-" +
        byte2hex[buffer[10]] +
        byte2hex[buffer[11]] +
        byte2hex[buffer[12]] +
        byte2hex[buffer[13]] +
        byte2hex[buffer[14]] +
        byte2hex[buffer[15]]);
}
// according to rfc4122#section-4.1.7
exports.nil = new UUID("00000000-0000-0000-0000-000000000000");
// UUID.v4 = uuidRandom
// UUID.v4fast = uuidRandomFast
// UUID.v3 = function(options, callback) {
//     return uuidNamed("md5", 0x30, options, callback)
// }
//# sourceMappingURL=uuid.js.map{"version":3,"file":"uuid.js","sourceRoot":"","sources":["../src/uuid.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes } from \"crypto\"\nimport { newError } from \"./error\"\n\nconst invalidName = \"options.name must be either a string or a Buffer\"\n\n// Node ID according to rfc4122#section-4.5\nconst randomHost = randomBytes(16)\nrandomHost[0] = randomHost[0] | 0x01\n\n// lookup table hex to byte\nconst hex2byte: any = {}\n\n// lookup table byte to hex\nconst byte2hex: Array<string> = []\n// populate lookup tables\nfor (let i = 0; i < 256; i++) {\n  const hex = (i + 0x100).toString(16).substr(1)\n  hex2byte[hex] = i\n  byte2hex[i] = hex\n}\n\n// UUID class\nexport class UUID {\n  private ascii: string | null = null\n  private readonly binary: Buffer | null = null\n  private readonly version: number\n\n  // from rfc4122#appendix-C\n  static readonly OID: Buffer = UUID.parse(\"6ba7b812-9dad-11d1-80b4-00c04fd430c8\")\n\n  constructor(uuid: Buffer | string) {\n    const check = UUID.check(uuid)\n    if (!check) {\n      throw new Error(\"not a UUID\")\n    }\n\n    this.version = check.version!\n\n    if (check.format === \"ascii\") {\n      this.ascii = uuid as string\n    } else {\n      this.binary = uuid as Buffer\n    }\n  }\n\n  static v5(name: string | Buffer, namespace: Buffer) {\n    return uuidNamed(name, \"sha1\", 0x50, namespace)\n  }\n\n  toString() {\n    if (this.ascii == null) {\n      this.ascii = stringify(this.binary!)\n    }\n    return this.ascii\n  }\n\n  inspect() {\n    return `UUID v${this.version} ${this.toString()}`\n  }\n\n  static check(uuid: Buffer | string, offset = 0) {\n    if (typeof uuid === \"string\") {\n      uuid = uuid.toLowerCase()\n\n      if (!/^[a-f0-9]{8}(-[a-f0-9]{4}){3}-([a-f0-9]{12})$/.test(uuid)) {\n        return false\n      }\n\n      if (uuid === \"00000000-0000-0000-0000-000000000000\") {\n        return { version: undefined, variant: \"nil\", format: \"ascii\" }\n      }\n\n      return {\n        version: (hex2byte[uuid[14] + uuid[15]] & 0xf0) >> 4,\n        variant: getVariant((hex2byte[uuid[19] + uuid[20]] & 0xe0) >> 5),\n        format: \"ascii\",\n      }\n    }\n\n    if (Buffer.isBuffer(uuid)) {\n      if (uuid.length < offset + 16) {\n        return false\n      }\n\n      let i = 0\n      for (; i < 16; i++) {\n        if (uuid[offset + i] !== 0) {\n          break\n        }\n      }\n      if (i === 16) {\n        return { version: undefined, variant: \"nil\", format: \"binary\" }\n      }\n\n      return {\n        version: (uuid[offset + 6] & 0xf0) >> 4,\n        variant: getVariant((uuid[offset + 8] & 0xe0) >> 5),\n        format: \"binary\",\n      }\n    }\n\n    throw newError(\"Unknown type of uuid\", \"ERR_UNKNOWN_UUID_TYPE\")\n  }\n\n  // read stringified uuid into a Buffer\n  static parse(input: string): Buffer {\n    const buffer = Buffer.allocUnsafe(16)\n    let j = 0\n    for (let i = 0; i < 16; i++) {\n      buffer[i] = hex2byte[input[j++] + input[j++]]\n      if (i === 3 || i === 5 || i === 7 || i === 9) {\n        j += 1\n      }\n    }\n    return buffer\n  }\n}\n\n// according to rfc4122#section-4.1.1\nfunction getVariant(bits: number) {\n  switch (bits) {\n    case 0:\n    case 1:\n    case 3:\n      return \"ncs\"\n    case 4:\n    case 5:\n      return \"rfc4122\"\n    case 6:\n      return \"microsoft\"\n    default:\n      return \"future\"\n  }\n}\n\nenum UuidEncoding {\n  ASCII,\n  BINARY,\n  OBJECT,\n}\n\n// v3 + v5\nfunction uuidNamed(name: string | Buffer, hashMethod: string, version: number, namespace: Buffer, encoding: UuidEncoding = UuidEncoding.ASCII) {\n  const hash = createHash(hashMethod)\n\n  const nameIsNotAString = typeof name !== \"string\"\n  if (nameIsNotAString && !Buffer.isBuffer(name)) {\n    throw newError(invalidName, \"ERR_INVALID_UUID_NAME\")\n  }\n\n  hash.update(namespace)\n  hash.update(name)\n\n  const buffer = hash.digest()\n  let result: any\n  switch (encoding) {\n    case UuidEncoding.BINARY:\n      buffer[6] = (buffer[6] & 0x0f) | version\n      buffer[8] = (buffer[8] & 0x3f) | 0x80\n      result = buffer\n      break\n    case UuidEncoding.OBJECT:\n      buffer[6] = (buffer[6] & 0x0f) | version\n      buffer[8] = (buffer[8] & 0x3f) | 0x80\n      result = new UUID(buffer)\n      break\n    default:\n      result =\n        byte2hex[buffer[0]] +\n        byte2hex[buffer[1]] +\n        byte2hex[buffer[2]] +\n        byte2hex[buffer[3]] +\n        \"-\" +\n        byte2hex[buffer[4]] +\n        byte2hex[buffer[5]] +\n        \"-\" +\n        byte2hex[(buffer[6] & 0x0f) | version] +\n        byte2hex[buffer[7]] +\n        \"-\" +\n        byte2hex[(buffer[8] & 0x3f) | 0x80] +\n        byte2hex[buffer[9]] +\n        \"-\" +\n        byte2hex[buffer[10]] +\n        byte2hex[buffer[11]] +\n        byte2hex[buffer[12]] +\n        byte2hex[buffer[13]] +\n        byte2hex[buffer[14]] +\n        byte2hex[buffer[15]]\n      break\n  }\n  return result\n}\n\nfunction stringify(buffer: Buffer) {\n  return (\n    byte2hex[buffer[0]] +\n    byte2hex[buffer[1]] +\n    byte2hex[buffer[2]] +\n    byte2hex[buffer[3]] +\n    \"-\" +\n    byte2hex[buffer[4]] +\n    byte2hex[buffer[5]] +\n    \"-\" +\n    byte2hex[buffer[6]] +\n    byte2hex[buffer[7]] +\n    \"-\" +\n    byte2hex[buffer[8]] +\n    byte2hex[buffer[9]] +\n    \"-\" +\n    byte2hex[buffer[10]] +\n    byte2hex[buffer[11]] +\n    byte2hex[buffer[12]] +\n    byte2hex[buffer[13]] +\n    byte2hex[buffer[14]] +\n    byte2hex[buffer[15]]\n  )\n}\n\n// according to rfc4122#section-4.1.7\nexport const nil = new UUID(\"00000000-0000-0000-0000-000000000000\")\n\n// UUID.v4 = uuidRandom\n\n// UUID.v4fast = uuidRandomFast\n\n// UUID.v3 = function(options, callback) {\n//     return uuidNamed(\"md5\", 0x30, options, callback)\n// }\n"]}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XElement = void 0;
exports.parseXml = parseXml;
const sax = require("sax");
const error_1 = require("./error");
class XElement {
    constructor(name) {
        this.name = name;
        this.value = "";
        this.attributes = null;
        this.isCData = false;
        this.elements = null;
        if (!name) {
            throw (0, error_1.newError)("Element name cannot be empty", "ERR_XML_ELEMENT_NAME_EMPTY");
        }
        if (!isValidName(name)) {
            throw (0, error_1.newError)(`Invalid element name: ${name}`, "ERR_XML_ELEMENT_INVALID_NAME");
        }
    }
    attribute(name) {
        const result = this.attributes === null ? null : this.attributes[name];
        if (result == null) {
            throw (0, error_1.newError)(`No attribute "${name}"`, "ERR_XML_MISSED_ATTRIBUTE");
        }
        return result;
    }
    removeAttribute(name) {
        if (this.attributes !== null) {
            delete this.attributes[name];
        }
    }
    element(name, ignoreCase = false, errorIfMissed = null) {
        const result = this.elementOrNull(name, ignoreCase);
        if (result === null) {
            throw (0, error_1.newError)(errorIfMissed || `No element "${name}"`, "ERR_XML_MISSED_ELEMENT");
        }
        return result;
    }
    elementOrNull(name, ignoreCase = false) {
        if (this.elements === null) {
            return null;
        }
        for (const element of this.elements) {
            if (isNameEquals(element, name, ignoreCase)) {
                return element;
            }
        }
        return null;
    }
    getElements(name, ignoreCase = false) {
        if (this.elements === null) {
            return [];
        }
        return this.elements.filter(it => isNameEquals(it, name, ignoreCase));
    }
    elementValueOrEmpty(name, ignoreCase = false) {
        const element = this.elementOrNull(name, ignoreCase);
        return element === null ? "" : element.value;
    }
}
exports.XElement = XElement;
const NAME_REG_EXP = new RegExp(/^[A-Za-z_][:A-Za-z0-9_-]*$/i);
function isValidName(name) {
    return NAME_REG_EXP.test(name);
}
function isNameEquals(element, name, ignoreCase) {
    const elementName = element.name;
    return elementName === name || (ignoreCase === true && elementName.length === name.length && elementName.toLowerCase() === name.toLowerCase());
}
function parseXml(data) {
    let rootElement = null;
    const parser = sax.parser(true, {});
    const elements = [];
    parser.onopentag = saxElement => {
        const element = new XElement(saxElement.name);
        element.attributes = saxElement.attributes;
        if (rootElement === null) {
            rootElement = element;
        }
        else {
            const parent = elements[elements.length - 1];
            if (parent.elements == null) {
                parent.elements = [];
            }
            parent.elements.push(element);
        }
        elements.push(element);
    };
    parser.onclosetag = () => {
        elements.pop();
    };
    parser.ontext = text => {
        if (elements.length > 0) {
            elements[elements.length - 1].value = text;
        }
    };
    parser.oncdata = cdata => {
        const element = elements[elements.length - 1];
        element.value = cdata;
        element.isCData = true;
    };
    parser.onerror = err => {
        throw err;
    };
    parser.write(data);
    return rootElement;
}
//# sourceMappingURL=xml.js.map{"version":3,"file":"xml.js","sourceRoot":"","sources":["../src/xml.ts"],"names":[],"mappings":"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","sourcesContent":["import * as sax from \"sax\"\nimport { newError } from \"./error\"\n\nexport class XElement {\n  value = \"\"\n  attributes: Record<string, string> | null = null\n  isCData = false\n  elements: Array<XElement> | null = null\n\n  constructor(readonly name: string) {\n    if (!name) {\n      throw newError(\"Element name cannot be empty\", \"ERR_XML_ELEMENT_NAME_EMPTY\")\n    }\n    if (!isValidName(name)) {\n      throw newError(`Invalid element name: ${name}`, \"ERR_XML_ELEMENT_INVALID_NAME\")\n    }\n  }\n\n  attribute(name: string): string {\n    const result = this.attributes === null ? null : this.attributes[name]\n    if (result == null) {\n      throw newError(`No attribute \"${name}\"`, \"ERR_XML_MISSED_ATTRIBUTE\")\n    }\n    return result\n  }\n\n  removeAttribute(name: string): void {\n    if (this.attributes !== null) {\n      delete this.attributes[name]\n    }\n  }\n\n  element(name: string, ignoreCase = false, errorIfMissed: string | null = null): XElement {\n    const result = this.elementOrNull(name, ignoreCase)\n    if (result === null) {\n      throw newError(errorIfMissed || `No element \"${name}\"`, \"ERR_XML_MISSED_ELEMENT\")\n    }\n    return result\n  }\n\n  elementOrNull(name: string, ignoreCase = false): XElement | null {\n    if (this.elements === null) {\n      return null\n    }\n\n    for (const element of this.elements) {\n      if (isNameEquals(element, name, ignoreCase)) {\n        return element\n      }\n    }\n\n    return null\n  }\n\n  getElements(name: string, ignoreCase = false) {\n    if (this.elements === null) {\n      return []\n    }\n    return this.elements.filter(it => isNameEquals(it, name, ignoreCase))\n  }\n\n  elementValueOrEmpty(name: string, ignoreCase = false): string {\n    const element = this.elementOrNull(name, ignoreCase)\n    return element === null ? \"\" : element.value\n  }\n}\n\nconst NAME_REG_EXP = new RegExp(/^[A-Za-z_][:A-Za-z0-9_-]*$/i)\n\nfunction isValidName(name: string) {\n  return NAME_REG_EXP.test(name)\n}\n\nfunction isNameEquals(element: XElement, name: string, ignoreCase: boolean) {\n  const elementName = element.name\n  return elementName === name || (ignoreCase === true && elementName.length === name.length && elementName.toLowerCase() === name.toLowerCase())\n}\n\nexport function parseXml(data: string): XElement {\n  let rootElement: XElement | null = null\n  const parser = sax.parser(true, {})\n  const elements: Array<XElement> = []\n\n  parser.onopentag = saxElement => {\n    const element = new XElement(saxElement.name)\n    element.attributes = saxElement.attributes as Record<string, string>\n\n    if (rootElement === null) {\n      rootElement = element\n    } else {\n      const parent = elements[elements.length - 1]\n      if (parent.elements == null) {\n        parent.elements = []\n      }\n      parent.elements.push(element)\n    }\n    elements.push(element)\n  }\n\n  parser.onclosetag = () => {\n    elements.pop()\n  }\n\n  parser.ontext = text => {\n    if (elements.length > 0) {\n      elements[elements.length - 1].value = text\n    }\n  }\n\n  parser.oncdata = cdata => {\n    const element = elements[elements.length - 1]\n    element.value = cdata\n    element.isCData = true\n  }\n\n  parser.onerror = err => {\n    throw err\n  }\n\n  parser.write(data)\n  return rootElement!\n}\n"]}{
  "name": "builder-util-runtime",
  "version": "9.3.1",
  "main": "out/index.js",
  "author": "Vladimir Krivosheev",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/electron-userland/electron-builder.git",
    "directory": "packages/builder-util-runtime"
  },
  "homepage": "https://github.com/electron-userland/electron-builder",
  "files": [
    "out"
  ],
  "engines": {
    "node": ">=12.0.0"
  },
  "dependencies": {
    "debug": "^4.3.4",
    "sax": "^1.2.4"
  },
  "devDependencies": {
    "@types/debug": "4.1.7",
    "@types/sax": "1.2.3"
  },
  "types": "./out/index.d.ts"
}(The MIT License)

Copyright (c) 2011-2017 JP Richardson

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
 merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict'

const fs = require('graceful-fs')
const path = require('path')
const mkdirsSync = require('../mkdirs').mkdirsSync
const utimesMillisSync = require('../util/utimes').utimesMillisSync
const stat = require('../util/stat')

function copySync (src, dest, opts) {
  if (typeof opts === 'function') {
    opts = { filter: opts }
  }

  opts = opts || {}
  opts.clobber = 'clobber' in opts ? !!opts.clobber : true // default to true for now
  opts.overwrite = 'overwrite' in opts ? !!opts.overwrite : opts.clobber // overwrite falls back to clobber

  // Warn about using preserveTimestamps on 32-bit node
  if (opts.preserveTimestamps && process.arch === 'ia32') {
    process.emitWarning(
      'Using the preserveTimestamps option in 32-bit node is not recommended;\n\n' +
      '\tsee https://github.com/jprichardson/node-fs-extra/issues/269',
      'Warning', 'fs-extra-WARN0002'
    )
  }

  const { srcStat, destStat } = stat.checkPathsSync(src, dest, 'copy', opts)
  stat.checkParentPathsSync(src, srcStat, dest, 'copy')
  return handleFilterAndCopy(destStat, src, dest, opts)
}

function handleFilterAndCopy (destStat, src, dest, opts) {
  if (opts.filter && !opts.filter(src, dest)) return
  const destParent = path.dirname(dest)
  if (!fs.existsSync(destParent)) mkdirsSync(destParent)
  return getStats(destStat, src, dest, opts)
}

function startCopy (destStat, src, dest, opts) {
  if (opts.filter && !opts.filter(src, dest)) return
  return getStats(destStat, src, dest, opts)
}

function getStats (destStat, src, dest, opts) {
  const statSync = opts.dereference ? fs.statSync : fs.lstatSync
  const srcStat = statSync(src)

  if (srcStat.isDirectory()) return onDir(srcStat, destStat, src, dest, opts)
  else if (srcStat.isFile() ||
           srcStat.isCharacterDevice() ||
           srcStat.isBlockDevice()) return onFile(srcStat, destStat, src, dest, opts)
  else if (srcStat.isSymbolicLink()) return onLink(destStat, src, dest, opts)
  else if (srcStat.isSocket()) throw new Error(`Cannot copy a socket file: ${src}`)
  else if (srcStat.isFIFO()) throw new Error(`Cannot copy a FIFO pipe: ${src}`)
  throw new Error(`Unknown file: ${src}`)
}

function onFile (srcStat, destStat, src, dest, opts) {
  if (!destStat) return copyFile(srcStat, src, dest, opts)
  return mayCopyFile(srcStat, src, dest, opts)
}

function mayCopyFile (srcStat, src, dest, opts) {
  if (opts.overwrite) {
    fs.unlinkSync(dest)
    return copyFile(srcStat, src, dest, opts)
  } else if (opts.errorOnExist) {
    throw new Error(`'${dest}' already exists`)
  }
}

function copyFile (srcStat, src, dest, opts) {
  fs.copyFileSync(src, dest)
  if (opts.preserveTimestamps) handleTimestamps(srcStat.mode, src, dest)
  return setDestMode(dest, srcStat.mode)
}

function handleTimestamps (srcMode, src, dest) {
  // Make sure the file is writable before setting the timestamp
  // otherwise open fails with EPERM when invoked with 'r+'
  // (through utimes call)
  if (fileIsNotWritable(srcMode)) makeFileWritable(dest, srcMode)
  return setDestTimestamps(src, dest)
}

function fileIsNotWritable (srcMode) {
  return (srcMode & 0o200) === 0
}

function makeFileWritable (dest, srcMode) {
  return setDestMode(dest, srcMode | 0o200)
}

function setDestMode (dest, srcMode) {
  return fs.chmodSync(dest, srcMode)
}

function setDestTimestamps (src, dest) {
  // The initial srcStat.atime cannot be trusted
  // because it is modified by the read(2) system call
  // (See https://nodejs.org/api/fs.html#fs_stat_time_values)
  const updatedSrcStat = fs.statSync(src)
  return utimesMillisSync(dest, updatedSrcStat.atime, updatedSrcStat.mtime)
}

function onDir (srcStat, destStat, src, dest, opts) {
  if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts)
  return copyDir(src, dest, opts)
}

function mkDirAndCopy (srcMode, src, dest, opts) {
  fs.mkdirSync(dest)
  copyDir(src, dest, opts)
  return setDestMode(dest, srcMode)
}

function copyDir (src, dest, opts) {
  fs.readdirSync(src).forEach(item => copyDirItem(item, src, dest, opts))
}

function copyDirItem (item, src, dest, opts) {
  const srcItem = path.join(src, item)
  const destItem = path.join(dest, item)
  const { destStat } = stat.checkPathsSync(srcItem, destItem, 'copy', opts)
  return startCopy(destStat, srcItem, destItem, opts)
}

function onLink (destStat, src, dest, opts) {
  let resolvedSrc = fs.readlinkSync(src)
  if (opts.dereference) {
    resolvedSrc = path.resolve(process.cwd(), resolvedSrc)
  }

  if (!destStat) {
    return fs.symlinkSync(resolvedSrc, dest)
  } else {
    let resolvedDest
    try {
      resolvedDest = fs.readlinkSync(dest)
    } catch (err) {
      // dest exists and is a regular file or directory,
      // Windows may throw UNKNOWN error. If dest already exists,
      // fs throws error anyway, so no need to guard against it here.
      if (err.code === 'EINVAL' || err.code === 'UNKNOWN') return fs.symlinkSync(resolvedSrc, dest)
      throw err
    }
    if (opts.dereference) {
      resolvedDest = path.resolve(process.cwd(), resolvedDest)
    }
    if (stat.isSrcSubdir(resolvedSrc, resolvedDest)) {
      throw new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`)
    }

    // prevent copy if src is a subdir of dest since unlinking
    // dest in this case would result in removing src contents
    // and therefore a broken symlink would be created.
    if (fs.statSync(dest).isDirectory() && stat.isSrcSubdir(resolvedDest, resolvedSrc)) {
      throw new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`)
    }
    return copyLink(resolvedSrc, dest)
  }
}

function copyLink (resolvedSrc, dest) {
  fs.unlinkSync(dest)
  return fs.symlinkSync(resolvedSrc, dest)
}

module.exports = copySync
'use strict'

const fs = require('graceful-fs')
const path = require('path')
const mkdirs = require('../mkdirs').mkdirs
const pathExists = require('../path-exists').pathExists
const utimesMillis = require('../util/utimes').utimesMillis
const stat = require('../util/stat')

function copy (src, dest, opts, cb) {
  if (typeof opts === 'function' && !cb) {
    cb = opts
    opts = {}
  } else if (typeof opts === 'function') {
    opts = { filter: opts }
  }

  cb = cb || function () {}
  opts = opts || {}

  opts.clobber = 'clobber' in opts ? !!opts.clobber : true // default to true for now
  opts.overwrite = 'overwrite' in opts ? !!opts.overwrite : opts.clobber // overwrite falls back to clobber

  // Warn about using preserveTimestamps on 32-bit node
  if (opts.preserveTimestamps && process.arch === 'ia32') {
    process.emitWarning(
      'Using the preserveTimestamps option in 32-bit node is not recommended;\n\n' +
      '\tsee https://github.com/jprichardson/node-fs-extra/issues/269',
      'Warning', 'fs-extra-WARN0001'
    )
  }

  stat.checkPaths(src, dest, 'copy', opts, (err, stats) => {
    if (err) return cb(err)
    const { srcStat, destStat } = stats
    stat.checkParentPaths(src, srcStat, dest, 'copy', err => {
      if (err) return cb(err)
      if (opts.filter) return handleFilter(checkParentDir, destStat, src, dest, opts, cb)
      return checkParentDir(destStat, src, dest, opts, cb)
    })
  })
}

function checkParentDir (destStat, src, dest, opts, cb) {
  const destParent = path.dirname(dest)
  pathExists(destParent, (err, dirExists) => {
    if (err) return cb(err)
    if (dirExists) return getStats(destStat, src, dest, opts, cb)
    mkdirs(destParent, err => {
      if (err) return cb(err)
      return getStats(destStat, src, dest, opts, cb)
    })
  })
}

function handleFilter (onInclude, destStat, src, dest, opts, cb) {
  Promise.resolve(opts.filter(src, dest)).then(include => {
    if (include) return onInclude(destStat, src, dest, opts, cb)
    return cb()
  }, error => cb(error))
}

function startCopy (destStat, src, dest, opts, cb) {
  if (opts.filter) return handleFilter(getStats, destStat, src, dest, opts, cb)
  return getStats(destStat, src, dest, opts, cb)
}

function getStats (destStat, src, dest, opts, cb) {
  const stat = opts.dereference ? fs.stat : fs.lstat
  stat(src, (err, srcStat) => {
    if (err) return cb(err)

    if (srcStat.isDirectory()) return onDir(srcStat, destStat, src, dest, opts, cb)
    else if (srcStat.isFile() ||
             srcStat.isCharacterDevice() ||
             srcStat.isBlockDevice()) return onFile(srcStat, destStat, src, dest, opts, cb)
    else if (srcStat.isSymbolicLink()) return onLink(destStat, src, dest, opts, cb)
    else if (srcStat.isSocket()) return cb(new Error(`Cannot copy a socket file: ${src}`))
    else if (srcStat.isFIFO()) return cb(new Error(`Cannot copy a FIFO pipe: ${src}`))
    return cb(new Error(`Unknown file: ${src}`))
  })
}

function onFile (srcStat, destStat, src, dest, opts, cb) {
  if (!destStat) return copyFile(srcStat, src, dest, opts, cb)
  return mayCopyFile(srcStat, src, dest, opts, cb)
}

function mayCopyFile (srcStat, src, dest, opts, cb) {
  if (opts.overwrite) {
    fs.unlink(dest, err => {
      if (err) return cb(err)
      return copyFile(srcStat, src, dest, opts, cb)
    })
  } else if (opts.errorOnExist) {
    return cb(new Error(`'${dest}' already exists`))
  } else return cb()
}

function copyFile (srcStat, src, dest, opts, cb) {
  fs.copyFile(src, dest, err => {
    if (err) return cb(err)
    if (opts.preserveTimestamps) return handleTimestampsAndMode(srcStat.mode, src, dest, cb)
    return setDestMode(dest, srcStat.mode, cb)
  })
}

function handleTimestampsAndMode (srcMode, src, dest, cb) {
  // Make sure the file is writable before setting the timestamp
  // otherwise open fails with EPERM when invoked with 'r+'
  // (through utimes call)
  if (fileIsNotWritable(srcMode)) {
    return makeFileWritable(dest, srcMode, err => {
      if (err) return cb(err)
      return setDestTimestampsAndMode(srcMode, src, dest, cb)
    })
  }
  return setDestTimestampsAndMode(srcMode, src, dest, cb)
}

function fileIsNotWritable (srcMode) {
  return (srcMode & 0o200) === 0
}

function makeFileWritable (dest, srcMode, cb) {
  return setDestMode(dest, srcMode | 0o200, cb)
}

function setDestTimestampsAndMode (srcMode, src, dest, cb) {
  setDestTimestamps(src, dest, err => {
    if (err) return cb(err)
    return setDestMode(dest, srcMode, cb)
  })
}

function setDestMode (dest, srcMode, cb) {
  return fs.chmod(dest, srcMode, cb)
}

function setDestTimestamps (src, dest, cb) {
  // The initial srcStat.atime cannot be trusted
  // because it is modified by the read(2) system call
  // (See https://nodejs.org/api/fs.html#fs_stat_time_values)
  fs.stat(src, (err, updatedSrcStat) => {
    if (err) return cb(err)
    return utimesMillis(dest, updatedSrcStat.atime, updatedSrcStat.mtime, cb)
  })
}

function onDir (srcStat, destStat, src, dest, opts, cb) {
  if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts, cb)
  return copyDir(src, dest, opts, cb)
}

function mkDirAndCopy (srcMode, src, dest, opts, cb) {
  fs.mkdir(dest, err => {
    if (err) return cb(err)
    copyDir(src, dest, opts, err => {
      if (err) return cb(err)
      return setDestMode(dest, srcMode, cb)
    })
  })
}

function copyDir (src, dest, opts, cb) {
  fs.readdir(src, (err, items) => {
    if (err) return cb(err)
    return copyDirItems(items, src, dest, opts, cb)
  })
}

function copyDirItems (items, src, dest, opts, cb) {
  const item = items.pop()
  if (!item) return cb()
  return copyDirItem(items, item, src, dest, opts, cb)
}

function copyDirItem (items, item, src, dest, opts, cb) {
  const srcItem = path.join(src, item)
  const destItem = path.join(dest, item)
  stat.checkPaths(srcItem, destItem, 'copy', opts, (err, stats) => {
    if (err) return cb(err)
    const { destStat } = stats
    startCopy(destStat, srcItem, destItem, opts, err => {
      if (err) return cb(err)
      return copyDirItems(items, src, dest, opts, cb)
    })
  })
}

function onLink (destStat, src, dest, opts, cb) {
  fs.readlink(src, (err, resolvedSrc) => {
    if (err) return cb(err)
    if (opts.dereference) {
      resolvedSrc = path.resolve(process.cwd(), resolvedSrc)
    }

    if (!destStat) {
      return fs.symlink(resolvedSrc, dest, cb)
    } else {
      fs.readlink(dest, (err, resolvedDest) => {
        if (err) {
          // dest exists and is a regular file or directory,
          // Windows may throw UNKNOWN error. If dest already exists,
          // fs throws error anyway, so no need to guard against it here.
          if (err.code === 'EINVAL' || err.code === 'UNKNOWN') return fs.symlink(resolvedSrc, dest, cb)
          return cb(err)
        }
        if (opts.dereference) {
          resolvedDest = path.resolve(process.cwd(), resolvedDest)
        }
        if (stat.isSrcSubdir(resolvedSrc, resolvedDest)) {
          return cb(new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`))
        }

        // do not copy if src is a subdir of dest since unlinking
        // dest in this case would result in removing src contents
        // and therefore a broken symlink would be created.
        if (destStat.isDirectory() && stat.isSrcSubdir(resolvedDest, resolvedSrc)) {
          return cb(new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`))
        }
        return copyLink(resolvedSrc, dest, cb)
      })
    }
  })
}

function copyLink (resolvedSrc, dest, cb) {
  fs.unlink(dest, err => {
    if (err) return cb(err)
    return fs.symlink(resolvedSrc, dest, cb)
  })
}

module.exports = copy
'use strict'

const u = require('universalify').fromCallback
module.exports = {
  copy: u(require('./copy')),
  copySync: require('./copy-sync')
}
'use strict'

const u = require('universalify').fromPromise
const fs = require('../fs')
const path = require('path')
const mkdir = require('../mkdirs')
const remove = require('../remove')

const emptyDir = u(async function emptyDir (dir) {
  let items
  try {
    items = await fs.readdir(dir)
  } catch {
    return mkdir.mkdirs(dir)
  }

  return Promise.all(items.map(item => remove.remove(path.join(dir, item))))
})

function emptyDirSync (dir) {
  let items
  try {
    items = fs.readdirSync(dir)
  } catch {
    return mkdir.mkdirsSync(dir)
  }

  items.forEach(item => {
    item = path.join(dir, item)
    remove.removeSync(item)
  })
}

module.exports = {
  emptyDirSync,
  emptydirSync: emptyDirSync,
  emptyDir,
  emptydir: emptyDir
}
'use strict'

const u = require('universalify').fromCallback
const path = require('path')
const fs = require('graceful-fs')
const mkdir = require('../mkdirs')

function createFile (file, callback) {
  function makeFile () {
    fs.writeFile(file, '', err => {
      if (err) return callback(err)
      callback()
    })
  }

  fs.stat(file, (err, stats) => { // eslint-disable-line handle-callback-err
    if (!err && stats.isFile()) return callback()
    const dir = path.dirname(file)
    fs.stat(dir, (err, stats) => {
      if (err) {
        // if the directory doesn't exist, make it
        if (err.code === 'ENOENT') {
          return mkdir.mkdirs(dir, err => {
            if (err) return callback(err)
            makeFile()
          })
        }
        return callback(err)
      }

      if (stats.isDirectory()) makeFile()
      else {
        // parent is not a directory
        // This is just to cause an internal ENOTDIR error to be thrown
        fs.readdir(dir, err => {
          if (err) return callback(err)
        })
      }
    })
  })
}

function createFileSync (file) {
  let stats
  try {
    stats = fs.statSync(file)
  } catch {}
  if (stats && stats.isFile()) return

  const dir = path.dirname(file)
  try {
    if (!fs.statSync(dir).isDirectory()) {
      // parent is not a directory
      // This is just to cause an internal ENOTDIR error to be thrown
      fs.readdirSync(dir)
    }
  } catch (err) {
    // If the stat call above failed because the directory doesn't exist, create it
    if (err && err.code === 'ENOENT') mkdir.mkdirsSync(dir)
    else throw err
  }

  fs.writeFileSync(file, '')
}

module.exports = {
  createFile: u(createFile),
  createFileSync
}
'use strict'

const { createFile, createFileSync } = require('./file')
const { createLink, createLinkSync } = require('./link')
const { createSymlink, createSymlinkSync } = require('./symlink')

module.exports = {
  // file
  createFile,
  createFileSync,
  ensureFile: createFile,
  ensureFileSync: createFileSync,
  // link
  createLink,
  createLinkSync,
  ensureLink: createLink,
  ensureLinkSync: createLinkSync,
  // symlink
  createSymlink,
  createSymlinkSync,
  ensureSymlink: createSymlink,
  ensureSymlinkSync: createSymlinkSync
}
'use strict'

const u = require('universalify').fromCallback
const path = require('path')
const fs = require('graceful-fs')
const mkdir = require('../mkdirs')
const pathExists = require('../path-exists').pathExists
const { areIdentical } = require('../util/stat')

function createLink (srcpath, dstpath, callback) {
  function makeLink (srcpath, dstpath) {
    fs.link(srcpath, dstpath, err => {
      if (err) return callback(err)
      callback(null)
    })
  }

  fs.lstat(dstpath, (_, dstStat) => {
    fs.lstat(srcpath, (err, srcStat) => {
      if (err) {
        err.message = err.message.replace('lstat', 'ensureLink')
        return callback(err)
      }
      if (dstStat && areIdentical(srcStat, dstStat)) return callback(null)

      const dir = path.dirname(dstpath)
      pathExists(dir, (err, dirExists) => {
        if (err) return callback(err)
        if (dirExists) return makeLink(srcpath, dstpath)
        mkdir.mkdirs(dir, err => {
          if (err) return callback(err)
          makeLink(srcpath, dstpath)
        })
      })
    })
  })
}

function createLinkSync (srcpath, dstpath) {
  let dstStat
  try {
    dstStat = fs.lstatSync(dstpath)
  } catch {}

  try {
    const srcStat = fs.lstatSync(srcpath)
    if (dstStat && areIdentical(srcStat, dstStat)) return
  } catch (err) {
    err.message = err.message.replace('lstat', 'ensureLink')
    throw err
  }

  const dir = path.dirname(dstpath)
  const dirExists = fs.existsSync(dir)
  if (dirExists) return fs.linkSync(srcpath, dstpath)
  mkdir.mkdirsSync(dir)

  return fs.linkSync(srcpath, dstpath)
}

module.exports = {
  createLink: u(createLink),
  createLinkSync
}
'use strict'

const path = require('path')
const fs = require('graceful-fs')
const pathExists = require('../path-exists').pathExists

/**
 * Function that returns two types of paths, one relative to symlink, and one
 * relative to the current working directory. Checks if path is absolute or
 * relative. If the path is relative, this function checks if the path is
 * relative to symlink or relative to current working directory. This is an
 * initiative to find a smarter `srcpath` to supply when building symlinks.
 * This allows you to determine which path to use out of one of three possible
 * types of source paths. The first is an absolute path. This is detected by
 * `path.isAbsolute()`. When an absolute path is provided, it is checked to
 * see if it exists. If it does it's used, if not an error is returned
 * (callback)/ thrown (sync). The other two options for `srcpath` are a
 * relative url. By default Node's `fs.symlink` works by creating a symlink
 * using `dstpath` and expects the `srcpath` to be relative to the newly
 * created symlink. If you provide a `srcpath` that does not exist on the file
 * system it results in a broken symlink. To minimize this, the function
 * checks to see if the 'relative to symlink' source file exists, and if it
 * does it will use it. If it does not, it checks if there's a file that
 * exists that is relative to the current working directory, if does its used.
 * This preserves the expectations of the original fs.symlink spec and adds
 * the ability to pass in `relative to current working direcotry` paths.
 */

function symlinkPaths (srcpath, dstpath, callback) {
  if (path.isAbsolute(srcpath)) {
    return fs.lstat(srcpath, (err) => {
      if (err) {
        err.message = err.message.replace('lstat', 'ensureSymlink')
        return callback(err)
      }
      return callback(null, {
        toCwd: srcpath,
        toDst: srcpath
      })
    })
  } else {
    const dstdir = path.dirname(dstpath)
    const relativeToDst = path.join(dstdir, srcpath)
    return pathExists(relativeToDst, (err, exists) => {
      if (err) return callback(err)
      if (exists) {
        return callback(null, {
          toCwd: relativeToDst,
          toDst: srcpath
        })
      } else {
        return fs.lstat(srcpath, (err) => {
          if (err) {
            err.message = err.message.replace('lstat', 'ensureSymlink')
            return callback(err)
          }
          return callback(null, {
            toCwd: srcpath,
            toDst: path.relative(dstdir, srcpath)
          })
        })
      }
    })
  }
}

function symlinkPathsSync (srcpath, dstpath) {
  let exists
  if (path.isAbsolute(srcpath)) {
    exists = fs.existsSync(srcpath)
    if (!exists) throw new Error('absolute srcpath does not exist')
    return {
      toCwd: srcpath,
      toDst: srcpath
    }
  } else {
    const dstdir = path.dirname(dstpath)
    const relativeToDst = path.join(dstdir, srcpath)
    exists = fs.existsSync(relativeToDst)
    if (exists) {
      return {
        toCwd: relativeToDst,
        toDst: srcpath
      }
    } else {
      exists = fs.existsSync(srcpath)
      if (!exists) throw new Error('relative srcpath does not exist')
      return {
        toCwd: srcpath,
        toDst: path.relative(dstdir, srcpath)
      }
    }
  }
}

module.exports = {
  symlinkPaths,
  symlinkPathsSync
}
'use strict'

const fs = require('graceful-fs')

function symlinkType (srcpath, type, callback) {
  callback = (typeof type === 'function') ? type : callback
  type = (typeof type === 'function') ? false : type
  if (type) return callback(null, type)
  fs.lstat(srcpath, (err, stats) => {
    if (err) return callback(null, 'file')
    type = (stats && stats.isDirectory()) ? 'dir' : 'file'
    callback(null, type)
  })
}

function symlinkTypeSync (srcpath, type) {
  let stats

  if (type) return type
  try {
    stats = fs.lstatSync(srcpath)
  } catch {
    return 'file'
  }
  return (stats && stats.isDirectory()) ? 'dir' : 'file'
}

module.exports = {
  symlinkType,
  symlinkTypeSync
}
'use strict'

const u = require('universalify').fromCallback
const path = require('path')
const fs = require('../fs')
const _mkdirs = require('../mkdirs')
const mkdirs = _mkdirs.mkdirs
const mkdirsSync = _mkdirs.mkdirsSync

const _symlinkPaths = require('./symlink-paths')
const symlinkPaths = _symlinkPaths.symlinkPaths
const symlinkPathsSync = _symlinkPaths.symlinkPathsSync

const _symlinkType = require('./symlink-type')
const symlinkType = _symlinkType.symlinkType
const symlinkTypeSync = _symlinkType.symlinkTypeSync

const pathExists = require('../path-exists').pathExists

const { areIdentical } = require('../util/stat')

function createSymlink (srcpath, dstpath, type, callback) {
  callback = (typeof type === 'function') ? type : callback
  type = (typeof type === 'function') ? false : type

  fs.lstat(dstpath, (err, stats) => {
    if (!err && stats.isSymbolicLink()) {
      Promise.all([
        fs.stat(srcpath),
        fs.stat(dstpath)
      ]).then(([srcStat, dstStat]) => {
        if (areIdentical(srcStat, dstStat)) return callback(null)
        _createSymlink(srcpath, dstpath, type, callback)
      })
    } else _createSymlink(srcpath, dstpath, type, callback)
  })
}

function _createSymlink (srcpath, dstpath, type, callback) {
  symlinkPaths(srcpath, dstpath, (err, relative) => {
    if (err) return callback(err)
    srcpath = relative.toDst
    symlinkType(relative.toCwd, type, (err, type) => {
      if (err) return callback(err)
      const dir = path.dirname(dstpath)
      pathExists(dir, (err, dirExists) => {
        if (err) return callback(err)
        if (dirExists) return fs.symlink(srcpath, dstpath, type, callback)
        mkdirs(dir, err => {
          if (err) return callback(err)
          fs.symlink(srcpath, dstpath, type, callback)
        })
      })
    })
  })
}

function createSymlinkSync (srcpath, dstpath, type) {
  let stats
  try {
    stats = fs.lstatSync(dstpath)
  } catch {}
  if (stats && stats.isSymbolicLink()) {
    const srcStat = fs.statSync(srcpath)
    const dstStat = fs.statSync(dstpath)
    if (areIdentical(srcStat, dstStat)) return
  }

  const relative = symlinkPathsSync(srcpath, dstpath)
  srcpath = relative.toDst
  type = symlinkTypeSync(relative.toCwd, type)
  const dir = path.dirname(dstpath)
  const exists = fs.existsSync(dir)
  if (exists) return fs.symlinkSync(srcpath, dstpath, type)
  mkdirsSync(dir)
  return fs.symlinkSync(srcpath, dstpath, type)
}

module.exports = {
  createSymlink: u(createSymlink),
  createSymlinkSync
}
'use strict'
// This is adapted from https://github.com/normalize/mz
// Copyright (c) 2014-2016 Jonathan Ong me@jongleberry.com and Contributors
const u = require('universalify').fromCallback
const fs = require('graceful-fs')

const api = [
  'access',
  'appendFile',
  'chmod',
  'chown',
  'close',
  'copyFile',
  'fchmod',
  'fchown',
  'fdatasync',
  'fstat',
  'fsync',
  'ftruncate',
  'futimes',
  'lchmod',
  'lchown',
  'link',
  'lstat',
  'mkdir',
  'mkdtemp',
  'open',
  'opendir',
  'readdir',
  'readFile',
  'readlink',
  'realpath',
  'rename',
  'rm',
  'rmdir',
  'stat',
  'symlink',
  'truncate',
  'unlink',
  'utimes',
  'writeFile'
].filter(key => {
  // Some commands are not available on some systems. Ex:
  // fs.opendir was added in Node.js v12.12.0
  // fs.rm was added in Node.js v14.14.0
  // fs.lchown is not available on at least some Linux
  return typeof fs[key] === 'function'
})

// Export cloned fs:
Object.assign(exports, fs)

// Universalify async methods:
api.forEach(method => {
  exports[method] = u(fs[method])
})

// We differ from mz/fs in that we still ship the old, broken, fs.exists()
// since we are a drop-in replacement for the native module
exports.exists = function (filename, callback) {
  if (typeof callback === 'function') {
    return fs.exists(filename, callback)
  }
  return new Promise(resolve => {
    return fs.exists(filename, resolve)
  })
}

// fs.read(), fs.write(), & fs.writev() need special treatment due to multiple callback args

exports.read = function (fd, buffer, offset, length, position, callback) {
  if (typeof callback === 'function') {
    return fs.read(fd, buffer, offset, length, position, callback)
  }
  return new Promise((resolve, reject) => {
    fs.read(fd, buffer, offset, length, position, (err, bytesRead, buffer) => {
      if (err) return reject(err)
      resolve({ bytesRead, buffer })
    })
  })
}

// Function signature can be
// fs.write(fd, buffer[, offset[, length[, position]]], callback)
// OR
// fs.write(fd, string[, position[, encoding]], callback)
// We need to handle both cases, so we use ...args
exports.write = function (fd, buffer, ...args) {
  if (typeof args[args.length - 1] === 'function') {
    return fs.write(fd, buffer, ...args)
  }

  return new Promise((resolve, reject) => {
    fs.write(fd, buffer, ...args, (err, bytesWritten, buffer) => {
      if (err) return reject(err)
      resolve({ bytesWritten, buffer })
    })
  })
}

// fs.writev only available in Node v12.9.0+
if (typeof fs.writev === 'function') {
  // Function signature is
  // s.writev(fd, buffers[, position], callback)
  // We need to handle the optional arg, so we use ...args
  exports.writev = function (fd, buffers, ...args) {
    if (typeof args[args.length - 1] === 'function') {
      return fs.writev(fd, buffers, ...args)
    }

    return new Promise((resolve, reject) => {
      fs.writev(fd, buffers, ...args, (err, bytesWritten, buffers) => {
        if (err) return reject(err)
        resolve({ bytesWritten, buffers })
      })
    })
  }
}

// fs.realpath.native sometimes not available if fs is monkey-patched
if (typeof fs.realpath.native === 'function') {
  exports.realpath.native = u(fs.realpath.native)
} else {
  process.emitWarning(
    'fs.realpath.native is not a function. Is fs being monkey-patched?',
    'Warning', 'fs-extra-WARN0003'
  )
}
'use strict'

module.exports = {
  // Export promiseified graceful-fs:
  ...require('./fs'),
  // Export extra methods:
  ...require('./copy'),
  ...require('./empty'),
  ...require('./ensure'),
  ...require('./json'),
  ...require('./mkdirs'),
  ...require('./move'),
  ...require('./output-file'),
  ...require('./path-exists'),
  ...require('./remove')
}
'use strict'

const u = require('universalify').fromPromise
const jsonFile = require('./jsonfile')

jsonFile.outputJson = u(require('./output-json'))
jsonFile.outputJsonSync = require('./output-json-sync')
// aliases
jsonFile.outputJSON = jsonFile.outputJson
jsonFile.outputJSONSync = jsonFile.outputJsonSync
jsonFile.writeJSON = jsonFile.writeJson
jsonFile.writeJSONSync = jsonFile.writeJsonSync
jsonFile.readJSON = jsonFile.readJson
jsonFile.readJSONSync = jsonFile.readJsonSync

module.exports = jsonFile
'use strict'

const jsonFile = require('jsonfile')

module.exports = {
  // jsonfile exports
  readJson: jsonFile.readFile,
  readJsonSync: jsonFile.readFileSync,
  writeJson: jsonFile.writeFile,
  writeJsonSync: jsonFile.writeFileSync
}
'use strict'

const { stringify } = require('jsonfile/utils')
const { outputFileSync } = require('../output-file')

function outputJsonSync (file, data, options) {
  const str = stringify(data, options)

  outputFileSync(file, str, options)
}

module.exports = outputJsonSync
'use strict'

const { stringify } = require('jsonfile/utils')
const { outputFile } = require('../output-file')

async function outputJson (file, data, options = {}) {
  const str = stringify(data, options)

  await outputFile(file, str, options)
}

module.exports = outputJson
'use strict'
const u = require('universalify').fromPromise
const { makeDir: _makeDir, makeDirSync } = require('./make-dir')
const makeDir = u(_makeDir)

module.exports = {
  mkdirs: makeDir,
  mkdirsSync: makeDirSync,
  // alias
  mkdirp: makeDir,
  mkdirpSync: makeDirSync,
  ensureDir: makeDir,
  ensureDirSync: makeDirSync
}
'use strict'
const fs = require('../fs')
const { checkPath } = require('./utils')

const getMode = options => {
  const defaults = { mode: 0o777 }
  if (typeof options === 'number') return options
  return ({ ...defaults, ...options }).mode
}

module.exports.makeDir = async (dir, options) => {
  checkPath(dir)

  return fs.mkdir(dir, {
    mode: getMode(options),
    recursive: true
  })
}

module.exports.makeDirSync = (dir, options) => {
  checkPath(dir)

  return fs.mkdirSync(dir, {
    mode: getMode(options),
    recursive: true
  })
}
// Adapted from https://github.com/sindresorhus/make-dir
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict'
const path = require('path')

// https://github.com/nodejs/node/issues/8987
// https://github.com/libuv/libuv/pull/1088
module.exports.checkPath = function checkPath (pth) {
  if (process.platform === 'win32') {
    const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path.parse(pth).root, ''))

    if (pathHasInvalidWinCharacters) {
      const error = new Error(`Path contains invalid characters: ${pth}`)
      error.code = 'EINVAL'
      throw error
    }
  }
}
'use strict'

const u = require('universalify').fromCallback
module.exports = {
  move: u(require('./move')),
  moveSync: require('./move-sync')
}
'use strict'

const fs = require('graceful-fs')
const path = require('path')
const copySync = require('../copy').copySync
const removeSync = require('../remove').removeSync
const mkdirpSync = require('../mkdirs').mkdirpSync
const stat = require('../util/stat')

function moveSync (src, dest, opts) {
  opts = opts || {}
  const overwrite = opts.overwrite || opts.clobber || false

  const { srcStat, isChangingCase = false } = stat.checkPathsSync(src, dest, 'move', opts)
  stat.checkParentPathsSync(src, srcStat, dest, 'move')
  if (!isParentRoot(dest)) mkdirpSync(path.dirname(dest))
  return doRename(src, dest, overwrite, isChangingCase)
}

function isParentRoot (dest) {
  const parent = path.dirname(dest)
  const parsedPath = path.parse(parent)
  return parsedPath.root === parent
}

function doRename (src, dest, overwrite, isChangingCase) {
  if (isChangingCase) return rename(src, dest, overwrite)
  if (overwrite) {
    removeSync(dest)
    return rename(src, dest, overwrite)
  }
  if (fs.existsSync(dest)) throw new Error('dest already exists.')
  return rename(src, dest, overwrite)
}

function rename (src, dest, overwrite) {
  try {
    fs.renameSync(src, dest)
  } catch (err) {
    if (err.code !== 'EXDEV') throw err
    return moveAcrossDevice(src, dest, overwrite)
  }
}

function moveAcrossDevice (src, dest, overwrite) {
  const opts = {
    overwrite,
    errorOnExist: true
  }
  copySync(src, dest, opts)
  return removeSync(src)
}

module.exports = moveSync
'use strict'

const fs = require('graceful-fs')
const path = require('path')
const copy = require('../copy').copy
const remove = require('../remove').remove
const mkdirp = require('../mkdirs').mkdirp
const pathExists = require('../path-exists').pathExists
const stat = require('../util/stat')

function move (src, dest, opts, cb) {
  if (typeof opts === 'function') {
    cb = opts
    opts = {}
  }

  opts = opts || {}

  const overwrite = opts.overwrite || opts.clobber || false

  stat.checkPaths(src, dest, 'move', opts, (err, stats) => {
    if (err) return cb(err)
    const { srcStat, isChangingCase = false } = stats
    stat.checkParentPaths(src, srcStat, dest, 'move', err => {
      if (err) return cb(err)
      if (isParentRoot(dest)) return doRename(src, dest, overwrite, isChangingCase, cb)
      mkdirp(path.dirname(dest), err => {
        if (err) return cb(err)
        return doRename(src, dest, overwrite, isChangingCase, cb)
      })
    })
  })
}

function isParentRoot (dest) {
  const parent = path.dirname(dest)
  const parsedPath = path.parse(parent)
  return parsedPath.root === parent
}

function doRename (src, dest, overwrite, isChangingCase, cb) {
  if (isChangingCase) return rename(src, dest, overwrite, cb)
  if (overwrite) {
    return remove(dest, err => {
      if (err) return cb(err)
      return rename(src, dest, overwrite, cb)
    })
  }
  pathExists(dest, (err, destExists) => {
    if (err) return cb(err)
    if (destExists) return cb(new Error('dest already exists.'))
    return rename(src, dest, overwrite, cb)
  })
}

function rename (src, dest, overwrite, cb) {
  fs.rename(src, dest, err => {
    if (!err) return cb()
    if (err.code !== 'EXDEV') return cb(err)
    return moveAcrossDevice(src, dest, overwrite, cb)
  })
}

function moveAcrossDevice (src, dest, overwrite, cb) {
  const opts = {
    overwrite,
    errorOnExist: true
  }
  copy(src, dest, opts, err => {
    if (err) return cb(err)
    return remove(src, cb)
  })
}

module.exports = move
'use strict'

const u = require('universalify').fromCallback
const fs = require('graceful-fs')
const path = require('path')
const mkdir = require('../mkdirs')
const pathExists = require('../path-exists').pathExists

function outputFile (file, data, encoding, callback) {
  if (typeof encoding === 'function') {
    callback = encoding
    encoding = 'utf8'
  }

  const dir = path.dirname(file)
  pathExists(dir, (err, itDoes) => {
    if (err) return callback(err)
    if (itDoes) return fs.writeFile(file, data, encoding, callback)

    mkdir.mkdirs(dir, err => {
      if (err) return callback(err)

      fs.writeFile(file, data, encoding, callback)
    })
  })
}

function outputFileSync (file, ...args) {
  const dir = path.dirname(file)
  if (fs.existsSync(dir)) {
    return fs.writeFileSync(file, ...args)
  }
  mkdir.mkdirsSync(dir)
  fs.writeFileSync(file, ...args)
}

module.exports = {
  outputFile: u(outputFile),
  outputFileSync
}
'use strict'
const u = require('universalify').fromPromise
const fs = require('../fs')

function pathExists (path) {
  return fs.access(path).then(() => true).catch(() => false)
}

module.exports = {
  pathExists: u(pathExists),
  pathExistsSync: fs.existsSync
}
'use strict'

const fs = require('graceful-fs')
const u = require('universalify').fromCallback
const rimraf = require('./rimraf')

function remove (path, callback) {
  // Node 14.14.0+
  if (fs.rm) return fs.rm(path, { recursive: true, force: true }, callback)
  rimraf(path, callback)
}

function removeSync (path) {
  // Node 14.14.0+
  if (fs.rmSync) return fs.rmSync(path, { recursive: true, force: true })
  rimraf.sync(path)
}

module.exports = {
  remove: u(remove),
  removeSync
}
'use strict'

const fs = require('graceful-fs')
const path = require('path')
const assert = require('assert')

const isWindows = (process.platform === 'win32')

function defaults (options) {
  const methods = [
    'unlink',
    'chmod',
    'stat',
    'lstat',
    'rmdir',
    'readdir'
  ]
  methods.forEach(m => {
    options[m] = options[m] || fs[m]
    m = m + 'Sync'
    options[m] = options[m] || fs[m]
  })

  options.maxBusyTries = options.maxBusyTries || 3
}

function rimraf (p, options, cb) {
  let busyTries = 0

  if (typeof options === 'function') {
    cb = options
    options = {}
  }

  assert(p, 'rimraf: missing path')
  assert.strictEqual(typeof p, 'string', 'rimraf: path should be a string')
  assert.strictEqual(typeof cb, 'function', 'rimraf: callback function required')
  assert(options, 'rimraf: invalid options argument provided')
  assert.strictEqual(typeof options, 'object', 'rimraf: options should be object')

  defaults(options)

  rimraf_(p, options, function CB (er) {
    if (er) {
      if ((er.code === 'EBUSY' || er.code === 'ENOTEMPTY' || er.code === 'EPERM') &&
          busyTries < options.maxBusyTries) {
        busyTries++
        const time = busyTries * 100
        // try again, with the same exact callback as this one.
        return setTimeout(() => rimraf_(p, options, CB), time)
      }

      // already gone
      if (er.code === 'ENOENT') er = null
    }

    cb(er)
  })
}

// Two possible strategies.
// 1. Assume it's a file.  unlink it, then do the dir stuff on EPERM or EISDIR
// 2. Assume it's a directory.  readdir, then do the file stuff on ENOTDIR
//
// Both result in an extra syscall when you guess wrong.  However, there
// are likely far more normal files in the world than directories.  This
// is based on the assumption that a the average number of files per
// directory is >= 1.
//
// If anyone ever complains about this, then I guess the strategy could
// be made configurable somehow.  But until then, YAGNI.
function rimraf_ (p, options, cb) {
  assert(p)
  assert(options)
  assert(typeof cb === 'function')

  // sunos lets the root user unlink directories, which is... weird.
  // so we have to lstat here and make sure it's not a dir.
  options.lstat(p, (er, st) => {
    if (er && er.code === 'ENOENT') {
      return cb(null)
    }

    // Windows can EPERM on stat.  Life is suffering.
    if (er && er.code === 'EPERM' && isWindows) {
      return fixWinEPERM(p, options, er, cb)
    }

    if (st && st.isDirectory()) {
      return rmdir(p, options, er, cb)
    }

    options.unlink(p, er => {
      if (er) {
        if (er.code === 'ENOENT') {
          return cb(null)
        }
        if (er.code === 'EPERM') {
          return (isWindows)
            ? fixWinEPERM(p, options, er, cb)
            : rmdir(p, options, er, cb)
        }
        if (er.code === 'EISDIR') {
          return rmdir(p, options, er, cb)
        }
      }
      return cb(er)
    })
  })
}

function fixWinEPERM (p, options, er, cb) {
  assert(p)
  assert(options)
  assert(typeof cb === 'function')

  options.chmod(p, 0o666, er2 => {
    if (er2) {
      cb(er2.code === 'ENOENT' ? null : er)
    } else {
      options.stat(p, (er3, stats) => {
        if (er3) {
          cb(er3.code === 'ENOENT' ? null : er)
        } else if (stats.isDirectory()) {
          rmdir(p, options, er, cb)
        } else {
          options.unlink(p, cb)
        }
      })
    }
  })
}

function fixWinEPERMSync (p, options, er) {
  let stats

  assert(p)
  assert(options)

  try {
    options.chmodSync(p, 0o666)
  } catch (er2) {
    if (er2.code === 'ENOENT') {
      return
    } else {
      throw er
    }
  }

  try {
    stats = options.statSync(p)
  } catch (er3) {
    if (er3.code === 'ENOENT') {
      return
    } else {
      throw er
    }
  }

  if (stats.isDirectory()) {
    rmdirSync(p, options, er)
  } else {
    options.unlinkSync(p)
  }
}

function rmdir (p, options, originalEr, cb) {
  assert(p)
  assert(options)
  assert(typeof cb === 'function')

  // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS)
  // if we guessed wrong, and it's not a directory, then
  // raise the original error.
  options.rmdir(p, er => {
    if (er && (er.code === 'ENOTEMPTY' || er.code === 'EEXIST' || er.code === 'EPERM')) {
      rmkids(p, options, cb)
    } else if (er && er.code === 'ENOTDIR') {
      cb(originalEr)
    } else {
      cb(er)
    }
  })
}

function rmkids (p, options, cb) {
  assert(p)
  assert(options)
  assert(typeof cb === 'function')

  options.readdir(p, (er, files) => {
    if (er) return cb(er)

    let n = files.length
    let errState

    if (n === 0) return options.rmdir(p, cb)

    files.forEach(f => {
      rimraf(path.join(p, f), options, er => {
        if (errState) {
          return
        }
        if (er) return cb(errState = er)
        if (--n === 0) {
          options.rmdir(p, cb)
        }
      })
    })
  })
}

// this looks simpler, and is strictly *faster*, but will
// tie up the JavaScript thread and fail on excessively
// deep directory trees.
function rimrafSync (p, options) {
  let st

  options = options || {}
  defaults(options)

  assert(p, 'rimraf: missing path')
  assert.strictEqual(typeof p, 'string', 'rimraf: path should be a string')
  assert(options, 'rimraf: missing options')
  assert.strictEqual(typeof options, 'object', 'rimraf: options should be object')

  try {
    st = options.lstatSync(p)
  } catch (er) {
    if (er.code === 'ENOENT') {
      return
    }

    // Windows can EPERM on stat.  Life is suffering.
    if (er.code === 'EPERM' && isWindows) {
      fixWinEPERMSync(p, options, er)
    }
  }

  try {
    // sunos lets the root user unlink directories, which is... weird.
    if (st && st.isDirectory()) {
      rmdirSync(p, options, null)
    } else {
      options.unlinkSync(p)
    }
  } catch (er) {
    if (er.code === 'ENOENT') {
      return
    } else if (er.code === 'EPERM') {
      return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er)
    } else if (er.code !== 'EISDIR') {
      throw er
    }
    rmdirSync(p, options, er)
  }
}

function rmdirSync (p, options, originalEr) {
  assert(p)
  assert(options)

  try {
    options.rmdirSync(p)
  } catch (er) {
    if (er.code === 'ENOTDIR') {
      throw originalEr
    } else if (er.code === 'ENOTEMPTY' || er.code === 'EEXIST' || er.code === 'EPERM') {
      rmkidsSync(p, options)
    } else if (er.code !== 'ENOENT') {
      throw er
    }
  }
}

function rmkidsSync (p, options) {
  assert(p)
  assert(options)
  options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), options))

  if (isWindows) {
    // We only end up here once we got ENOTEMPTY at least once, and
    // at this point, we are guaranteed to have removed all the kids.
    // So, we know that it won't be ENOENT or ENOTDIR or anything else.
    // try really hard to delete stuff on windows, because it has a
    // PROFOUNDLY annoying habit of not closing handles promptly when
    // files are deleted, resulting in spurious ENOTEMPTY errors.
    const startTime = Date.now()
    do {
      try {
        const ret = options.rmdirSync(p, options)
        return ret
      } catch {}
    } while (Date.now() - startTime < 500) // give up after 500ms
  } else {
    const ret = options.rmdirSync(p, options)
    return ret
  }
}

module.exports = rimraf
rimraf.sync = rimrafSync
'use strict'

const fs = require('../fs')
const path = require('path')
const util = require('util')

function getStats (src, dest, opts) {
  const statFunc = opts.dereference
    ? (file) => fs.stat(file, { bigint: true })
    : (file) => fs.lstat(file, { bigint: true })
  return Promise.all([
    statFunc(src),
    statFunc(dest).catch(err => {
      if (err.code === 'ENOENT') return null
      throw err
    })
  ]).then(([srcStat, destStat]) => ({ srcStat, destStat }))
}

function getStatsSync (src, dest, opts) {
  let destStat
  const statFunc = opts.dereference
    ? (file) => fs.statSync(file, { bigint: true })
    : (file) => fs.lstatSync(file, { bigint: true })
  const srcStat = statFunc(src)
  try {
    destStat = statFunc(dest)
  } catch (err) {
    if (err.code === 'ENOENT') return { srcStat, destStat: null }
    throw err
  }
  return { srcStat, destStat }
}

function checkPaths (src, dest, funcName, opts, cb) {
  util.callbackify(getStats)(src, dest, opts, (err, stats) => {
    if (err) return cb(err)
    const { srcStat, destStat } = stats

    if (destStat) {
      if (areIdentical(srcStat, destStat)) {
        const srcBaseName = path.basename(src)
        const destBaseName = path.basename(dest)
        if (funcName === 'move' &&
          srcBaseName !== destBaseName &&
          srcBaseName.toLowerCase() === destBaseName.toLowerCase()) {
          return cb(null, { srcStat, destStat, isChangingCase: true })
        }
        return cb(new Error('Source and destination must not be the same.'))
      }
      if (srcStat.isDirectory() && !destStat.isDirectory()) {
        return cb(new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`))
      }
      if (!srcStat.isDirectory() && destStat.isDirectory()) {
        return cb(new Error(`Cannot overwrite directory '${dest}' with non-directory '${src}'.`))
      }
    }

    if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
      return cb(new Error(errMsg(src, dest, funcName)))
    }
    return cb(null, { srcStat, destStat })
  })
}

function checkPathsSync (src, dest, funcName, opts) {
  const { srcStat, destStat } = getStatsSync(src, dest, opts)

  if (destStat) {
    if (areIdentical(srcStat, destStat)) {
      const srcBaseName = path.basename(src)
      const destBaseName = path.basename(dest)
      if (funcName === 'move' &&
        srcBaseName !== destBaseName &&
        srcBaseName.toLowerCase() === destBaseName.toLowerCase()) {
        return { srcStat, destStat, isChangingCase: true }
      }
      throw new Error('Source and destination must not be the same.')
    }
    if (srcStat.isDirectory() && !destStat.isDirectory()) {
      throw new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`)
    }
    if (!srcStat.isDirectory() && destStat.isDirectory()) {
      throw new Error(`Cannot overwrite directory '${dest}' with non-directory '${src}'.`)
    }
  }

  if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
    throw new Error(errMsg(src, dest, funcName))
  }
  return { srcStat, destStat }
}

// recursively check if dest parent is a subdirectory of src.
// It works for all file types including symlinks since it
// checks the src and dest inodes. It starts from the deepest
// parent and stops once it reaches the src parent or the root path.
function checkParentPaths (src, srcStat, dest, funcName, cb) {
  const srcParent = path.resolve(path.dirname(src))
  const destParent = path.resolve(path.dirname(dest))
  if (destParent === srcParent || destParent === path.parse(destParent).root) return cb()
  fs.stat(destParent, { bigint: true }, (err, destStat) => {
    if (err) {
      if (err.code === 'ENOENT') return cb()
      return cb(err)
    }
    if (areIdentical(srcStat, destStat)) {
      return cb(new Error(errMsg(src, dest, funcName)))
    }
    return checkParentPaths(src, srcStat, destParent, funcName, cb)
  })
}

function checkParentPathsSync (src, srcStat, dest, funcName) {
  const srcParent = path.resolve(path.dirname(src))
  const destParent = path.resolve(path.dirname(dest))
  if (destParent === srcParent || destParent === path.parse(destParent).root) return
  let destStat
  try {
    destStat = fs.statSync(destParent, { bigint: true })
  } catch (err) {
    if (err.code === 'ENOENT') return
    throw err
  }
  if (areIdentical(srcStat, destStat)) {
    throw new Error(errMsg(src, dest, funcName))
  }
  return checkParentPathsSync(src, srcStat, destParent, funcName)
}

function areIdentical (srcStat, destStat) {
  return destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev
}

// return true if dest is a subdir of src, otherwise false.
// It only checks the path strings.
function isSrcSubdir (src, dest) {
  const srcArr = path.resolve(src).split(path.sep).filter(i => i)
  const destArr = path.resolve(dest).split(path.sep).filter(i => i)
  return srcArr.reduce((acc, cur, i) => acc && destArr[i] === cur, true)
}

function errMsg (src, dest, funcName) {
  return `Cannot ${funcName} '${src}' to a subdirectory of itself, '${dest}'.`
}

module.exports = {
  checkPaths,
  checkPathsSync,
  checkParentPaths,
  checkParentPathsSync,
  isSrcSubdir,
  areIdentical
}
'use strict'

const fs = require('graceful-fs')

function utimesMillis (path, atime, mtime, callback) {
  // if (!HAS_MILLIS_RES) return fs.utimes(path, atime, mtime, callback)
  fs.open(path, 'r+', (err, fd) => {
    if (err) return callback(err)
    fs.futimes(fd, atime, mtime, futimesErr => {
      fs.close(fd, closeErr => {
        if (callback) callback(futimesErr || closeErr)
      })
    })
  })
}

function utimesMillisSync (path, atime, mtime) {
  const fd = fs.openSync(path, 'r+')
  fs.futimesSync(fd, atime, mtime)
  return fs.closeSync(fd)
}

module.exports = {
  utimesMillis,
  utimesMillisSync
}
{
  "name": "fs-extra",
  "version": "10.1.0",
  "description": "fs-extra contains methods that aren't included in the vanilla Node.js fs package. Such as recursive mkdir, copy, and remove.",
  "engines": {
    "node": ">=12"
  },
  "homepage": "https://github.com/jprichardson/node-fs-extra",
  "repository": {
    "type": "git",
    "url": "https://github.com/jprichardson/node-fs-extra"
  },
  "author": "JP Richardson <jprichardson@gmail.com>",
  "license": "MIT",
  "dependencies": {
    "graceful-fs": "^4.2.0",
    "jsonfile": "^6.0.1",
    "universalify": "^2.0.0"
  },
  "devDependencies": {
    "at-least-node": "^1.0.0",
    "klaw": "^2.1.1",
    "klaw-sync": "^3.0.2",
    "minimist": "^1.1.1",
    "mocha": "^5.0.5",
    "nyc": "^15.0.0",
    "proxyquire": "^2.0.1",
    "read-dir-files": "^0.1.1",
    "standard": "^16.0.3"
  },
  "main": "./lib/index.js",
  "files": [
    "lib/",
    "!lib/**/__tests__/"
  ],
  "sideEffects": false
}(The MIT License)

Copyright (c) 2012-2015, JP Richardson <jprichardson@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
 merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
let _fs
try {
  _fs = require('graceful-fs')
} catch (_) {
  _fs = require('fs')
}
const universalify = require('universalify')
const { stringify, stripBom } = require('./utils')

async function _readFile (file, options = {}) {
  if (typeof options === 'string') {
    options = { encoding: options }
  }

  const fs = options.fs || _fs

  const shouldThrow = 'throws' in options ? options.throws : true

  let data = await universalify.fromCallback(fs.readFile)(file, options)

  data = stripBom(data)

  let obj
  try {
    obj = JSON.parse(data, options ? options.reviver : null)
  } catch (err) {
    if (shouldThrow) {
      err.message = `${file}: ${err.message}`
      throw err
    } else {
      return null
    }
  }

  return obj
}

const readFile = universalify.fromPromise(_readFile)

function readFileSync (file, options = {}) {
  if (typeof options === 'string') {
    options = { encoding: options }
  }

  const fs = options.fs || _fs

  const shouldThrow = 'throws' in options ? options.throws : true

  try {
    let content = fs.readFileSync(file, options)
    content = stripBom(content)
    return JSON.parse(content, options.reviver)
  } catch (err) {
    if (shouldThrow) {
      err.message = `${file}: ${err.message}`
      throw err
    } else {
      return null
    }
  }
}

async function _writeFile (file, obj, options = {}) {
  const fs = options.fs || _fs

  const str = stringify(obj, options)

  await universalify.fromCallback(fs.writeFile)(file, str, options)
}

const writeFile = universalify.fromPromise(_writeFile)

function writeFileSync (file, obj, options = {}) {
  const fs = options.fs || _fs

  const str = stringify(obj, options)
  // not sure if fs.writeFileSync returns anything, but just in case
  return fs.writeFileSync(file, str, options)
}

// NOTE: do not change this export format; required for ESM compat
// see https://github.com/jprichardson/node-jsonfile/pull/162 for details
module.exports = {
  readFile,
  readFileSync,
  writeFile,
  writeFileSync
}
{
  "name": "jsonfile",
  "version": "6.2.0",
  "description": "Easily read/write JSON files.",
  "repository": {
    "type": "git",
    "url": "git@github.com:jprichardson/node-jsonfile.git"
  },
  "author": "JP Richardson <jprichardson@gmail.com>",
  "license": "MIT",
  "dependencies": {
    "universalify": "^2.0.0"
  },
  "optionalDependencies": {
    "graceful-fs": "^4.1.6"
  },
  "devDependencies": {
    "mocha": "^8.2.0",
    "rimraf": "^2.4.0",
    "standard": "^16.0.1"
  },
  "main": "index.js",
  "files": [
    "index.js",
    "utils.js"
  ]
}function stringify (obj, { EOL = '\n', finalEOL = true, replacer = null, spaces } = {}) {
  const EOF = finalEOL ? EOL : ''
  const str = JSON.stringify(obj, replacer, spaces)

  return str.replace(/\n/g, EOL) + EOF
}

function stripBom (content) {
  // we do this because JSON.parse would convert it to a utf8 string if encoding wasn't specified
  if (Buffer.isBuffer(content)) content = content.toString('utf8')
  return content.replace(/^\uFEFF/, '')
}

module.exports = { stringify, stripBom }
The ISC License

Copyright (c) Isaac Z. Schlueter and Contributors

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#!/usr/bin/env node
// Standalone semver comparison program.
// Exits successfully and prints matching version(s) if
// any supplied version is valid and passes all tests.

'use strict'

const argv = process.argv.slice(2)

let versions = []

const range = []

let inc = null

const version = require('../package.json').version

let loose = false

let includePrerelease = false

let coerce = false

let rtl = false

let identifier

let identifierBase

const semver = require('../')
const parseOptions = require('../internal/parse-options')

let reverse = false

let options = {}

const main = () => {
  if (!argv.length) {
    return help()
  }
  while (argv.length) {
    let a = argv.shift()
    const indexOfEqualSign = a.indexOf('=')
    if (indexOfEqualSign !== -1) {
      const value = a.slice(indexOfEqualSign + 1)
      a = a.slice(0, indexOfEqualSign)
      argv.unshift(value)
    }
    switch (a) {
      case '-rv': case '-rev': case '--rev': case '--reverse':
        reverse = true
        break
      case '-l': case '--loose':
        loose = true
        break
      case '-p': case '--include-prerelease':
        includePrerelease = true
        break
      case '-v': case '--version':
        versions.push(argv.shift())
        break
      case '-i': case '--inc': case '--increment':
        switch (argv[0]) {
          case 'major': case 'minor': case 'patch': case 'prerelease':
          case 'premajor': case 'preminor': case 'prepatch':
          case 'release':
            inc = argv.shift()
            break
          default:
            inc = 'patch'
            break
        }
        break
      case '--preid':
        identifier = argv.shift()
        break
      case '-r': case '--range':
        range.push(argv.shift())
        break
      case '-n':
        identifierBase = argv.shift()
        if (identifierBase === 'false') {
          identifierBase = false
        }
        break
      case '-c': case '--coerce':
        coerce = true
        break
      case '--rtl':
        rtl = true
        break
      case '--ltr':
        rtl = false
        break
      case '-h': case '--help': case '-?':
        return help()
      default:
        versions.push(a)
        break
    }
  }

  options = parseOptions({ loose, includePrerelease, rtl })

  versions = versions.map((v) => {
    return coerce ? (semver.coerce(v, options) || { version: v }).version : v
  }).filter((v) => {
    return semver.valid(v)
  })
  if (!versions.length) {
    return fail()
  }
  if (inc && (versions.length !== 1 || range.length)) {
    return failInc()
  }

  for (let i = 0, l = range.length; i < l; i++) {
    versions = versions.filter((v) => {
      return semver.satisfies(v, range[i], options)
    })
    if (!versions.length) {
      return fail()
    }
  }
  versions
    .sort((a, b) => semver[reverse ? 'rcompare' : 'compare'](a, b, options))
    .map(v => semver.clean(v, options))
    .map(v => inc ? semver.inc(v, inc, options, identifier, identifierBase) : v)
    .forEach(v => console.log(v))
}

const failInc = () => {
  console.error('--inc can only be used on a single version with no range')
  fail()
}

const fail = () => process.exit(1)

const help = () => console.log(
`SemVer ${version}

A JavaScript implementation of the https://semver.org/ specification
Copyright Isaac Z. Schlueter

Usage: semver [options] <version> [<version> [...]]
Prints valid versions sorted by SemVer precedence

Options:
-r --range <range>
        Print versions that match the specified range.

-i --increment [<level>]
        Increment a version by the specified level.  Level can
        be one of: major, minor, patch, premajor, preminor,
        prepatch, prerelease, or release.  Default level is 'patch'.
        Only one version may be specified.

--preid <identifier>
        Identifier to be used to prefix premajor, preminor,
        prepatch or prerelease version increments.

-l --loose
        Interpret versions and ranges loosely

-p --include-prerelease
        Always include prerelease versions in range matching

-c --coerce
        Coerce a string into SemVer if possible
        (does not imply --loose)

--rtl
        Coerce version strings right to left

--ltr
        Coerce version strings left to right (default)

-n <base>
        Base number to be used for the prerelease identifier.
        Can be either 0 or 1, or false to omit the number altogether.
        Defaults to 0.

Program exits successfully if any valid version satisfies
all supplied ranges, and prints all satisfying versions.

If no satisfying versions are found, then exits failure.

Versions are printed in ascending order, so supplying
multiple versions to the utility will just sort them.`)

main()
'use strict'

const ANY = Symbol('SemVer ANY')
// hoisted class for cyclic dependency
class Comparator {
  static get ANY () {
    return ANY
  }

  constructor (comp, options) {
    options = parseOptions(options)

    if (comp instanceof Comparator) {
      if (comp.loose === !!options.loose) {
        return comp
      } else {
        comp = comp.value
      }
    }

    comp = comp.trim().split(/\s+/).join(' ')
    debug('comparator', comp, options)
    this.options = options
    this.loose = !!options.loose
    this.parse(comp)

    if (this.semver === ANY) {
      this.value = ''
    } else {
      this.value = this.operator + this.semver.version
    }

    debug('comp', this)
  }

  parse (comp) {
    const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]
    const m = comp.match(r)

    if (!m) {
      throw new TypeError(`Invalid comparator: ${comp}`)
    }

    this.operator = m[1] !== undefined ? m[1] : ''
    if (this.operator === '=') {
      this.operator = ''
    }

    // if it literally is just '>' or '' then allow anything.
    if (!m[2]) {
      this.semver = ANY
    } else {
      this.semver = new SemVer(m[2], this.options.loose)
    }
  }

  toString () {
    return this.value
  }

  test (version) {
    debug('Comparator.test', version, this.options.loose)

    if (this.semver === ANY || version === ANY) {
      return true
    }

    if (typeof version === 'string') {
      try {
        version = new SemVer(version, this.options)
      } catch (er) {
        return false
      }
    }

    return cmp(version, this.operator, this.semver, this.options)
  }

  intersects (comp, options) {
    if (!(comp instanceof Comparator)) {
      throw new TypeError('a Comparator is required')
    }

    if (this.operator === '') {
      if (this.value === '') {
        return true
      }
      return new Range(comp.value, options).test(this.value)
    } else if (comp.operator === '') {
      if (comp.value === '') {
        return true
      }
      return new Range(this.value, options).test(comp.semver)
    }

    options = parseOptions(options)

    // Special cases where nothing can possibly be lower
    if (options.includePrerelease &&
      (this.value === '<0.0.0-0' || comp.value === '<0.0.0-0')) {
      return false
    }
    if (!options.includePrerelease &&
      (this.value.startsWith('<0.0.0') || comp.value.startsWith('<0.0.0'))) {
      return false
    }

    // Same direction increasing (> or >=)
    if (this.operator.startsWith('>') && comp.operator.startsWith('>')) {
      return true
    }
    // Same direction decreasing (< or <=)
    if (this.operator.startsWith('<') && comp.operator.startsWith('<')) {
      return true
    }
    // same SemVer and both sides are inclusive (<= or >=)
    if (
      (this.semver.version === comp.semver.version) &&
      this.operator.includes('=') && comp.operator.includes('=')) {
      return true
    }
    // opposite directions less than
    if (cmp(this.semver, '<', comp.semver, options) &&
      this.operator.startsWith('>') && comp.operator.startsWith('<')) {
      return true
    }
    // opposite directions greater than
    if (cmp(this.semver, '>', comp.semver, options) &&
      this.operator.startsWith('<') && comp.operator.startsWith('>')) {
      return true
    }
    return false
  }
}

module.exports = Comparator

const parseOptions = require('../internal/parse-options')
const { safeRe: re, t } = require('../internal/re')
const cmp = require('../functions/cmp')
const debug = require('../internal/debug')
const SemVer = require('./semver')
const Range = require('./range')
'use strict'

module.exports = {
  SemVer: require('./semver.js'),
  Range: require('./range.js'),
  Comparator: require('./comparator.js'),
}
'use strict'

const SPACE_CHARACTERS = /\s+/g

// hoisted class for cyclic dependency
class Range {
  constructor (range, options) {
    options = parseOptions(options)

    if (range instanceof Range) {
      if (
        range.loose === !!options.loose &&
        range.includePrerelease === !!options.includePrerelease
      ) {
        return range
      } else {
        return new Range(range.raw, options)
      }
    }

    if (range instanceof Comparator) {
      // just put it in the set and return
      this.raw = range.value
      this.set = [[range]]
      this.formatted = undefined
      return this
    }

    this.options = options
    this.loose = !!options.loose
    this.includePrerelease = !!options.includePrerelease

    // First reduce all whitespace as much as possible so we do not have to rely
    // on potentially slow regexes like \s*. This is then stored and used for
    // future error messages as well.
    this.raw = range.trim().replace(SPACE_CHARACTERS, ' ')

    // First, split on ||
    this.set = this.raw
      .split('||')
      // map the range to a 2d array of comparators
      .map(r => this.parseRange(r.trim()))
      // throw out any comparator lists that are empty
      // this generally means that it was not a valid range, which is allowed
      // in loose mode, but will still throw if the WHOLE range is invalid.
      .filter(c => c.length)

    if (!this.set.length) {
      throw new TypeError(`Invalid SemVer Range: ${this.raw}`)
    }

    // if we have any that are not the null set, throw out null sets.
    if (this.set.length > 1) {
      // keep the first one, in case they're all null sets
      const first = this.set[0]
      this.set = this.set.filter(c => !isNullSet(c[0]))
      if (this.set.length === 0) {
        this.set = [first]
      } else if (this.set.length > 1) {
        // if we have any that are *, then the range is just *
        for (const c of this.set) {
          if (c.length === 1 && isAny(c[0])) {
            this.set = [c]
            break
          }
        }
      }
    }

    this.formatted = undefined
  }

  get range () {
    if (this.formatted === undefined) {
      this.formatted = ''
      for (let i = 0; i < this.set.length; i++) {
        if (i > 0) {
          this.formatted += '||'
        }
        const comps = this.set[i]
        for (let k = 0; k < comps.length; k++) {
          if (k > 0) {
            this.formatted += ' '
          }
          this.formatted += comps[k].toString().trim()
        }
      }
    }
    return this.formatted
  }

  format () {
    return this.range
  }

  toString () {
    return this.range
  }

  parseRange (range) {
    // memoize range parsing for performance.
    // this is a very hot path, and fully deterministic.
    const memoOpts =
      (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) |
      (this.options.loose && FLAG_LOOSE)
    const memoKey = memoOpts + ':' + range
    const cached = cache.get(memoKey)
    if (cached) {
      return cached
    }

    const loose = this.options.loose
    // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
    const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]
    range = range.replace(hr, hyphenReplace(this.options.includePrerelease))
    debug('hyphen replace', range)

    // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
    range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace)
    debug('comparator trim', range)

    // `~ 1.2.3` => `~1.2.3`
    range = range.replace(re[t.TILDETRIM], tildeTrimReplace)
    debug('tilde trim', range)

    // `^ 1.2.3` => `^1.2.3`
    range = range.replace(re[t.CARETTRIM], caretTrimReplace)
    debug('caret trim', range)

    // At this point, the range is completely trimmed and
    // ready to be split into comparators.

    let rangeList = range
      .split(' ')
      .map(comp => parseComparator(comp, this.options))
      .join(' ')
      .split(/\s+/)
      // >=0.0.0 is equivalent to *
      .map(comp => replaceGTE0(comp, this.options))

    if (loose) {
      // in loose mode, throw out any that are not valid comparators
      rangeList = rangeList.filter(comp => {
        debug('loose invalid filter', comp, this.options)
        return !!comp.match(re[t.COMPARATORLOOSE])
      })
    }
    debug('range list', rangeList)

    // if any comparators are the null set, then replace with JUST null set
    // if more than one comparator, remove any * comparators
    // also, don't include the same comparator more than once
    const rangeMap = new Map()
    const comparators = rangeList.map(comp => new Comparator(comp, this.options))
    for (const comp of comparators) {
      if (isNullSet(comp)) {
        return [comp]
      }
      rangeMap.set(comp.value, comp)
    }
    if (rangeMap.size > 1 && rangeMap.has('')) {
      rangeMap.delete('')
    }

    const result = [...rangeMap.values()]
    cache.set(memoKey, result)
    return result
  }

  intersects (range, options) {
    if (!(range instanceof Range)) {
      throw new TypeError('a Range is required')
    }

    return this.set.some((thisComparators) => {
      return (
        isSatisfiable(thisComparators, options) &&
        range.set.some((rangeComparators) => {
          return (
            isSatisfiable(rangeComparators, options) &&
            thisComparators.every((thisComparator) => {
              return rangeComparators.every((rangeComparator) => {
                return thisComparator.intersects(rangeComparator, options)
              })
            })
          )
        })
      )
    })
  }

  // if ANY of the sets match ALL of its comparators, then pass
  test (version) {
    if (!version) {
      return false
    }

    if (typeof version === 'string') {
      try {
        version = new SemVer(version, this.options)
      } catch (er) {
        return false
      }
    }

    for (let i = 0; i < this.set.length; i++) {
      if (testSet(this.set[i], version, this.options)) {
        return true
      }
    }
    return false
  }
}

module.exports = Range

const LRU = require('../internal/lrucache')
const cache = new LRU()

const parseOptions = require('../internal/parse-options')
const Comparator = require('./comparator')
const debug = require('../internal/debug')
const SemVer = require('./semver')
const {
  safeRe: re,
  t,
  comparatorTrimReplace,
  tildeTrimReplace,
  caretTrimReplace,
} = require('../internal/re')
const { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require('../internal/constants')

const isNullSet = c => c.value === '<0.0.0-0'
const isAny = c => c.value === ''

// take a set of comparators and determine whether there
// exists a version which can satisfy it
const isSatisfiable = (comparators, options) => {
  let result = true
  const remainingComparators = comparators.slice()
  let testComparator = remainingComparators.pop()

  while (result && remainingComparators.length) {
    result = remainingComparators.every((otherComparator) => {
      return testComparator.intersects(otherComparator, options)
    })

    testComparator = remainingComparators.pop()
  }

  return result
}

// comprised of xranges, tildes, stars, and gtlt's at this point.
// already replaced the hyphen ranges
// turn into a set of JUST comparators.
const parseComparator = (comp, options) => {
  comp = comp.replace(re[t.BUILD], '')
  debug('comp', comp, options)
  comp = replaceCarets(comp, options)
  debug('caret', comp)
  comp = replaceTildes(comp, options)
  debug('tildes', comp)
  comp = replaceXRanges(comp, options)
  debug('xrange', comp)
  comp = replaceStars(comp, options)
  debug('stars', comp)
  return comp
}

const isX = id => !id || id.toLowerCase() === 'x' || id === '*'

// ~, ~> --> * (any, kinda silly)
// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0-0
// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0-0
// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0-0
// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0-0
// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0-0
// ~0.0.1 --> >=0.0.1 <0.1.0-0
const replaceTildes = (comp, options) => {
  return comp
    .trim()
    .split(/\s+/)
    .map((c) => replaceTilde(c, options))
    .join(' ')
}

const replaceTilde = (comp, options) => {
  const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]
  return comp.replace(r, (_, M, m, p, pr) => {
    debug('tilde', comp, _, M, m, p, pr)
    let ret

    if (isX(M)) {
      ret = ''
    } else if (isX(m)) {
      ret = `>=${M}.0.0 <${+M + 1}.0.0-0`
    } else if (isX(p)) {
      // ~1.2 == >=1.2.0 <1.3.0-0
      ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`
    } else if (pr) {
      debug('replaceTilde pr', pr)
      ret = `>=${M}.${m}.${p}-${pr
      } <${M}.${+m + 1}.0-0`
    } else {
      // ~1.2.3 == >=1.2.3 <1.3.0-0
      ret = `>=${M}.${m}.${p
      } <${M}.${+m + 1}.0-0`
    }

    debug('tilde return', ret)
    return ret
  })
}

// ^ --> * (any, kinda silly)
// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0-0
// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0-0
// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0-0
// ^1.2.3 --> >=1.2.3 <2.0.0-0
// ^1.2.0 --> >=1.2.0 <2.0.0-0
// ^0.0.1 --> >=0.0.1 <0.0.2-0
// ^0.1.0 --> >=0.1.0 <0.2.0-0
const replaceCarets = (comp, options) => {
  return comp
    .trim()
    .split(/\s+/)
    .map((c) => replaceCaret(c, options))
    .join(' ')
}

const replaceCaret = (comp, options) => {
  debug('caret', comp, options)
  const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]
  const z = options.includePrerelease ? '-0' : ''
  return comp.replace(r, (_, M, m, p, pr) => {
    debug('caret', comp, _, M, m, p, pr)
    let ret

    if (isX(M)) {
      ret = ''
    } else if (isX(m)) {
      ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`
    } else if (isX(p)) {
      if (M === '0') {
        ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`
      } else {
        ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`
      }
    } else if (pr) {
      debug('replaceCaret pr', pr)
      if (M === '0') {
        if (m === '0') {
          ret = `>=${M}.${m}.${p}-${pr
          } <${M}.${m}.${+p + 1}-0`
        } else {
          ret = `>=${M}.${m}.${p}-${pr
          } <${M}.${+m + 1}.0-0`
        }
      } else {
        ret = `>=${M}.${m}.${p}-${pr
        } <${+M + 1}.0.0-0`
      }
    } else {
      debug('no pr')
      if (M === '0') {
        if (m === '0') {
          ret = `>=${M}.${m}.${p
          }${z} <${M}.${m}.${+p + 1}-0`
        } else {
          ret = `>=${M}.${m}.${p
          }${z} <${M}.${+m + 1}.0-0`
        }
      } else {
        ret = `>=${M}.${m}.${p
        } <${+M + 1}.0.0-0`
      }
    }

    debug('caret return', ret)
    return ret
  })
}

const replaceXRanges = (comp, options) => {
  debug('replaceXRanges', comp, options)
  return comp
    .split(/\s+/)
    .map((c) => replaceXRange(c, options))
    .join(' ')
}

const replaceXRange = (comp, options) => {
  comp = comp.trim()
  const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]
  return comp.replace(r, (ret, gtlt, M, m, p, pr) => {
    debug('xRange', comp, ret, gtlt, M, m, p, pr)
    const xM = isX(M)
    const xm = xM || isX(m)
    const xp = xm || isX(p)
    const anyX = xp

    if (gtlt === '=' && anyX) {
      gtlt = ''
    }

    // if we're including prereleases in the match, then we need
    // to fix this to -0, the lowest possible prerelease value
    pr = options.includePrerelease ? '-0' : ''

    if (xM) {
      if (gtlt === '>' || gtlt === '<') {
        // nothing is allowed
        ret = '<0.0.0-0'
      } else {
        // nothing is forbidden
        ret = '*'
      }
    } else if (gtlt && anyX) {
      // we know patch is an x, because we have any x at all.
      // replace X with 0
      if (xm) {
        m = 0
      }
      p = 0

      if (gtlt === '>') {
        // >1 => >=2.0.0
        // >1.2 => >=1.3.0
        gtlt = '>='
        if (xm) {
          M = +M + 1
          m = 0
          p = 0
        } else {
          m = +m + 1
          p = 0
        }
      } else if (gtlt === '<=') {
        // <=0.7.x is actually <0.8.0, since any 0.7.x should
        // pass.  Similarly, <=7.x is actually <8.0.0, etc.
        gtlt = '<'
        if (xm) {
          M = +M + 1
        } else {
          m = +m + 1
        }
      }

      if (gtlt === '<') {
        pr = '-0'
      }

      ret = `${gtlt + M}.${m}.${p}${pr}`
    } else if (xm) {
      ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`
    } else if (xp) {
      ret = `>=${M}.${m}.0${pr
      } <${M}.${+m + 1}.0-0`
    }

    debug('xRange return', ret)

    return ret
  })
}

// Because * is AND-ed with everything else in the comparator,
// and '' means "any version", just remove the *s entirely.
const replaceStars = (comp, options) => {
  debug('replaceStars', comp, options)
  // Looseness is ignored here.  star is always as loose as it gets!
  return comp
    .trim()
    .replace(re[t.STAR], '')
}

const replaceGTE0 = (comp, options) => {
  debug('replaceGTE0', comp, options)
  return comp
    .trim()
    .replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], '')
}

// This function is passed to string.replace(re[t.HYPHENRANGE])
// M, m, patch, prerelease, build
// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
// 1.2.3 - 3.4 => >=1.2.0 <3.5.0-0 Any 3.4.x will do
// 1.2 - 3.4 => >=1.2.0 <3.5.0-0
// TODO build?
const hyphenReplace = incPr => ($0,
  from, fM, fm, fp, fpr, fb,
  to, tM, tm, tp, tpr) => {
  if (isX(fM)) {
    from = ''
  } else if (isX(fm)) {
    from = `>=${fM}.0.0${incPr ? '-0' : ''}`
  } else if (isX(fp)) {
    from = `>=${fM}.${fm}.0${incPr ? '-0' : ''}`
  } else if (fpr) {
    from = `>=${from}`
  } else {
    from = `>=${from}${incPr ? '-0' : ''}`
  }

  if (isX(tM)) {
    to = ''
  } else if (isX(tm)) {
    to = `<${+tM + 1}.0.0-0`
  } else if (isX(tp)) {
    to = `<${tM}.${+tm + 1}.0-0`
  } else if (tpr) {
    to = `<=${tM}.${tm}.${tp}-${tpr}`
  } else if (incPr) {
    to = `<${tM}.${tm}.${+tp + 1}-0`
  } else {
    to = `<=${to}`
  }

  return `${from} ${to}`.trim()
}

const testSet = (set, version, options) => {
  for (let i = 0; i < set.length; i++) {
    if (!set[i].test(version)) {
      return false
    }
  }

  if (version.prerelease.length && !options.includePrerelease) {
    // Find the set of versions that are allowed to have prereleases
    // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0
    // That should allow `1.2.3-pr.2` to pass.
    // However, `1.2.4-alpha.notready` should NOT be allowed,
    // even though it's within the range set by the comparators.
    for (let i = 0; i < set.length; i++) {
      debug(set[i].semver)
      if (set[i].semver === Comparator.ANY) {
        continue
      }

      if (set[i].semver.prerelease.length > 0) {
        const allowed = set[i].semver
        if (allowed.major === version.major &&
            allowed.minor === version.minor &&
            allowed.patch === version.patch) {
          return true
        }
      }
    }

    // Version has a -pre, but it's not one of the ones we like.
    return false
  }

  return true
}
'use strict'

const debug = require('../internal/debug')
const { MAX_LENGTH, MAX_SAFE_INTEGER } = require('../internal/constants')
const { safeRe: re, t } = require('../internal/re')

const parseOptions = require('../internal/parse-options')
const { compareIdentifiers } = require('../internal/identifiers')
class SemVer {
  constructor (version, options) {
    options = parseOptions(options)

    if (version instanceof SemVer) {
      if (version.loose === !!options.loose &&
        version.includePrerelease === !!options.includePrerelease) {
        return version
      } else {
        version = version.version
      }
    } else if (typeof version !== 'string') {
      throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`)
    }

    if (version.length > MAX_LENGTH) {
      throw new TypeError(
        `version is longer than ${MAX_LENGTH} characters`
      )
    }

    debug('SemVer', version, options)
    this.options = options
    this.loose = !!options.loose
    // this isn't actually relevant for versions, but keep it so that we
    // don't run into trouble passing this.options around.
    this.includePrerelease = !!options.includePrerelease

    const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL])

    if (!m) {
      throw new TypeError(`Invalid Version: ${version}`)
    }

    this.raw = version

    // these are actually numbers
    this.major = +m[1]
    this.minor = +m[2]
    this.patch = +m[3]

    if (this.major > MAX_SAFE_INTEGER || this.major < 0) {
      throw new TypeError('Invalid major version')
    }

    if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) {
      throw new TypeError('Invalid minor version')
    }

    if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) {
      throw new TypeError('Invalid patch version')
    }

    // numberify any prerelease numeric ids
    if (!m[4]) {
      this.prerelease = []
    } else {
      this.prerelease = m[4].split('.').map((id) => {
        if (/^[0-9]+$/.test(id)) {
          const num = +id
          if (num >= 0 && num < MAX_SAFE_INTEGER) {
            return num
          }
        }
        return id
      })
    }

    this.build = m[5] ? m[5].split('.') : []
    this.format()
  }

  format () {
    this.version = `${this.major}.${this.minor}.${this.patch}`
    if (this.prerelease.length) {
      this.version += `-${this.prerelease.join('.')}`
    }
    return this.version
  }

  toString () {
    return this.version
  }

  compare (other) {
    debug('SemVer.compare', this.version, this.options, other)
    if (!(other instanceof SemVer)) {
      if (typeof other === 'string' && other === this.version) {
        return 0
      }
      other = new SemVer(other, this.options)
    }

    if (other.version === this.version) {
      return 0
    }

    return this.compareMain(other) || this.comparePre(other)
  }

  compareMain (other) {
    if (!(other instanceof SemVer)) {
      other = new SemVer(other, this.options)
    }

    if (this.major < other.major) {
      return -1
    }
    if (this.major > other.major) {
      return 1
    }
    if (this.minor < other.minor) {
      return -1
    }
    if (this.minor > other.minor) {
      return 1
    }
    if (this.patch < other.patch) {
      return -1
    }
    if (this.patch > other.patch) {
      return 1
    }
    return 0
  }

  comparePre (other) {
    if (!(other instanceof SemVer)) {
      other = new SemVer(other, this.options)
    }

    // NOT having a prerelease is > having one
    if (this.prerelease.length && !other.prerelease.length) {
      return -1
    } else if (!this.prerelease.length && other.prerelease.length) {
      return 1
    } else if (!this.prerelease.length && !other.prerelease.length) {
      return 0
    }

    let i = 0
    do {
      const a = this.prerelease[i]
      const b = other.prerelease[i]
      debug('prerelease compare', i, a, b)
      if (a === undefined && b === undefined) {
        return 0
      } else if (b === undefined) {
        return 1
      } else if (a === undefined) {
        return -1
      } else if (a === b) {
        continue
      } else {
        return compareIdentifiers(a, b)
      }
    } while (++i)
  }

  compareBuild (other) {
    if (!(other instanceof SemVer)) {
      other = new SemVer(other, this.options)
    }

    let i = 0
    do {
      const a = this.build[i]
      const b = other.build[i]
      debug('build compare', i, a, b)
      if (a === undefined && b === undefined) {
        return 0
      } else if (b === undefined) {
        return 1
      } else if (a === undefined) {
        return -1
      } else if (a === b) {
        continue
      } else {
        return compareIdentifiers(a, b)
      }
    } while (++i)
  }

  // preminor will bump the version up to the next minor release, and immediately
  // down to pre-release. premajor and prepatch work the same way.
  inc (release, identifier, identifierBase) {
    if (release.startsWith('pre')) {
      if (!identifier && identifierBase === false) {
        throw new Error('invalid increment argument: identifier is empty')
      }
      // Avoid an invalid semver results
      if (identifier) {
        const match = `-${identifier}`.match(this.options.loose ? re[t.PRERELEASELOOSE] : re[t.PRERELEASE])
        if (!match || match[1] !== identifier) {
          throw new Error(`invalid identifier: ${identifier}`)
        }
      }
    }

    switch (release) {
      case 'premajor':
        this.prerelease.length = 0
        this.patch = 0
        this.minor = 0
        this.major++
        this.inc('pre', identifier, identifierBase)
        break
      case 'preminor':
        this.prerelease.length = 0
        this.patch = 0
        this.minor++
        this.inc('pre', identifier, identifierBase)
        break
      case 'prepatch':
        // If this is already a prerelease, it will bump to the next version
        // drop any prereleases that might already exist, since they are not
        // relevant at this point.
        this.prerelease.length = 0
        this.inc('patch', identifier, identifierBase)
        this.inc('pre', identifier, identifierBase)
        break
      // If the input is a non-prerelease version, this acts the same as
      // prepatch.
      case 'prerelease':
        if (this.prerelease.length === 0) {
          this.inc('patch', identifier, identifierBase)
        }
        this.inc('pre', identifier, identifierBase)
        break
      case 'release':
        if (this.prerelease.length === 0) {
          throw new Error(`version ${this.raw} is not a prerelease`)
        }
        this.prerelease.length = 0
        break

      case 'major':
        // If this is a pre-major version, bump up to the same major version.
        // Otherwise increment major.
        // 1.0.0-5 bumps to 1.0.0
        // 1.1.0 bumps to 2.0.0
        if (
          this.minor !== 0 ||
          this.patch !== 0 ||
          this.prerelease.length === 0
        ) {
          this.major++
        }
        this.minor = 0
        this.patch = 0
        this.prerelease = []
        break
      case 'minor':
        // If this is a pre-minor version, bump up to the same minor version.
        // Otherwise increment minor.
        // 1.2.0-5 bumps to 1.2.0
        // 1.2.1 bumps to 1.3.0
        if (this.patch !== 0 || this.prerelease.length === 0) {
          this.minor++
        }
        this.patch = 0
        this.prerelease = []
        break
      case 'patch':
        // If this is not a pre-release version, it will increment the patch.
        // If it is a pre-release it will bump up to the same patch version.
        // 1.2.0-5 patches to 1.2.0
        // 1.2.0 patches to 1.2.1
        if (this.prerelease.length === 0) {
          this.patch++
        }
        this.prerelease = []
        break
      // This probably shouldn't be used publicly.
      // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction.
      case 'pre': {
        const base = Number(identifierBase) ? 1 : 0

        if (this.prerelease.length === 0) {
          this.prerelease = [base]
        } else {
          let i = this.prerelease.length
          while (--i >= 0) {
            if (typeof this.prerelease[i] === 'number') {
              this.prerelease[i]++
              i = -2
            }
          }
          if (i === -1) {
            // didn't increment anything
            if (identifier === this.prerelease.join('.') && identifierBase === false) {
              throw new Error('invalid increment argument: identifier already exists')
            }
            this.prerelease.push(base)
          }
        }
        if (identifier) {
          // 1.2.0-beta.1 bumps to 1.2.0-beta.2,
          // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
          let prerelease = [identifier, base]
          if (identifierBase === false) {
            prerelease = [identifier]
          }
          if (compareIdentifiers(this.prerelease[0], identifier) === 0) {
            if (isNaN(this.prerelease[1])) {
              this.prerelease = prerelease
            }
          } else {
            this.prerelease = prerelease
          }
        }
        break
      }
      default:
        throw new Error(`invalid increment argument: ${release}`)
    }
    this.raw = this.format()
    if (this.build.length) {
      this.raw += `+${this.build.join('.')}`
    }
    return this
  }
}

module.exports = SemVer
'use strict'

const parse = require('./parse')
const clean = (version, options) => {
  const s = parse(version.trim().replace(/^[=v]+/, ''), options)
  return s ? s.version : null
}
module.exports = clean
'use strict'

const eq = require('./eq')
const neq = require('./neq')
const gt = require('./gt')
const gte = require('./gte')
const lt = require('./lt')
const lte = require('./lte')

const cmp = (a, op, b, loose) => {
  switch (op) {
    case '===':
      if (typeof a === 'object') {
        a = a.version
      }
      if (typeof b === 'object') {
        b = b.version
      }
      return a === b

    case '!==':
      if (typeof a === 'object') {
        a = a.version
      }
      if (typeof b === 'object') {
        b = b.version
      }
      return a !== b

    case '':
    case '=':
    case '==':
      return eq(a, b, loose)

    case '!=':
      return neq(a, b, loose)

    case '>':
      return gt(a, b, loose)

    case '>=':
      return gte(a, b, loose)

    case '<':
      return lt(a, b, loose)

    case '<=':
      return lte(a, b, loose)

    default:
      throw new TypeError(`Invalid operator: ${op}`)
  }
}
module.exports = cmp
'use strict'

const SemVer = require('../classes/semver')
const parse = require('./parse')
const { safeRe: re, t } = require('../internal/re')

const coerce = (version, options) => {
  if (version instanceof SemVer) {
    return version
  }

  if (typeof version === 'number') {
    version = String(version)
  }

  if (typeof version !== 'string') {
    return null
  }

  options = options || {}

  let match = null
  if (!options.rtl) {
    match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE])
  } else {
    // Find the right-most coercible string that does not share
    // a terminus with a more left-ward coercible string.
    // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4'
    // With includePrerelease option set, '1.2.3.4-rc' wants to coerce '2.3.4-rc', not '2.3.4'
    //
    // Walk through the string checking with a /g regexp
    // Manually set the index so as to pick up overlapping matches.
    // Stop when we get a match that ends at the string end, since no
    // coercible string can be more right-ward without the same terminus.
    const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL]
    let next
    while ((next = coerceRtlRegex.exec(version)) &&
        (!match || match.index + match[0].length !== version.length)
    ) {
      if (!match ||
            next.index + next[0].length !== match.index + match[0].length) {
        match = next
      }
      coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length
    }
    // leave it in a clean state
    coerceRtlRegex.lastIndex = -1
  }

  if (match === null) {
    return null
  }

  const major = match[2]
  const minor = match[3] || '0'
  const patch = match[4] || '0'
  const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : ''
  const build = options.includePrerelease && match[6] ? `+${match[6]}` : ''

  return parse(`${major}.${minor}.${patch}${prerelease}${build}`, options)
}
module.exports = coerce
'use strict'

const SemVer = require('../classes/semver')
const compareBuild = (a, b, loose) => {
  const versionA = new SemVer(a, loose)
  const versionB = new SemVer(b, loose)
  return versionA.compare(versionB) || versionA.compareBuild(versionB)
}
module.exports = compareBuild
'use strict'

const compare = require('./compare')
const compareLoose = (a, b) => compare(a, b, true)
module.exports = compareLoose
'use strict'

const SemVer = require('../classes/semver')
const compare = (a, b, loose) =>
  new SemVer(a, loose).compare(new SemVer(b, loose))

module.exports = compare
'use strict'

const parse = require('./parse.js')

const diff = (version1, version2) => {
  const v1 = parse(version1, null, true)
  const v2 = parse(version2, null, true)
  const comparison = v1.compare(v2)

  if (comparison === 0) {
    return null
  }

  const v1Higher = comparison > 0
  const highVersion = v1Higher ? v1 : v2
  const lowVersion = v1Higher ? v2 : v1
  const highHasPre = !!highVersion.prerelease.length
  const lowHasPre = !!lowVersion.prerelease.length

  if (lowHasPre && !highHasPre) {
    // Going from prerelease -> no prerelease requires some special casing

    // If the low version has only a major, then it will always be a major
    // Some examples:
    // 1.0.0-1 -> 1.0.0
    // 1.0.0-1 -> 1.1.1
    // 1.0.0-1 -> 2.0.0
    if (!lowVersion.patch && !lowVersion.minor) {
      return 'major'
    }

    // If the main part has no difference
    if (lowVersion.compareMain(highVersion) === 0) {
      if (lowVersion.minor && !lowVersion.patch) {
        return 'minor'
      }
      return 'patch'
    }
  }

  // add the `pre` prefix if we are going to a prerelease version
  const prefix = highHasPre ? 'pre' : ''

  if (v1.major !== v2.major) {
    return prefix + 'major'
  }

  if (v1.minor !== v2.minor) {
    return prefix + 'minor'
  }

  if (v1.patch !== v2.patch) {
    return prefix + 'patch'
  }

  // high and low are preleases
  return 'prerelease'
}

module.exports = diff
'use strict'

const compare = require('./compare')
const eq = (a, b, loose) => compare(a, b, loose) === 0
module.exports = eq
'use strict'

const compare = require('./compare')
const gt = (a, b, loose) => compare(a, b, loose) > 0
module.exports = gt
'use strict'

const compare = require('./compare')
const gte = (a, b, loose) => compare(a, b, loose) >= 0
module.exports = gte
'use strict'

const SemVer = require('../classes/semver')

const inc = (version, release, options, identifier, identifierBase) => {
  if (typeof (options) === 'string') {
    identifierBase = identifier
    identifier = options
    options = undefined
  }

  try {
    return new SemVer(
      version instanceof SemVer ? version.version : version,
      options
    ).inc(release, identifier, identifierBase).version
  } catch (er) {
    return null
  }
}
module.exports = inc
'use strict'

const compare = require('./compare')
const lt = (a, b, loose) => compare(a, b, loose) < 0
module.exports = lt
'use strict'

const compare = require('./compare')
const lte = (a, b, loose) => compare(a, b, loose) <= 0
module.exports = lte
'use strict'

const SemVer = require('../classes/semver')
const major = (a, loose) => new SemVer(a, loose).major
module.exports = major
'use strict'

const SemVer = require('../classes/semver')
const minor = (a, loose) => new SemVer(a, loose).minor
module.exports = minor
'use strict'

const compare = require('./compare')
const neq = (a, b, loose) => compare(a, b, loose) !== 0
module.exports = neq
'use strict'

const SemVer = require('../classes/semver')
const parse = (version, options, throwErrors = false) => {
  if (version instanceof SemVer) {
    return version
  }
  try {
    return new SemVer(version, options)
  } catch (er) {
    if (!throwErrors) {
      return null
    }
    throw er
  }
}

module.exports = parse
'use strict'

const SemVer = require('../classes/semver')
const patch = (a, loose) => new SemVer(a, loose).patch
module.exports = patch
'use strict'

const parse = require('./parse')
const prerelease = (version, options) => {
  const parsed = parse(version, options)
  return (parsed && parsed.prerelease.length) ? parsed.prerelease : null
}
module.exports = prerelease
'use strict'

const compare = require('./compare')
const rcompare = (a, b, loose) => compare(b, a, loose)
module.exports = rcompare
'use strict'

const compareBuild = require('./compare-build')
const rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose))
module.exports = rsort
'use strict'

const Range = require('../classes/range')
const satisfies = (version, range, options) => {
  try {
    range = new Range(range, options)
  } catch (er) {
    return false
  }
  return range.test(version)
}
module.exports = satisfies
'use strict'

const compareBuild = require('./compare-build')
const sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose))
module.exports = sort
'use strict'

const parse = require('./parse')
const valid = (version, options) => {
  const v = parse(version, options)
  return v ? v.version : null
}
module.exports = valid
'use strict'

// just pre-load all the stuff that index.js lazily exports
const internalRe = require('./internal/re')
const constants = require('./internal/constants')
const SemVer = require('./classes/semver')
const identifiers = require('./internal/identifiers')
const parse = require('./functions/parse')
const valid = require('./functions/valid')
const clean = require('./functions/clean')
const inc = require('./functions/inc')
const diff = require('./functions/diff')
const major = require('./functions/major')
const minor = require('./functions/minor')
const patch = require('./functions/patch')
const prerelease = require('./functions/prerelease')
const compare = require('./functions/compare')
const rcompare = require('./functions/rcompare')
const compareLoose = require('./functions/compare-loose')
const compareBuild = require('./functions/compare-build')
const sort = require('./functions/sort')
const rsort = require('./functions/rsort')
const gt = require('./functions/gt')
const lt = require('./functions/lt')
const eq = require('./functions/eq')
const neq = require('./functions/neq')
const gte = require('./functions/gte')
const lte = require('./functions/lte')
const cmp = require('./functions/cmp')
const coerce = require('./functions/coerce')
const Comparator = require('./classes/comparator')
const Range = require('./classes/range')
const satisfies = require('./functions/satisfies')
const toComparators = require('./ranges/to-comparators')
const maxSatisfying = require('./ranges/max-satisfying')
const minSatisfying = require('./ranges/min-satisfying')
const minVersion = require('./ranges/min-version')
const validRange = require('./ranges/valid')
const outside = require('./ranges/outside')
const gtr = require('./ranges/gtr')
const ltr = require('./ranges/ltr')
const intersects = require('./ranges/intersects')
const simplifyRange = require('./ranges/simplify')
const subset = require('./ranges/subset')
module.exports = {
  parse,
  valid,
  clean,
  inc,
  diff,
  major,
  minor,
  patch,
  prerelease,
  compare,
  rcompare,
  compareLoose,
  compareBuild,
  sort,
  rsort,
  gt,
  lt,
  eq,
  neq,
  gte,
  lte,
  cmp,
  coerce,
  Comparator,
  Range,
  satisfies,
  toComparators,
  maxSatisfying,
  minSatisfying,
  minVersion,
  validRange,
  outside,
  gtr,
  ltr,
  intersects,
  simplifyRange,
  subset,
  SemVer,
  re: internalRe.re,
  src: internalRe.src,
  tokens: internalRe.t,
  SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION,
  RELEASE_TYPES: constants.RELEASE_TYPES,
  compareIdentifiers: identifiers.compareIdentifiers,
  rcompareIdentifiers: identifiers.rcompareIdentifiers,
}
'use strict'

// Note: this is the semver.org version of the spec that it implements
// Not necessarily the package version of this code.
const SEMVER_SPEC_VERSION = '2.0.0'

const MAX_LENGTH = 256
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
/* istanbul ignore next */ 9007199254740991

// Max safe segment length for coercion.
const MAX_SAFE_COMPONENT_LENGTH = 16

// Max safe length for a build identifier. The max length minus 6 characters for
// the shortest version with a build 0.0.0+BUILD.
const MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6

const RELEASE_TYPES = [
  'major',
  'premajor',
  'minor',
  'preminor',
  'patch',
  'prepatch',
  'prerelease',
]

module.exports = {
  MAX_LENGTH,
  MAX_SAFE_COMPONENT_LENGTH,
  MAX_SAFE_BUILD_LENGTH,
  MAX_SAFE_INTEGER,
  RELEASE_TYPES,
  SEMVER_SPEC_VERSION,
  FLAG_INCLUDE_PRERELEASE: 0b001,
  FLAG_LOOSE: 0b010,
}
'use strict'

const debug = (
  typeof process === 'object' &&
  process.env &&
  process.env.NODE_DEBUG &&
  /\bsemver\b/i.test(process.env.NODE_DEBUG)
) ? (...args) => console.error('SEMVER', ...args)
  : () => {}

module.exports = debug
'use strict'

const numeric = /^[0-9]+$/
const compareIdentifiers = (a, b) => {
  if (typeof a === 'number' && typeof b === 'number') {
    return a === b ? 0 : a < b ? -1 : 1
  }

  const anum = numeric.test(a)
  const bnum = numeric.test(b)

  if (anum && bnum) {
    a = +a
    b = +b
  }

  return a === b ? 0
    : (anum && !bnum) ? -1
    : (bnum && !anum) ? 1
    : a < b ? -1
    : 1
}

const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a)

module.exports = {
  compareIdentifiers,
  rcompareIdentifiers,
}
'use strict'

class LRUCache {
  constructor () {
    this.max = 1000
    this.map = new Map()
  }

  get (key) {
    const value = this.map.get(key)
    if (value === undefined) {
      return undefined
    } else {
      // Remove the key from the map and add it to the end
      this.map.delete(key)
      this.map.set(key, value)
      return value
    }
  }

  delete (key) {
    return this.map.delete(key)
  }

  set (key, value) {
    const deleted = this.delete(key)

    if (!deleted && value !== undefined) {
      // If cache is full, delete the least recently used item
      if (this.map.size >= this.max) {
        const firstKey = this.map.keys().next().value
        this.delete(firstKey)
      }

      this.map.set(key, value)
    }

    return this
  }
}

module.exports = LRUCache
'use strict'

// parse out just the options we care about
const looseOption = Object.freeze({ loose: true })
const emptyOpts = Object.freeze({ })
const parseOptions = options => {
  if (!options) {
    return emptyOpts
  }

  if (typeof options !== 'object') {
    return looseOption
  }

  return options
}
module.exports = parseOptions
'use strict'

const {
  MAX_SAFE_COMPONENT_LENGTH,
  MAX_SAFE_BUILD_LENGTH,
  MAX_LENGTH,
} = require('./constants')
const debug = require('./debug')
exports = module.exports = {}

// The actual regexps go on exports.re
const re = exports.re = []
const safeRe = exports.safeRe = []
const src = exports.src = []
const safeSrc = exports.safeSrc = []
const t = exports.t = {}
let R = 0

const LETTERDASHNUMBER = '[a-zA-Z0-9-]'

// Replace some greedy regex tokens to prevent regex dos issues. These regex are
// used internally via the safeRe object since all inputs in this library get
// normalized first to trim and collapse all extra whitespace. The original
// regexes are exported for userland consumption and lower level usage. A
// future breaking change could export the safer regex only with a note that
// all input should have extra whitespace removed.
const safeRegexReplacements = [
  ['\\s', 1],
  ['\\d', MAX_LENGTH],
  [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH],
]

const makeSafeRegex = (value) => {
  for (const [token, max] of safeRegexReplacements) {
    value = value
      .split(`${token}*`).join(`${token}{0,${max}}`)
      .split(`${token}+`).join(`${token}{1,${max}}`)
  }
  return value
}

const createToken = (name, value, isGlobal) => {
  const safe = makeSafeRegex(value)
  const index = R++
  debug(name, index, value)
  t[name] = index
  src[index] = value
  safeSrc[index] = safe
  re[index] = new RegExp(value, isGlobal ? 'g' : undefined)
  safeRe[index] = new RegExp(safe, isGlobal ? 'g' : undefined)
}

// The following Regular Expressions can be used for tokenizing,
// validating, and parsing SemVer version strings.

// ## Numeric Identifier
// A single `0`, or a non-zero digit followed by zero or more digits.

createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*')
createToken('NUMERICIDENTIFIERLOOSE', '\\d+')

// ## Non-numeric Identifier
// Zero or more digits, followed by a letter or hyphen, and then zero or
// more letters, digits, or hyphens.

createToken('NONNUMERICIDENTIFIER', `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`)

// ## Main Version
// Three dot-separated numeric identifiers.

createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` +
                   `(${src[t.NUMERICIDENTIFIER]})\\.` +
                   `(${src[t.NUMERICIDENTIFIER]})`)

createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
                        `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
                        `(${src[t.NUMERICIDENTIFIERLOOSE]})`)

// ## Pre-release Version Identifier
// A numeric identifier, or a non-numeric identifier.
// Non-numberic identifiers include numberic identifiers but can be longer.
// Therefore non-numberic identifiers must go first.

createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NONNUMERICIDENTIFIER]
}|${src[t.NUMERICIDENTIFIER]})`)

createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NONNUMERICIDENTIFIER]
}|${src[t.NUMERICIDENTIFIERLOOSE]})`)

// ## Pre-release Version
// Hyphen, followed by one or more dot-separated pre-release version
// identifiers.

createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER]
}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`)

createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]
}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`)

// ## Build Metadata Identifier
// Any combination of digits, letters, or hyphens.

createToken('BUILDIDENTIFIER', `${LETTERDASHNUMBER}+`)

// ## Build Metadata
// Plus sign, followed by one or more period-separated build metadata
// identifiers.

createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER]
}(?:\\.${src[t.BUILDIDENTIFIER]})*))`)

// ## Full Version String
// A main version, followed optionally by a pre-release version and
// build metadata.

// Note that the only major, minor, patch, and pre-release sections of
// the version string are capturing groups.  The build metadata is not a
// capturing group, because it should not ever be used in version
// comparison.

createToken('FULLPLAIN', `v?${src[t.MAINVERSION]
}${src[t.PRERELEASE]}?${
  src[t.BUILD]}?`)

createToken('FULL', `^${src[t.FULLPLAIN]}$`)

// like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
// common in the npm registry.
createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE]
}${src[t.PRERELEASELOOSE]}?${
  src[t.BUILD]}?`)

createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`)

createToken('GTLT', '((?:<|>)?=?)')

// Something like "2.*" or "1.2.x".
// Note that "x.x" is a valid xRange identifer, meaning "any version"
// Only the first item is strictly required.
createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`)
createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`)

createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` +
                   `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
                   `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
                   `(?:${src[t.PRERELEASE]})?${
                     src[t.BUILD]}?` +
                   `)?)?`)

createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` +
                        `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
                        `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
                        `(?:${src[t.PRERELEASELOOSE]})?${
                          src[t.BUILD]}?` +
                        `)?)?`)

createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`)
createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`)

// Coercion.
// Extract anything that could conceivably be a part of a valid semver
createToken('COERCEPLAIN', `${'(^|[^\\d])' +
              '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +
              `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
              `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`)
createToken('COERCE', `${src[t.COERCEPLAIN]}(?:$|[^\\d])`)
createToken('COERCEFULL', src[t.COERCEPLAIN] +
              `(?:${src[t.PRERELEASE]})?` +
              `(?:${src[t.BUILD]})?` +
              `(?:$|[^\\d])`)
createToken('COERCERTL', src[t.COERCE], true)
createToken('COERCERTLFULL', src[t.COERCEFULL], true)

// Tilde ranges.
// Meaning is "reasonably at or greater than"
createToken('LONETILDE', '(?:~>?)')

createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true)
exports.tildeTrimReplace = '$1~'

createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`)
createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`)

// Caret ranges.
// Meaning is "at least and backwards compatible with"
createToken('LONECARET', '(?:\\^)')

createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true)
exports.caretTrimReplace = '$1^'

createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`)
createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`)

// A simple gt/lt/eq thing, or just "" to indicate "any version"
createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`)
createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`)

// An expression to strip any whitespace between the gtlt and the thing
// it modifies, so that `> 1.2.3` ==> `>1.2.3`
createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT]
}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true)
exports.comparatorTrimReplace = '$1$2$3'

// Something like `1.2.3 - 1.2.4`
// Note that these all use the loose form, because they'll be
// checked against either the strict or loose comparator form
// later.
createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` +
                   `\\s+-\\s+` +
                   `(${src[t.XRANGEPLAIN]})` +
                   `\\s*$`)

createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` +
                        `\\s+-\\s+` +
                        `(${src[t.XRANGEPLAINLOOSE]})` +
                        `\\s*$`)

// Star ranges basically just allow anything at all.
createToken('STAR', '(<|>)?=?\\s*\\*')
// >=0.0.0 is like a star
createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$')
createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$')
{
  "name": "semver",
  "version": "7.7.3",
  "description": "The semantic version parser used by npm.",
  "main": "index.js",
  "devDependencies": {
    "@npmcli/eslint-config": "^5.0.0",
    "@npmcli/template-oss": "4.25.1",
    "benchmark": "^2.1.4",
    "tap": "^16.0.0"
  },
  "license": "ISC",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/npm/node-semver.git"
  },
  "bin": {
    "semver": "bin/semver.js"
  },
  "files": [
    "bin/",
    "lib/",
    "classes/",
    "functions/",
    "internal/",
    "ranges/",
    "index.js",
    "preload.js",
    "range.bnf"
  ],
  "tap": {
    "timeout": 30,
    "coverage-map": "map.js",
    "nyc-arg": [
      "--exclude",
      "tap-snapshots/**"
    ]
  },
  "engines": {
    "node": ">=10"
  },
  "author": "GitHub Inc.",
  "templateOSS": {
    "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
    "version": "4.25.1",
    "engines": ">=10",
    "distPaths": [
      "classes/",
      "functions/",
      "internal/",
      "ranges/",
      "index.js",
      "preload.js",
      "range.bnf"
    ],
    "allowPaths": [
      "/classes/",
      "/functions/",
      "/internal/",
      "/ranges/",
      "/index.js",
      "/preload.js",
      "/range.bnf",
      "/benchmarks"
    ],
    "publish": "true"
  }
}'use strict'

// XXX remove in v8 or beyond
module.exports = require('./index.js')
range-set  ::= range ( logical-or range ) *
logical-or ::= ( ' ' ) * '||' ( ' ' ) *
range      ::= hyphen | simple ( ' ' simple ) * | ''
hyphen     ::= partial ' - ' partial
simple     ::= primitive | partial | tilde | caret
primitive  ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial
partial    ::= xr ( '.' xr ( '.' xr qualifier ? )? )?
xr         ::= 'x' | 'X' | '*' | nr
nr         ::= '0' | [1-9] ( [0-9] ) *
tilde      ::= '~' partial
caret      ::= '^' partial
qualifier  ::= ( '-' pre )? ( '+' build )?
pre        ::= parts
build      ::= parts
parts      ::= part ( '.' part ) *
part       ::= nr | [-0-9A-Za-z]+
'use strict'

// Determine if version is greater than all the versions possible in the range.
const outside = require('./outside')
const gtr = (version, range, options) => outside(version, range, '>', options)
module.exports = gtr
'use strict'

const Range = require('../classes/range')
const intersects = (r1, r2, options) => {
  r1 = new Range(r1, options)
  r2 = new Range(r2, options)
  return r1.intersects(r2, options)
}
module.exports = intersects
'use strict'

const outside = require('./outside')
// Determine if version is less than all the versions possible in the range
const ltr = (version, range, options) => outside(version, range, '<', options)
module.exports = ltr
'use strict'

const SemVer = require('../classes/semver')
const Range = require('../classes/range')

const maxSatisfying = (versions, range, options) => {
  let max = null
  let maxSV = null
  let rangeObj = null
  try {
    rangeObj = new Range(range, options)
  } catch (er) {
    return null
  }
  versions.forEach((v) => {
    if (rangeObj.test(v)) {
      // satisfies(v, range, options)
      if (!max || maxSV.compare(v) === -1) {
        // compare(max, v, true)
        max = v
        maxSV = new SemVer(max, options)
      }
    }
  })
  return max
}
module.exports = maxSatisfying
'use strict'

const SemVer = require('../classes/semver')
const Range = require('../classes/range')
const minSatisfying = (versions, range, options) => {
  let min = null
  let minSV = null
  let rangeObj = null
  try {
    rangeObj = new Range(range, options)
  } catch (er) {
    return null
  }
  versions.forEach((v) => {
    if (rangeObj.test(v)) {
      // satisfies(v, range, options)
      if (!min || minSV.compare(v) === 1) {
        // compare(min, v, true)
        min = v
        minSV = new SemVer(min, options)
      }
    }
  })
  return min
}
module.exports = minSatisfying
'use strict'

const SemVer = require('../classes/semver')
const Range = require('../classes/range')
const gt = require('../functions/gt')

const minVersion = (range, loose) => {
  range = new Range(range, loose)

  let minver = new SemVer('0.0.0')
  if (range.test(minver)) {
    return minver
  }

  minver = new SemVer('0.0.0-0')
  if (range.test(minver)) {
    return minver
  }

  minver = null
  for (let i = 0; i < range.set.length; ++i) {
    const comparators = range.set[i]

    let setMin = null
    comparators.forEach((comparator) => {
      // Clone to avoid manipulating the comparator's semver object.
      const compver = new SemVer(comparator.semver.version)
      switch (comparator.operator) {
        case '>':
          if (compver.prerelease.length === 0) {
            compver.patch++
          } else {
            compver.prerelease.push(0)
          }
          compver.raw = compver.format()
          /* fallthrough */
        case '':
        case '>=':
          if (!setMin || gt(compver, setMin)) {
            setMin = compver
          }
          break
        case '<':
        case '<=':
          /* Ignore maximum versions */
          break
        /* istanbul ignore next */
        default:
          throw new Error(`Unexpected operation: ${comparator.operator}`)
      }
    })
    if (setMin && (!minver || gt(minver, setMin))) {
      minver = setMin
    }
  }

  if (minver && range.test(minver)) {
    return minver
  }

  return null
}
module.exports = minVersion
'use strict'

const SemVer = require('../classes/semver')
const Comparator = require('../classes/comparator')
const { ANY } = Comparator
const Range = require('../classes/range')
const satisfies = require('../functions/satisfies')
const gt = require('../functions/gt')
const lt = require('../functions/lt')
const lte = require('../functions/lte')
const gte = require('../functions/gte')

const outside = (version, range, hilo, options) => {
  version = new SemVer(version, options)
  range = new Range(range, options)

  let gtfn, ltefn, ltfn, comp, ecomp
  switch (hilo) {
    case '>':
      gtfn = gt
      ltefn = lte
      ltfn = lt
      comp = '>'
      ecomp = '>='
      break
    case '<':
      gtfn = lt
      ltefn = gte
      ltfn = gt
      comp = '<'
      ecomp = '<='
      break
    default:
      throw new TypeError('Must provide a hilo val of "<" or ">"')
  }

  // If it satisfies the range it is not outside
  if (satisfies(version, range, options)) {
    return false
  }

  // From now on, variable terms are as if we're in "gtr" mode.
  // but note that everything is flipped for the "ltr" function.

  for (let i = 0; i < range.set.length; ++i) {
    const comparators = range.set[i]

    let high = null
    let low = null

    comparators.forEach((comparator) => {
      if (comparator.semver === ANY) {
        comparator = new Comparator('>=0.0.0')
      }
      high = high || comparator
      low = low || comparator
      if (gtfn(comparator.semver, high.semver, options)) {
        high = comparator
      } else if (ltfn(comparator.semver, low.semver, options)) {
        low = comparator
      }
    })

    // If the edge version comparator has a operator then our version
    // isn't outside it
    if (high.operator === comp || high.operator === ecomp) {
      return false
    }

    // If the lowest version comparator has an operator and our version
    // is less than it then it isn't higher than the range
    if ((!low.operator || low.operator === comp) &&
        ltefn(version, low.semver)) {
      return false
    } else if (low.operator === ecomp && ltfn(version, low.semver)) {
      return false
    }
  }
  return true
}

module.exports = outside
'use strict'

// given a set of versions and a range, create a "simplified" range
// that includes the same versions that the original range does
// If the original range is shorter than the simplified one, return that.
const satisfies = require('../functions/satisfies.js')
const compare = require('../functions/compare.js')
module.exports = (versions, range, options) => {
  const set = []
  let first = null
  let prev = null
  const v = versions.sort((a, b) => compare(a, b, options))
  for (const version of v) {
    const included = satisfies(version, range, options)
    if (included) {
      prev = version
      if (!first) {
        first = version
      }
    } else {
      if (prev) {
        set.push([first, prev])
      }
      prev = null
      first = null
    }
  }
  if (first) {
    set.push([first, null])
  }

  const ranges = []
  for (const [min, max] of set) {
    if (min === max) {
      ranges.push(min)
    } else if (!max && min === v[0]) {
      ranges.push('*')
    } else if (!max) {
      ranges.push(`>=${min}`)
    } else if (min === v[0]) {
      ranges.push(`<=${max}`)
    } else {
      ranges.push(`${min} - ${max}`)
    }
  }
  const simplified = ranges.join(' || ')
  const original = typeof range.raw === 'string' ? range.raw : String(range)
  return simplified.length < original.length ? simplified : range
}
'use strict'

const Range = require('../classes/range.js')
const Comparator = require('../classes/comparator.js')
const { ANY } = Comparator
const satisfies = require('../functions/satisfies.js')
const compare = require('../functions/compare.js')

// Complex range `r1 || r2 || ...` is a subset of `R1 || R2 || ...` iff:
// - Every simple range `r1, r2, ...` is a null set, OR
// - Every simple range `r1, r2, ...` which is not a null set is a subset of
//   some `R1, R2, ...`
//
// Simple range `c1 c2 ...` is a subset of simple range `C1 C2 ...` iff:
// - If c is only the ANY comparator
//   - If C is only the ANY comparator, return true
//   - Else if in prerelease mode, return false
//   - else replace c with `[>=0.0.0]`
// - If C is only the ANY comparator
//   - if in prerelease mode, return true
//   - else replace C with `[>=0.0.0]`
// - Let EQ be the set of = comparators in c
// - If EQ is more than one, return true (null set)
// - Let GT be the highest > or >= comparator in c
// - Let LT be the lowest < or <= comparator in c
// - If GT and LT, and GT.semver > LT.semver, return true (null set)
// - If any C is a = range, and GT or LT are set, return false
// - If EQ
//   - If GT, and EQ does not satisfy GT, return true (null set)
//   - If LT, and EQ does not satisfy LT, return true (null set)
//   - If EQ satisfies every C, return true
//   - Else return false
// - If GT
//   - If GT.semver is lower than any > or >= comp in C, return false
//   - If GT is >=, and GT.semver does not satisfy every C, return false
//   - If GT.semver has a prerelease, and not in prerelease mode
//     - If no C has a prerelease and the GT.semver tuple, return false
// - If LT
//   - If LT.semver is greater than any < or <= comp in C, return false
//   - If LT is <=, and LT.semver does not satisfy every C, return false
//   - If GT.semver has a prerelease, and not in prerelease mode
//     - If no C has a prerelease and the LT.semver tuple, return false
// - Else return true

const subset = (sub, dom, options = {}) => {
  if (sub === dom) {
    return true
  }

  sub = new Range(sub, options)
  dom = new Range(dom, options)
  let sawNonNull = false

  OUTER: for (const simpleSub of sub.set) {
    for (const simpleDom of dom.set) {
      const isSub = simpleSubset(simpleSub, simpleDom, options)
      sawNonNull = sawNonNull || isSub !== null
      if (isSub) {
        continue OUTER
      }
    }
    // the null set is a subset of everything, but null simple ranges in
    // a complex range should be ignored.  so if we saw a non-null range,
    // then we know this isn't a subset, but if EVERY simple range was null,
    // then it is a subset.
    if (sawNonNull) {
      return false
    }
  }
  return true
}

const minimumVersionWithPreRelease = [new Comparator('>=0.0.0-0')]
const minimumVersion = [new Comparator('>=0.0.0')]

const simpleSubset = (sub, dom, options) => {
  if (sub === dom) {
    return true
  }

  if (sub.length === 1 && sub[0].semver === ANY) {
    if (dom.length === 1 && dom[0].semver === ANY) {
      return true
    } else if (options.includePrerelease) {
      sub = minimumVersionWithPreRelease
    } else {
      sub = minimumVersion
    }
  }

  if (dom.length === 1 && dom[0].semver === ANY) {
    if (options.includePrerelease) {
      return true
    } else {
      dom = minimumVersion
    }
  }

  const eqSet = new Set()
  let gt, lt
  for (const c of sub) {
    if (c.operator === '>' || c.operator === '>=') {
      gt = higherGT(gt, c, options)
    } else if (c.operator === '<' || c.operator === '<=') {
      lt = lowerLT(lt, c, options)
    } else {
      eqSet.add(c.semver)
    }
  }

  if (eqSet.size > 1) {
    return null
  }

  let gtltComp
  if (gt && lt) {
    gtltComp = compare(gt.semver, lt.semver, options)
    if (gtltComp > 0) {
      return null
    } else if (gtltComp === 0 && (gt.operator !== '>=' || lt.operator !== '<=')) {
      return null
    }
  }

  // will iterate one or zero times
  for (const eq of eqSet) {
    if (gt && !satisfies(eq, String(gt), options)) {
      return null
    }

    if (lt && !satisfies(eq, String(lt), options)) {
      return null
    }

    for (const c of dom) {
      if (!satisfies(eq, String(c), options)) {
        return false
      }
    }

    return true
  }

  let higher, lower
  let hasDomLT, hasDomGT
  // if the subset has a prerelease, we need a comparator in the superset
  // with the same tuple and a prerelease, or it's not a subset
  let needDomLTPre = lt &&
    !options.includePrerelease &&
    lt.semver.prerelease.length ? lt.semver : false
  let needDomGTPre = gt &&
    !options.includePrerelease &&
    gt.semver.prerelease.length ? gt.semver : false
  // exception: <1.2.3-0 is the same as <1.2.3
  if (needDomLTPre && needDomLTPre.prerelease.length === 1 &&
      lt.operator === '<' && needDomLTPre.prerelease[0] === 0) {
    needDomLTPre = false
  }

  for (const c of dom) {
    hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>='
    hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<='
    if (gt) {
      if (needDomGTPre) {
        if (c.semver.prerelease && c.semver.prerelease.length &&
            c.semver.major === needDomGTPre.major &&
            c.semver.minor === needDomGTPre.minor &&
            c.semver.patch === needDomGTPre.patch) {
          needDomGTPre = false
        }
      }
      if (c.operator === '>' || c.operator === '>=') {
        higher = higherGT(gt, c, options)
        if (higher === c && higher !== gt) {
          return false
        }
      } else if (gt.operator === '>=' && !satisfies(gt.semver, String(c), options)) {
        return false
      }
    }
    if (lt) {
      if (needDomLTPre) {
        if (c.semver.prerelease && c.semver.prerelease.length &&
            c.semver.major === needDomLTPre.major &&
            c.semver.minor === needDomLTPre.minor &&
            c.semver.patch === needDomLTPre.patch) {
          needDomLTPre = false
        }
      }
      if (c.operator === '<' || c.operator === '<=') {
        lower = lowerLT(lt, c, options)
        if (lower === c && lower !== lt) {
          return false
        }
      } else if (lt.operator === '<=' && !satisfies(lt.semver, String(c), options)) {
        return false
      }
    }
    if (!c.operator && (lt || gt) && gtltComp !== 0) {
      return false
    }
  }

  // if there was a < or >, and nothing in the dom, then must be false
  // UNLESS it was limited by another range in the other direction.
  // Eg, >1.0.0 <1.0.1 is still a subset of <2.0.0
  if (gt && hasDomLT && !lt && gtltComp !== 0) {
    return false
  }

  if (lt && hasDomGT && !gt && gtltComp !== 0) {
    return false
  }

  // we needed a prerelease range in a specific tuple, but didn't get one
  // then this isn't a subset.  eg >=1.2.3-pre is not a subset of >=1.0.0,
  // because it includes prereleases in the 1.2.3 tuple
  if (needDomGTPre || needDomLTPre) {
    return false
  }

  return true
}

// >=1.2.3 is lower than >1.2.3
const higherGT = (a, b, options) => {
  if (!a) {
    return b
  }
  const comp = compare(a.semver, b.semver, options)
  return comp > 0 ? a
    : comp < 0 ? b
    : b.operator === '>' && a.operator === '>=' ? b
    : a
}

// <=1.2.3 is higher than <1.2.3
const lowerLT = (a, b, options) => {
  if (!a) {
    return b
  }
  const comp = compare(a.semver, b.semver, options)
  return comp < 0 ? a
    : comp > 0 ? b
    : b.operator === '<' && a.operator === '<=' ? b
    : a
}

module.exports = subset
'use strict'

const Range = require('../classes/range')

// Mostly just for testing and legacy API reasons
const toComparators = (range, options) =>
  new Range(range, options).set
    .map(comp => comp.map(c => c.value).join(' ').trim().split(' '))

module.exports = toComparators
'use strict'

const Range = require('../classes/range')
const validRange = (range, options) => {
  try {
    // Return '*' instead of '' so that truthiness works.
    // This will throw if it's invalid anyway
    return new Range(range, options).range || '*'
  } catch (er) {
    return null
  }
}
module.exports = validRange
(The MIT License)

Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the 'Software'), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict'

exports.fromCallback = function (fn) {
  return Object.defineProperty(function (...args) {
    if (typeof args[args.length - 1] === 'function') fn.apply(this, args)
    else {
      return new Promise((resolve, reject) => {
        args.push((err, res) => (err != null) ? reject(err) : resolve(res))
        fn.apply(this, args)
      })
    }
  }, 'name', { value: fn.name })
}

exports.fromPromise = function (fn) {
  return Object.defineProperty(function (...args) {
    const cb = args[args.length - 1]
    if (typeof cb !== 'function') return fn.apply(this, args)
    else {
      args.pop()
      fn.apply(this, args).then(r => cb(null, r), cb)
    }
  }, 'name', { value: fn.name })
}
{
  "name": "universalify",
  "version": "2.0.1",
  "description": "Make a callback- or promise-based function support both promises and callbacks.",
  "homepage": "https://github.com/RyanZim/universalify#readme",
  "license": "MIT",
  "author": "Ryan Zimmerman <opensrc@ryanzim.com>",
  "files": [
    "index.js"
  ],
  "repository": {
    "type": "git",
    "url": "git+https://github.com/RyanZim/universalify.git"
  },
  "devDependencies": {
    "colortape": "^0.1.2",
    "coveralls": "^3.0.1",
    "nyc": "^15.0.0",
    "standard": "^14.3.1",
    "tape": "^5.0.1"
  },
  "engines": {
    "node": ">= 10.0.0"
  }
}The ISC License

Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
'use strict'

module.exports = clone

var getPrototypeOf = Object.getPrototypeOf || function (obj) {
  return obj.__proto__
}

function clone (obj) {
  if (obj === null || typeof obj !== 'object')
    return obj

  if (obj instanceof Object)
    var copy = { __proto__: getPrototypeOf(obj) }
  else
    var copy = Object.create(null)

  Object.getOwnPropertyNames(obj).forEach(function (key) {
    Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key))
  })

  return copy
}
var fs = require('fs')
var polyfills = require('./polyfills.js')
var legacy = require('./legacy-streams.js')
var clone = require('./clone.js')

var util = require('util')

/* istanbul ignore next - node 0.x polyfill */
var gracefulQueue
var previousSymbol

/* istanbul ignore else - node 0.x polyfill */
if (typeof Symbol === 'function' && typeof Symbol.for === 'function') {
  gracefulQueue = Symbol.for('graceful-fs.queue')
  // This is used in testing by future versions
  previousSymbol = Symbol.for('graceful-fs.previous')
} else {
  gracefulQueue = '___graceful-fs.queue'
  previousSymbol = '___graceful-fs.previous'
}

function noop () {}

function publishQueue(context, queue) {
  Object.defineProperty(context, gracefulQueue, {
    get: function() {
      return queue
    }
  })
}

var debug = noop
if (util.debuglog)
  debug = util.debuglog('gfs4')
else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || ''))
  debug = function() {
    var m = util.format.apply(util, arguments)
    m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ')
    console.error(m)
  }

// Once time initialization
if (!fs[gracefulQueue]) {
  // This queue can be shared by multiple loaded instances
  var queue = global[gracefulQueue] || []
  publishQueue(fs, queue)

  // Patch fs.close/closeSync to shared queue version, because we need
  // to retry() whenever a close happens *anywhere* in the program.
  // This is essential when multiple graceful-fs instances are
  // in play at the same time.
  fs.close = (function (fs$close) {
    function close (fd, cb) {
      return fs$close.call(fs, fd, function (err) {
        // This function uses the graceful-fs shared queue
        if (!err) {
          resetQueue()
        }

        if (typeof cb === 'function')
          cb.apply(this, arguments)
      })
    }

    Object.defineProperty(close, previousSymbol, {
      value: fs$close
    })
    return close
  })(fs.close)

  fs.closeSync = (function (fs$closeSync) {
    function closeSync (fd) {
      // This function uses the graceful-fs shared queue
      fs$closeSync.apply(fs, arguments)
      resetQueue()
    }

    Object.defineProperty(closeSync, previousSymbol, {
      value: fs$closeSync
    })
    return closeSync
  })(fs.closeSync)

  if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) {
    process.on('exit', function() {
      debug(fs[gracefulQueue])
      require('assert').equal(fs[gracefulQueue].length, 0)
    })
  }
}

if (!global[gracefulQueue]) {
  publishQueue(global, fs[gracefulQueue]);
}

module.exports = patch(clone(fs))
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) {
    module.exports = patch(fs)
    fs.__patched = true;
}

function patch (fs) {
  // Everything that references the open() function needs to be in here
  polyfills(fs)
  fs.gracefulify = patch

  fs.createReadStream = createReadStream
  fs.createWriteStream = createWriteStream
  var fs$readFile = fs.readFile
  fs.readFile = readFile
  function readFile (path, options, cb) {
    if (typeof options === 'function')
      cb = options, options = null

    return go$readFile(path, options, cb)

    function go$readFile (path, options, cb, startTime) {
      return fs$readFile(path, options, function (err) {
        if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
          enqueue([go$readFile, [path, options, cb], err, startTime || Date.now(), Date.now()])
        else {
          if (typeof cb === 'function')
            cb.apply(this, arguments)
        }
      })
    }
  }

  var fs$writeFile = fs.writeFile
  fs.writeFile = writeFile
  function writeFile (path, data, options, cb) {
    if (typeof options === 'function')
      cb = options, options = null

    return go$writeFile(path, data, options, cb)

    function go$writeFile (path, data, options, cb, startTime) {
      return fs$writeFile(path, data, options, function (err) {
        if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
          enqueue([go$writeFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()])
        else {
          if (typeof cb === 'function')
            cb.apply(this, arguments)
        }
      })
    }
  }

  var fs$appendFile = fs.appendFile
  if (fs$appendFile)
    fs.appendFile = appendFile
  function appendFile (path, data, options, cb) {
    if (typeof options === 'function')
      cb = options, options = null

    return go$appendFile(path, data, options, cb)

    function go$appendFile (path, data, options, cb, startTime) {
      return fs$appendFile(path, data, options, function (err) {
        if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
          enqueue([go$appendFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()])
        else {
          if (typeof cb === 'function')
            cb.apply(this, arguments)
        }
      })
    }
  }

  var fs$copyFile = fs.copyFile
  if (fs$copyFile)
    fs.copyFile = copyFile
  function copyFile (src, dest, flags, cb) {
    if (typeof flags === 'function') {
      cb = flags
      flags = 0
    }
    return go$copyFile(src, dest, flags, cb)

    function go$copyFile (src, dest, flags, cb, startTime) {
      return fs$copyFile(src, dest, flags, function (err) {
        if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
          enqueue([go$copyFile, [src, dest, flags, cb], err, startTime || Date.now(), Date.now()])
        else {
          if (typeof cb === 'function')
            cb.apply(this, arguments)
        }
      })
    }
  }

  var fs$readdir = fs.readdir
  fs.readdir = readdir
  var noReaddirOptionVersions = /^v[0-5]\./
  function readdir (path, options, cb) {
    if (typeof options === 'function')
      cb = options, options = null

    var go$readdir = noReaddirOptionVersions.test(process.version)
      ? function go$readdir (path, options, cb, startTime) {
        return fs$readdir(path, fs$readdirCallback(
          path, options, cb, startTime
        ))
      }
      : function go$readdir (path, options, cb, startTime) {
        return fs$readdir(path, options, fs$readdirCallback(
          path, options, cb, startTime
        ))
      }

    return go$readdir(path, options, cb)

    function fs$readdirCallback (path, options, cb, startTime) {
      return function (err, files) {
        if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
          enqueue([
            go$readdir,
            [path, options, cb],
            err,
            startTime || Date.now(),
            Date.now()
          ])
        else {
          if (files && files.sort)
            files.sort()

          if (typeof cb === 'function')
            cb.call(this, err, files)
        }
      }
    }
  }

  if (process.version.substr(0, 4) === 'v0.8') {
    var legStreams = legacy(fs)
    ReadStream = legStreams.ReadStream
    WriteStream = legStreams.WriteStream
  }

  var fs$ReadStream = fs.ReadStream
  if (fs$ReadStream) {
    ReadStream.prototype = Object.create(fs$ReadStream.prototype)
    ReadStream.prototype.open = ReadStream$open
  }

  var fs$WriteStream = fs.WriteStream
  if (fs$WriteStream) {
    WriteStream.prototype = Object.create(fs$WriteStream.prototype)
    WriteStream.prototype.open = WriteStream$open
  }

  Object.defineProperty(fs, 'ReadStream', {
    get: function () {
      return ReadStream
    },
    set: function (val) {
      ReadStream = val
    },
    enumerable: true,
    configurable: true
  })
  Object.defineProperty(fs, 'WriteStream', {
    get: function () {
      return WriteStream
    },
    set: function (val) {
      WriteStream = val
    },
    enumerable: true,
    configurable: true
  })

  // legacy names
  var FileReadStream = ReadStream
  Object.defineProperty(fs, 'FileReadStream', {
    get: function () {
      return FileReadStream
    },
    set: function (val) {
      FileReadStream = val
    },
    enumerable: true,
    configurable: true
  })
  var FileWriteStream = WriteStream
  Object.defineProperty(fs, 'FileWriteStream', {
    get: function () {
      return FileWriteStream
    },
    set: function (val) {
      FileWriteStream = val
    },
    enumerable: true,
    configurable: true
  })

  function ReadStream (path, options) {
    if (this instanceof ReadStream)
      return fs$ReadStream.apply(this, arguments), this
    else
      return ReadStream.apply(Object.create(ReadStream.prototype), arguments)
  }

  function ReadStream$open () {
    var that = this
    open(that.path, that.flags, that.mode, function (err, fd) {
      if (err) {
        if (that.autoClose)
          that.destroy()

        that.emit('error', err)
      } else {
        that.fd = fd
        that.emit('open', fd)
        that.read()
      }
    })
  }

  function WriteStream (path, options) {
    if (this instanceof WriteStream)
      return fs$WriteStream.apply(this, arguments), this
    else
      return WriteStream.apply(Object.create(WriteStream.prototype), arguments)
  }

  function WriteStream$open () {
    var that = this
    open(that.path, that.flags, that.mode, function (err, fd) {
      if (err) {
        that.destroy()
        that.emit('error', err)
      } else {
        that.fd = fd
        that.emit('open', fd)
      }
    })
  }

  function createReadStream (path, options) {
    return new fs.ReadStream(path, options)
  }

  function createWriteStream (path, options) {
    return new fs.WriteStream(path, options)
  }

  var fs$open = fs.open
  fs.open = open
  function open (path, flags, mode, cb) {
    if (typeof mode === 'function')
      cb = mode, mode = null

    return go$open(path, flags, mode, cb)

    function go$open (path, flags, mode, cb, startTime) {
      return fs$open(path, flags, mode, function (err, fd) {
        if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
          enqueue([go$open, [path, flags, mode, cb], err, startTime || Date.now(), Date.now()])
        else {
          if (typeof cb === 'function')
            cb.apply(this, arguments)
        }
      })
    }
  }

  return fs
}

function enqueue (elem) {
  debug('ENQUEUE', elem[0].name, elem[1])
  fs[gracefulQueue].push(elem)
  retry()
}

// keep track of the timeout between retry() calls
var retryTimer

// reset the startTime and lastTime to now
// this resets the start of the 60 second overall timeout as well as the
// delay between attempts so that we'll retry these jobs sooner
function resetQueue () {
  var now = Date.now()
  for (var i = 0; i < fs[gracefulQueue].length; ++i) {
    // entries that are only a length of 2 are from an older version, don't
    // bother modifying those since they'll be retried anyway.
    if (fs[gracefulQueue][i].length > 2) {
      fs[gracefulQueue][i][3] = now // startTime
      fs[gracefulQueue][i][4] = now // lastTime
    }
  }
  // call retry to make sure we're actively processing the queue
  retry()
}

function retry () {
  // clear the timer and remove it to help prevent unintended concurrency
  clearTimeout(retryTimer)
  retryTimer = undefined

  if (fs[gracefulQueue].length === 0)
    return

  var elem = fs[gracefulQueue].shift()
  var fn = elem[0]
  var args = elem[1]
  // these items may be unset if they were added by an older graceful-fs
  var err = elem[2]
  var startTime = elem[3]
  var lastTime = elem[4]

  // if we don't have a startTime we have no way of knowing if we've waited
  // long enough, so go ahead and retry this item now
  if (startTime === undefined) {
    debug('RETRY', fn.name, args)
    fn.apply(null, args)
  } else if (Date.now() - startTime >= 60000) {
    // it's been more than 60 seconds total, bail now
    debug('TIMEOUT', fn.name, args)
    var cb = args.pop()
    if (typeof cb === 'function')
      cb.call(null, err)
  } else {
    // the amount of time between the last attempt and right now
    var sinceAttempt = Date.now() - lastTime
    // the amount of time between when we first tried, and when we last tried
    // rounded up to at least 1
    var sinceStart = Math.max(lastTime - startTime, 1)
    // backoff. wait longer than the total time we've been retrying, but only
    // up to a maximum of 100ms
    var desiredDelay = Math.min(sinceStart * 1.2, 100)
    // it's been long enough since the last retry, do it again
    if (sinceAttempt >= desiredDelay) {
      debug('RETRY', fn.name, args)
      fn.apply(null, args.concat([startTime]))
    } else {
      // if we can't do this job yet, push it to the end of the queue
      // and let the next iteration check again
      fs[gracefulQueue].push(elem)
    }
  }

  // schedule our next run if one isn't already scheduled
  if (retryTimer === undefined) {
    retryTimer = setTimeout(retry, 0)
  }
}
var Stream = require('stream').Stream

module.exports = legacy

function legacy (fs) {
  return {
    ReadStream: ReadStream,
    WriteStream: WriteStream
  }

  function ReadStream (path, options) {
    if (!(this instanceof ReadStream)) return new ReadStream(path, options);

    Stream.call(this);

    var self = this;

    this.path = path;
    this.fd = null;
    this.readable = true;
    this.paused = false;

    this.flags = 'r';
    this.mode = 438; /*=0666*/
    this.bufferSize = 64 * 1024;

    options = options || {};

    // Mixin options into this
    var keys = Object.keys(options);
    for (var index = 0, length = keys.length; index < length; index++) {
      var key = keys[index];
      this[key] = options[key];
    }

    if (this.encoding) this.setEncoding(this.encoding);

    if (this.start !== undefined) {
      if ('number' !== typeof this.start) {
        throw TypeError('start must be a Number');
      }
      if (this.end === undefined) {
        this.end = Infinity;
      } else if ('number' !== typeof this.end) {
        throw TypeError('end must be a Number');
      }

      if (this.start > this.end) {
        throw new Error('start must be <= end');
      }

      this.pos = this.start;
    }

    if (this.fd !== null) {
      process.nextTick(function() {
        self._read();
      });
      return;
    }

    fs.open(this.path, this.flags, this.mode, function (err, fd) {
      if (err) {
        self.emit('error', err);
        self.readable = false;
        return;
      }

      self.fd = fd;
      self.emit('open', fd);
      self._read();
    })
  }

  function WriteStream (path, options) {
    if (!(this instanceof WriteStream)) return new WriteStream(path, options);

    Stream.call(this);

    this.path = path;
    this.fd = null;
    this.writable = true;

    this.flags = 'w';
    this.encoding = 'binary';
    this.mode = 438; /*=0666*/
    this.bytesWritten = 0;

    options = options || {};

    // Mixin options into this
    var keys = Object.keys(options);
    for (var index = 0, length = keys.length; index < length; index++) {
      var key = keys[index];
      this[key] = options[key];
    }

    if (this.start !== undefined) {
      if ('number' !== typeof this.start) {
        throw TypeError('start must be a Number');
      }
      if (this.start < 0) {
        throw new Error('start must be >= zero');
      }

      this.pos = this.start;
    }

    this.busy = false;
    this._queue = [];

    if (this.fd === null) {
      this._open = fs.open;
      this._queue.push([this._open, this.path, this.flags, this.mode, undefined]);
      this.flush();
    }
  }
}
{
  "name": "graceful-fs",
  "description": "A drop-in replacement for fs, making various improvements.",
  "version": "4.2.11",
  "repository": {
    "type": "git",
    "url": "https://github.com/isaacs/node-graceful-fs"
  },
  "main": "graceful-fs.js",
  "directories": {
    "test": "test"
  },
  "license": "ISC",
  "devDependencies": {
    "import-fresh": "^2.0.0",
    "mkdirp": "^0.5.0",
    "rimraf": "^2.2.8",
    "tap": "^16.3.4"
  },
  "files": [
    "fs.js",
    "graceful-fs.js",
    "legacy-streams.js",
    "polyfills.js",
    "clone.js"
  ],
  "tap": {
    "reporter": "classic"
  }
}var constants = require('constants')

var origCwd = process.cwd
var cwd = null

var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform

process.cwd = function() {
  if (!cwd)
    cwd = origCwd.call(process)
  return cwd
}
try {
  process.cwd()
} catch (er) {}

// This check is needed until node.js 12 is required
if (typeof process.chdir === 'function') {
  var chdir = process.chdir
  process.chdir = function (d) {
    cwd = null
    chdir.call(process, d)
  }
  if (Object.setPrototypeOf) Object.setPrototypeOf(process.chdir, chdir)
}

module.exports = patch

function patch (fs) {
  // (re-)implement some things that are known busted or missing.

  // lchmod, broken prior to 0.6.2
  // back-port the fix here.
  if (constants.hasOwnProperty('O_SYMLINK') &&
      process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
    patchLchmod(fs)
  }

  // lutimes implementation, or no-op
  if (!fs.lutimes) {
    patchLutimes(fs)
  }

  // https://github.com/isaacs/node-graceful-fs/issues/4
  // Chown should not fail on einval or eperm if non-root.
  // It should not fail on enosys ever, as this just indicates
  // that a fs doesn't support the intended operation.

  fs.chown = chownFix(fs.chown)
  fs.fchown = chownFix(fs.fchown)
  fs.lchown = chownFix(fs.lchown)

  fs.chmod = chmodFix(fs.chmod)
  fs.fchmod = chmodFix(fs.fchmod)
  fs.lchmod = chmodFix(fs.lchmod)

  fs.chownSync = chownFixSync(fs.chownSync)
  fs.fchownSync = chownFixSync(fs.fchownSync)
  fs.lchownSync = chownFixSync(fs.lchownSync)

  fs.chmodSync = chmodFixSync(fs.chmodSync)
  fs.fchmodSync = chmodFixSync(fs.fchmodSync)
  fs.lchmodSync = chmodFixSync(fs.lchmodSync)

  fs.stat = statFix(fs.stat)
  fs.fstat = statFix(fs.fstat)
  fs.lstat = statFix(fs.lstat)

  fs.statSync = statFixSync(fs.statSync)
  fs.fstatSync = statFixSync(fs.fstatSync)
  fs.lstatSync = statFixSync(fs.lstatSync)

  // if lchmod/lchown do not exist, then make them no-ops
  if (fs.chmod && !fs.lchmod) {
    fs.lchmod = function (path, mode, cb) {
      if (cb) process.nextTick(cb)
    }
    fs.lchmodSync = function () {}
  }
  if (fs.chown && !fs.lchown) {
    fs.lchown = function (path, uid, gid, cb) {
      if (cb) process.nextTick(cb)
    }
    fs.lchownSync = function () {}
  }

  // on Windows, A/V software can lock the directory, causing this
  // to fail with an EACCES or EPERM if the directory contains newly
  // created files.  Try again on failure, for up to 60 seconds.

  // Set the timeout this long because some Windows Anti-Virus, such as Parity
  // bit9, may lock files for up to a minute, causing npm package install
  // failures. Also, take care to yield the scheduler. Windows scheduling gives
  // CPU to a busy looping process, which can cause the program causing the lock
  // contention to be starved of CPU by node, so the contention doesn't resolve.
  if (platform === "win32") {
    fs.rename = typeof fs.rename !== 'function' ? fs.rename
    : (function (fs$rename) {
      function rename (from, to, cb) {
        var start = Date.now()
        var backoff = 0;
        fs$rename(from, to, function CB (er) {
          if (er
              && (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY")
              && Date.now() - start < 60000) {
            setTimeout(function() {
              fs.stat(to, function (stater, st) {
                if (stater && stater.code === "ENOENT")
                  fs$rename(from, to, CB);
                else
                  cb(er)
              })
            }, backoff)
            if (backoff < 100)
              backoff += 10;
            return;
          }
          if (cb) cb(er)
        })
      }
      if (Object.setPrototypeOf) Object.setPrototypeOf(rename, fs$rename)
      return rename
    })(fs.rename)
  }

  // if read() returns EAGAIN, then just try it again.
  fs.read = typeof fs.read !== 'function' ? fs.read
  : (function (fs$read) {
    function read (fd, buffer, offset, length, position, callback_) {
      var callback
      if (callback_ && typeof callback_ === 'function') {
        var eagCounter = 0
        callback = function (er, _, __) {
          if (er && er.code === 'EAGAIN' && eagCounter < 10) {
            eagCounter ++
            return fs$read.call(fs, fd, buffer, offset, length, position, callback)
          }
          callback_.apply(this, arguments)
        }
      }
      return fs$read.call(fs, fd, buffer, offset, length, position, callback)
    }

    // This ensures `util.promisify` works as it does for native `fs.read`.
    if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read)
    return read
  })(fs.read)

  fs.readSync = typeof fs.readSync !== 'function' ? fs.readSync
  : (function (fs$readSync) { return function (fd, buffer, offset, length, position) {
    var eagCounter = 0
    while (true) {
      try {
        return fs$readSync.call(fs, fd, buffer, offset, length, position)
      } catch (er) {
        if (er.code === 'EAGAIN' && eagCounter < 10) {
          eagCounter ++
          continue
        }
        throw er
      }
    }
  }})(fs.readSync)

  function patchLchmod (fs) {
    fs.lchmod = function (path, mode, callback) {
      fs.open( path
             , constants.O_WRONLY | constants.O_SYMLINK
             , mode
             , function (err, fd) {
        if (err) {
          if (callback) callback(err)
          return
        }
        // prefer to return the chmod error, if one occurs,
        // but still try to close, and report closing errors if they occur.
        fs.fchmod(fd, mode, function (err) {
          fs.close(fd, function(err2) {
            if (callback) callback(err || err2)
          })
        })
      })
    }

    fs.lchmodSync = function (path, mode) {
      var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)

      // prefer to return the chmod error, if one occurs,
      // but still try to close, and report closing errors if they occur.
      var threw = true
      var ret
      try {
        ret = fs.fchmodSync(fd, mode)
        threw = false
      } finally {
        if (threw) {
          try {
            fs.closeSync(fd)
          } catch (er) {}
        } else {
          fs.closeSync(fd)
        }
      }
      return ret
    }
  }

  function patchLutimes (fs) {
    if (constants.hasOwnProperty("O_SYMLINK") && fs.futimes) {
      fs.lutimes = function (path, at, mt, cb) {
        fs.open(path, constants.O_SYMLINK, function (er, fd) {
          if (er) {
            if (cb) cb(er)
            return
          }
          fs.futimes(fd, at, mt, function (er) {
            fs.close(fd, function (er2) {
              if (cb) cb(er || er2)
            })
          })
        })
      }

      fs.lutimesSync = function (path, at, mt) {
        var fd = fs.openSync(path, constants.O_SYMLINK)
        var ret
        var threw = true
        try {
          ret = fs.futimesSync(fd, at, mt)
          threw = false
        } finally {
          if (threw) {
            try {
              fs.closeSync(fd)
            } catch (er) {}
          } else {
            fs.closeSync(fd)
          }
        }
        return ret
      }

    } else if (fs.futimes) {
      fs.lutimes = function (_a, _b, _c, cb) { if (cb) process.nextTick(cb) }
      fs.lutimesSync = function () {}
    }
  }

  function chmodFix (orig) {
    if (!orig) return orig
    return function (target, mode, cb) {
      return orig.call(fs, target, mode, function (er) {
        if (chownErOk(er)) er = null
        if (cb) cb.apply(this, arguments)
      })
    }
  }

  function chmodFixSync (orig) {
    if (!orig) return orig
    return function (target, mode) {
      try {
        return orig.call(fs, target, mode)
      } catch (er) {
        if (!chownErOk(er)) throw er
      }
    }
  }


  function chownFix (orig) {
    if (!orig) return orig
    return function (target, uid, gid, cb) {
      return orig.call(fs, target, uid, gid, function (er) {
        if (chownErOk(er)) er = null
        if (cb) cb.apply(this, arguments)
      })
    }
  }

  function chownFixSync (orig) {
    if (!orig) return orig
    return function (target, uid, gid) {
      try {
        return orig.call(fs, target, uid, gid)
      } catch (er) {
        if (!chownErOk(er)) throw er
      }
    }
  }

  function statFix (orig) {
    if (!orig) return orig
    // Older versions of Node erroneously returned signed integers for
    // uid + gid.
    return function (target, options, cb) {
      if (typeof options === 'function') {
        cb = options
        options = null
      }
      function callback (er, stats) {
        if (stats) {
          if (stats.uid < 0) stats.uid += 0x100000000
          if (stats.gid < 0) stats.gid += 0x100000000
        }
        if (cb) cb.apply(this, arguments)
      }
      return options ? orig.call(fs, target, options, callback)
        : orig.call(fs, target, callback)
    }
  }

  function statFixSync (orig) {
    if (!orig) return orig
    // Older versions of Node erroneously returned signed integers for
    // uid + gid.
    return function (target, options) {
      var stats = options ? orig.call(fs, target, options)
        : orig.call(fs, target)
      if (stats) {
        if (stats.uid < 0) stats.uid += 0x100000000
        if (stats.gid < 0) stats.gid += 0x100000000
      }
      return stats;
    }
  }

  // ENOSYS means that the fs doesn't support the op. Just ignore
  // that, because it doesn't matter.
  //
  // if there's no getuid, or if getuid() is something other
  // than 0, and the error is EINVAL or EPERM, then just ignore
  // it.
  //
  // This specific case is a silent failure in cp, install, tar,
  // and most other unix tools that manage permissions.
  //
  // When running as root, or if other types of errors are
  // encountered, then it's strict.
  function chownErOk (er) {
    if (!er)
      return true

    if (er.code === "ENOSYS")
      return true

    var nonroot = !process.getuid || process.getuid() !== 0
    if (nonroot) {
      if (er.code === "EINVAL" || er.code === "EPERM")
        return true
    }

    return false
  }
}
(The MIT License)

Copyright (C) 2011-2015 by Vitaly Puzrin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
#!/usr/bin/env node


'use strict';

/*eslint-disable no-console*/


var fs       = require('fs');
var argparse = require('argparse');
var yaml     = require('..');


////////////////////////////////////////////////////////////////////////////////


var cli = new argparse.ArgumentParser({
  prog:     'js-yaml',
  add_help:  true
});

cli.add_argument('-v', '--version', {
  action: 'version',
  version: require('../package.json').version
});

cli.add_argument('-c', '--compact', {
  help:   'Display errors in compact mode',
  action: 'store_true'
});

// deprecated (not needed after we removed output colors)
// option suppressed, but not completely removed for compatibility
cli.add_argument('-j', '--to-json', {
  help:   argparse.SUPPRESS,
  dest:   'json',
  action: 'store_true'
});

cli.add_argument('-t', '--trace', {
  help:   'Show stack trace on error',
  action: 'store_true'
});

cli.add_argument('file', {
  help:   'File to read, utf-8 encoded without BOM',
  nargs:  '?',
  default: '-'
});


////////////////////////////////////////////////////////////////////////////////


var options = cli.parse_args();


////////////////////////////////////////////////////////////////////////////////

function readFile(filename, encoding, callback) {
  if (options.file === '-') {
    // read from stdin

    var chunks = [];

    process.stdin.on('data', function (chunk) {
      chunks.push(chunk);
    });

    process.stdin.on('end', function () {
      return callback(null, Buffer.concat(chunks).toString(encoding));
    });
  } else {
    fs.readFile(filename, encoding, callback);
  }
}

readFile(options.file, 'utf8', function (error, input) {
  var output, isYaml;

  if (error) {
    if (error.code === 'ENOENT') {
      console.error('File not found: ' + options.file);
      process.exit(2);
    }

    console.error(
      options.trace && error.stack ||
      error.message ||
      String(error));

    process.exit(1);
  }

  try {
    output = JSON.parse(input);
    isYaml = false;
  } catch (err) {
    if (err instanceof SyntaxError) {
      try {
        output = [];
        yaml.loadAll(input, function (doc) { output.push(doc); }, {});
        isYaml = true;

        if (output.length === 0) output = null;
        else if (output.length === 1) output = output[0];

      } catch (e) {
        if (options.trace && err.stack) console.error(e.stack);
        else console.error(e.toString(options.compact));

        process.exit(1);
      }
    } else {
      console.error(
        options.trace && err.stack ||
        err.message ||
        String(err));

      process.exit(1);
    }
  }

  if (isYaml) console.log(JSON.stringify(output, null, '  '));
  else console.log(yaml.dump(output));
});

/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.jsyaml = {}));
}(this, (function (exports) { 'use strict';

  function isNothing(subject) {
    return (typeof subject === 'undefined') || (subject === null);
  }


  function isObject(subject) {
    return (typeof subject === 'object') && (subject !== null);
  }


  function toArray(sequence) {
    if (Array.isArray(sequence)) return sequence;
    else if (isNothing(sequence)) return [];

    return [ sequence ];
  }


  function extend(target, source) {
    var index, length, key, sourceKeys;

    if (source) {
      sourceKeys = Object.keys(source);

      for (index = 0, length = sourceKeys.length; index < length; index += 1) {
        key = sourceKeys[index];
        target[key] = source[key];
      }
    }

    return target;
  }


  function repeat(string, count) {
    var result = '', cycle;

    for (cycle = 0; cycle < count; cycle += 1) {
      result += string;
    }

    return result;
  }


  function isNegativeZero(number) {
    return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number);
  }


  var isNothing_1      = isNothing;
  var isObject_1       = isObject;
  var toArray_1        = toArray;
  var repeat_1         = repeat;
  var isNegativeZero_1 = isNegativeZero;
  var extend_1         = extend;

  var common = {
  	isNothing: isNothing_1,
  	isObject: isObject_1,
  	toArray: toArray_1,
  	repeat: repeat_1,
  	isNegativeZero: isNegativeZero_1,
  	extend: extend_1
  };

  // YAML error class. http://stackoverflow.com/questions/8458984


  function formatError(exception, compact) {
    var where = '', message = exception.reason || '(unknown reason)';

    if (!exception.mark) return message;

    if (exception.mark.name) {
      where += 'in "' + exception.mark.name + '" ';
    }

    where += '(' + (exception.mark.line + 1) + ':' + (exception.mark.column + 1) + ')';

    if (!compact && exception.mark.snippet) {
      where += '\n\n' + exception.mark.snippet;
    }

    return message + ' ' + where;
  }


  function YAMLException$1(reason, mark) {
    // Super constructor
    Error.call(this);

    this.name = 'YAMLException';
    this.reason = reason;
    this.mark = mark;
    this.message = formatError(this, false);

    // Include stack trace in error object
    if (Error.captureStackTrace) {
      // Chrome and NodeJS
      Error.captureStackTrace(this, this.constructor);
    } else {
      // FF, IE 10+ and Safari 6+. Fallback for others
      this.stack = (new Error()).stack || '';
    }
  }


  // Inherit from Error
  YAMLException$1.prototype = Object.create(Error.prototype);
  YAMLException$1.prototype.constructor = YAMLException$1;


  YAMLException$1.prototype.toString = function toString(compact) {
    return this.name + ': ' + formatError(this, compact);
  };


  var exception = YAMLException$1;

  // get snippet for a single line, respecting maxLength
  function getLine(buffer, lineStart, lineEnd, position, maxLineLength) {
    var head = '';
    var tail = '';
    var maxHalfLength = Math.floor(maxLineLength / 2) - 1;

    if (position - lineStart > maxHalfLength) {
      head = ' ... ';
      lineStart = position - maxHalfLength + head.length;
    }

    if (lineEnd - position > maxHalfLength) {
      tail = ' ...';
      lineEnd = position + maxHalfLength - tail.length;
    }

    return {
      str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, '→') + tail,
      pos: position - lineStart + head.length // relative position
    };
  }


  function padStart(string, max) {
    return common.repeat(' ', max - string.length) + string;
  }


  function makeSnippet(mark, options) {
    options = Object.create(options || null);

    if (!mark.buffer) return null;

    if (!options.maxLength) options.maxLength = 79;
    if (typeof options.indent      !== 'number') options.indent      = 1;
    if (typeof options.linesBefore !== 'number') options.linesBefore = 3;
    if (typeof options.linesAfter  !== 'number') options.linesAfter  = 2;

    var re = /\r?\n|\r|\0/g;
    var lineStarts = [ 0 ];
    var lineEnds = [];
    var match;
    var foundLineNo = -1;

    while ((match = re.exec(mark.buffer))) {
      lineEnds.push(match.index);
      lineStarts.push(match.index + match[0].length);

      if (mark.position <= match.index && foundLineNo < 0) {
        foundLineNo = lineStarts.length - 2;
      }
    }

    if (foundLineNo < 0) foundLineNo = lineStarts.length - 1;

    var result = '', i, line;
    var lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length;
    var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3);

    for (i = 1; i <= options.linesBefore; i++) {
      if (foundLineNo - i < 0) break;
      line = getLine(
        mark.buffer,
        lineStarts[foundLineNo - i],
        lineEnds[foundLineNo - i],
        mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),
        maxLineLength
      );
      result = common.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) +
        ' | ' + line.str + '\n' + result;
    }

    line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength);
    result += common.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) +
      ' | ' + line.str + '\n';
    result += common.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\n';

    for (i = 1; i <= options.linesAfter; i++) {
      if (foundLineNo + i >= lineEnds.length) break;
      line = getLine(
        mark.buffer,
        lineStarts[foundLineNo + i],
        lineEnds[foundLineNo + i],
        mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),
        maxLineLength
      );
      result += common.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) +
        ' | ' + line.str + '\n';
    }

    return result.replace(/\n$/, '');
  }


  var snippet = makeSnippet;

  var TYPE_CONSTRUCTOR_OPTIONS = [
    'kind',
    'multi',
    'resolve',
    'construct',
    'instanceOf',
    'predicate',
    'represent',
    'representName',
    'defaultStyle',
    'styleAliases'
  ];

  var YAML_NODE_KINDS = [
    'scalar',
    'sequence',
    'mapping'
  ];

  function compileStyleAliases(map) {
    var result = {};

    if (map !== null) {
      Object.keys(map).forEach(function (style) {
        map[style].forEach(function (alias) {
          result[String(alias)] = style;
        });
      });
    }

    return result;
  }

  function Type$1(tag, options) {
    options = options || {};

    Object.keys(options).forEach(function (name) {
      if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {
        throw new exception('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.');
      }
    });

    // TODO: Add tag format check.
    this.options       = options; // keep original options in case user wants to extend this type later
    this.tag           = tag;
    this.kind          = options['kind']          || null;
    this.resolve       = options['resolve']       || function () { return true; };
    this.construct     = options['construct']     || function (data) { return data; };
    this.instanceOf    = options['instanceOf']    || null;
    this.predicate     = options['predicate']     || null;
    this.represent     = options['represent']     || null;
    this.representName = options['representName'] || null;
    this.defaultStyle  = options['defaultStyle']  || null;
    this.multi         = options['multi']         || false;
    this.styleAliases  = compileStyleAliases(options['styleAliases'] || null);

    if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {
      throw new exception('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.');
    }
  }

  var type = Type$1;

  /*eslint-disable max-len*/





  function compileList(schema, name) {
    var result = [];

    schema[name].forEach(function (currentType) {
      var newIndex = result.length;

      result.forEach(function (previousType, previousIndex) {
        if (previousType.tag === currentType.tag &&
            previousType.kind === currentType.kind &&
            previousType.multi === currentType.multi) {

          newIndex = previousIndex;
        }
      });

      result[newIndex] = currentType;
    });

    return result;
  }


  function compileMap(/* lists... */) {
    var result = {
          scalar: {},
          sequence: {},
          mapping: {},
          fallback: {},
          multi: {
            scalar: [],
            sequence: [],
            mapping: [],
            fallback: []
          }
        }, index, length;

    function collectType(type) {
      if (type.multi) {
        result.multi[type.kind].push(type);
        result.multi['fallback'].push(type);
      } else {
        result[type.kind][type.tag] = result['fallback'][type.tag] = type;
      }
    }

    for (index = 0, length = arguments.length; index < length; index += 1) {
      arguments[index].forEach(collectType);
    }
    return result;
  }


  function Schema$1(definition) {
    return this.extend(definition);
  }


  Schema$1.prototype.extend = function extend(definition) {
    var implicit = [];
    var explicit = [];

    if (definition instanceof type) {
      // Schema.extend(type)
      explicit.push(definition);

    } else if (Array.isArray(definition)) {
      // Schema.extend([ type1, type2, ... ])
      explicit = explicit.concat(definition);

    } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) {
      // Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] })
      if (definition.implicit) implicit = implicit.concat(definition.implicit);
      if (definition.explicit) explicit = explicit.concat(definition.explicit);

    } else {
      throw new exception('Schema.extend argument should be a Type, [ Type ], ' +
        'or a schema definition ({ implicit: [...], explicit: [...] })');
    }

    implicit.forEach(function (type$1) {
      if (!(type$1 instanceof type)) {
        throw new exception('Specified list of YAML types (or a single Type object) contains a non-Type object.');
      }

      if (type$1.loadKind && type$1.loadKind !== 'scalar') {
        throw new exception('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.');
      }

      if (type$1.multi) {
        throw new exception('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.');
      }
    });

    explicit.forEach(function (type$1) {
      if (!(type$1 instanceof type)) {
        throw new exception('Specified list of YAML types (or a single Type object) contains a non-Type object.');
      }
    });

    var result = Object.create(Schema$1.prototype);

    result.implicit = (this.implicit || []).concat(implicit);
    result.explicit = (this.explicit || []).concat(explicit);

    result.compiledImplicit = compileList(result, 'implicit');
    result.compiledExplicit = compileList(result, 'explicit');
    result.compiledTypeMap  = compileMap(result.compiledImplicit, result.compiledExplicit);

    return result;
  };


  var schema = Schema$1;

  var str = new type('tag:yaml.org,2002:str', {
    kind: 'scalar',
    construct: function (data) { return data !== null ? data : ''; }
  });

  var seq = new type('tag:yaml.org,2002:seq', {
    kind: 'sequence',
    construct: function (data) { return data !== null ? data : []; }
  });

  var map = new type('tag:yaml.org,2002:map', {
    kind: 'mapping',
    construct: function (data) { return data !== null ? data : {}; }
  });

  var failsafe = new schema({
    explicit: [
      str,
      seq,
      map
    ]
  });

  function resolveYamlNull(data) {
    if (data === null) return true;

    var max = data.length;

    return (max === 1 && data === '~') ||
           (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'));
  }

  function constructYamlNull() {
    return null;
  }

  function isNull(object) {
    return object === null;
  }

  var _null = new type('tag:yaml.org,2002:null', {
    kind: 'scalar',
    resolve: resolveYamlNull,
    construct: constructYamlNull,
    predicate: isNull,
    represent: {
      canonical: function () { return '~';    },
      lowercase: function () { return 'null'; },
      uppercase: function () { return 'NULL'; },
      camelcase: function () { return 'Null'; },
      empty:     function () { return '';     }
    },
    defaultStyle: 'lowercase'
  });

  function resolveYamlBoolean(data) {
    if (data === null) return false;

    var max = data.length;

    return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||
           (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'));
  }

  function constructYamlBoolean(data) {
    return data === 'true' ||
           data === 'True' ||
           data === 'TRUE';
  }

  function isBoolean(object) {
    return Object.prototype.toString.call(object) === '[object Boolean]';
  }

  var bool = new type('tag:yaml.org,2002:bool', {
    kind: 'scalar',
    resolve: resolveYamlBoolean,
    construct: constructYamlBoolean,
    predicate: isBoolean,
    represent: {
      lowercase: function (object) { return object ? 'true' : 'false'; },
      uppercase: function (object) { return object ? 'TRUE' : 'FALSE'; },
      camelcase: function (object) { return object ? 'True' : 'False'; }
    },
    defaultStyle: 'lowercase'
  });

  function isHexCode(c) {
    return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) ||
           ((0x41/* A */ <= c) && (c <= 0x46/* F */)) ||
           ((0x61/* a */ <= c) && (c <= 0x66/* f */));
  }

  function isOctCode(c) {
    return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */));
  }

  function isDecCode(c) {
    return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */));
  }

  function resolveYamlInteger(data) {
    if (data === null) return false;

    var max = data.length,
        index = 0,
        hasDigits = false,
        ch;

    if (!max) return false;

    ch = data[index];

    // sign
    if (ch === '-' || ch === '+') {
      ch = data[++index];
    }

    if (ch === '0') {
      // 0
      if (index + 1 === max) return true;
      ch = data[++index];

      // base 2, base 8, base 16

      if (ch === 'b') {
        // base 2
        index++;

        for (; index < max; index++) {
          ch = data[index];
          if (ch === '_') continue;
          if (ch !== '0' && ch !== '1') return false;
          hasDigits = true;
        }
        return hasDigits && ch !== '_';
      }


      if (ch === 'x') {
        // base 16
        index++;

        for (; index < max; index++) {
          ch = data[index];
          if (ch === '_') continue;
          if (!isHexCode(data.charCodeAt(index))) return false;
          hasDigits = true;
        }
        return hasDigits && ch !== '_';
      }


      if (ch === 'o') {
        // base 8
        index++;

        for (; index < max; index++) {
          ch = data[index];
          if (ch === '_') continue;
          if (!isOctCode(data.charCodeAt(index))) return false;
          hasDigits = true;
        }
        return hasDigits && ch !== '_';
      }
    }

    // base 10 (except 0)

    // value should not start with `_`;
    if (ch === '_') return false;

    for (; index < max; index++) {
      ch = data[index];
      if (ch === '_') continue;
      if (!isDecCode(data.charCodeAt(index))) {
        return false;
      }
      hasDigits = true;
    }

    // Should have digits and should not end with `_`
    if (!hasDigits || ch === '_') return false;

    return true;
  }

  function constructYamlInteger(data) {
    var value = data, sign = 1, ch;

    if (value.indexOf('_') !== -1) {
      value = value.replace(/_/g, '');
    }

    ch = value[0];

    if (ch === '-' || ch === '+') {
      if (ch === '-') sign = -1;
      value = value.slice(1);
      ch = value[0];
    }

    if (value === '0') return 0;

    if (ch === '0') {
      if (value[1] === 'b') return sign * parseInt(value.slice(2), 2);
      if (value[1] === 'x') return sign * parseInt(value.slice(2), 16);
      if (value[1] === 'o') return sign * parseInt(value.slice(2), 8);
    }

    return sign * parseInt(value, 10);
  }

  function isInteger(object) {
    return (Object.prototype.toString.call(object)) === '[object Number]' &&
           (object % 1 === 0 && !common.isNegativeZero(object));
  }

  var int = new type('tag:yaml.org,2002:int', {
    kind: 'scalar',
    resolve: resolveYamlInteger,
    construct: constructYamlInteger,
    predicate: isInteger,
    represent: {
      binary:      function (obj) { return obj >= 0 ? '0b' + obj.toString(2) : '-0b' + obj.toString(2).slice(1); },
      octal:       function (obj) { return obj >= 0 ? '0o'  + obj.toString(8) : '-0o'  + obj.toString(8).slice(1); },
      decimal:     function (obj) { return obj.toString(10); },
      /* eslint-disable max-len */
      hexadecimal: function (obj) { return obj >= 0 ? '0x' + obj.toString(16).toUpperCase() :  '-0x' + obj.toString(16).toUpperCase().slice(1); }
    },
    defaultStyle: 'decimal',
    styleAliases: {
      binary:      [ 2,  'bin' ],
      octal:       [ 8,  'oct' ],
      decimal:     [ 10, 'dec' ],
      hexadecimal: [ 16, 'hex' ]
    }
  });

  var YAML_FLOAT_PATTERN = new RegExp(
    // 2.5e4, 2.5 and integers
    '^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?' +
    // .2e4, .2
    // special case, seems not from spec
    '|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?' +
    // .inf
    '|[-+]?\\.(?:inf|Inf|INF)' +
    // .nan
    '|\\.(?:nan|NaN|NAN))$');

  function resolveYamlFloat(data) {
    if (data === null) return false;

    if (!YAML_FLOAT_PATTERN.test(data) ||
        // Quick hack to not allow integers end with `_`
        // Probably should update regexp & check speed
        data[data.length - 1] === '_') {
      return false;
    }

    return true;
  }

  function constructYamlFloat(data) {
    var value, sign;

    value  = data.replace(/_/g, '').toLowerCase();
    sign   = value[0] === '-' ? -1 : 1;

    if ('+-'.indexOf(value[0]) >= 0) {
      value = value.slice(1);
    }

    if (value === '.inf') {
      return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;

    } else if (value === '.nan') {
      return NaN;
    }
    return sign * parseFloat(value, 10);
  }


  var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;

  function representYamlFloat(object, style) {
    var res;

    if (isNaN(object)) {
      switch (style) {
        case 'lowercase': return '.nan';
        case 'uppercase': return '.NAN';
        case 'camelcase': return '.NaN';
      }
    } else if (Number.POSITIVE_INFINITY === object) {
      switch (style) {
        case 'lowercase': return '.inf';
        case 'uppercase': return '.INF';
        case 'camelcase': return '.Inf';
      }
    } else if (Number.NEGATIVE_INFINITY === object) {
      switch (style) {
        case 'lowercase': return '-.inf';
        case 'uppercase': return '-.INF';
        case 'camelcase': return '-.Inf';
      }
    } else if (common.isNegativeZero(object)) {
      return '-0.0';
    }

    res = object.toString(10);

    // JS stringifier can build scientific format without dots: 5e-100,
    // while YAML requres dot: 5.e-100. Fix it with simple hack

    return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res;
  }

  function isFloat(object) {
    return (Object.prototype.toString.call(object) === '[object Number]') &&
           (object % 1 !== 0 || common.isNegativeZero(object));
  }

  var float = new type('tag:yaml.org,2002:float', {
    kind: 'scalar',
    resolve: resolveYamlFloat,
    construct: constructYamlFloat,
    predicate: isFloat,
    represent: representYamlFloat,
    defaultStyle: 'lowercase'
  });

  var json = failsafe.extend({
    implicit: [
      _null,
      bool,
      int,
      float
    ]
  });

  var core = json;

  var YAML_DATE_REGEXP = new RegExp(
    '^([0-9][0-9][0-9][0-9])'          + // [1] year
    '-([0-9][0-9])'                    + // [2] month
    '-([0-9][0-9])$');                   // [3] day

  var YAML_TIMESTAMP_REGEXP = new RegExp(
    '^([0-9][0-9][0-9][0-9])'          + // [1] year
    '-([0-9][0-9]?)'                   + // [2] month
    '-([0-9][0-9]?)'                   + // [3] day
    '(?:[Tt]|[ \\t]+)'                 + // ...
    '([0-9][0-9]?)'                    + // [4] hour
    ':([0-9][0-9])'                    + // [5] minute
    ':([0-9][0-9])'                    + // [6] second
    '(?:\\.([0-9]*))?'                 + // [7] fraction
    '(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tz_hour
    '(?::([0-9][0-9]))?))?$');           // [11] tz_minute

  function resolveYamlTimestamp(data) {
    if (data === null) return false;
    if (YAML_DATE_REGEXP.exec(data) !== null) return true;
    if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;
    return false;
  }

  function constructYamlTimestamp(data) {
    var match, year, month, day, hour, minute, second, fraction = 0,
        delta = null, tz_hour, tz_minute, date;

    match = YAML_DATE_REGEXP.exec(data);
    if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);

    if (match === null) throw new Error('Date resolve error');

    // match: [1] year [2] month [3] day

    year = +(match[1]);
    month = +(match[2]) - 1; // JS month starts with 0
    day = +(match[3]);

    if (!match[4]) { // no hour
      return new Date(Date.UTC(year, month, day));
    }

    // match: [4] hour [5] minute [6] second [7] fraction

    hour = +(match[4]);
    minute = +(match[5]);
    second = +(match[6]);

    if (match[7]) {
      fraction = match[7].slice(0, 3);
      while (fraction.length < 3) { // milli-seconds
        fraction += '0';
      }
      fraction = +fraction;
    }

    // match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute

    if (match[9]) {
      tz_hour = +(match[10]);
      tz_minute = +(match[11] || 0);
      delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds
      if (match[9] === '-') delta = -delta;
    }

    date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction));

    if (delta) date.setTime(date.getTime() - delta);

    return date;
  }

  function representYamlTimestamp(object /*, style*/) {
    return object.toISOString();
  }

  var timestamp = new type('tag:yaml.org,2002:timestamp', {
    kind: 'scalar',
    resolve: resolveYamlTimestamp,
    construct: constructYamlTimestamp,
    instanceOf: Date,
    represent: representYamlTimestamp
  });

  function resolveYamlMerge(data) {
    return data === '<<' || data === null;
  }

  var merge = new type('tag:yaml.org,2002:merge', {
    kind: 'scalar',
    resolve: resolveYamlMerge
  });

  /*eslint-disable no-bitwise*/





  // [ 64, 65, 66 ] -> [ padding, CR, LF ]
  var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r';


  function resolveYamlBinary(data) {
    if (data === null) return false;

    var code, idx, bitlen = 0, max = data.length, map = BASE64_MAP;

    // Convert one by one.
    for (idx = 0; idx < max; idx++) {
      code = map.indexOf(data.charAt(idx));

      // Skip CR/LF
      if (code > 64) continue;

      // Fail on illegal characters
      if (code < 0) return false;

      bitlen += 6;
    }

    // If there are any bits left, source was corrupted
    return (bitlen % 8) === 0;
  }

  function constructYamlBinary(data) {
    var idx, tailbits,
        input = data.replace(/[\r\n=]/g, ''), // remove CR/LF & padding to simplify scan
        max = input.length,
        map = BASE64_MAP,
        bits = 0,
        result = [];

    // Collect by 6*4 bits (3 bytes)

    for (idx = 0; idx < max; idx++) {
      if ((idx % 4 === 0) && idx) {
        result.push((bits >> 16) & 0xFF);
        result.push((bits >> 8) & 0xFF);
        result.push(bits & 0xFF);
      }

      bits = (bits << 6) | map.indexOf(input.charAt(idx));
    }

    // Dump tail

    tailbits = (max % 4) * 6;

    if (tailbits === 0) {
      result.push((bits >> 16) & 0xFF);
      result.push((bits >> 8) & 0xFF);
      result.push(bits & 0xFF);
    } else if (tailbits === 18) {
      result.push((bits >> 10) & 0xFF);
      result.push((bits >> 2) & 0xFF);
    } else if (tailbits === 12) {
      result.push((bits >> 4) & 0xFF);
    }

    return new Uint8Array(result);
  }

  function representYamlBinary(object /*, style*/) {
    var result = '', bits = 0, idx, tail,
        max = object.length,
        map = BASE64_MAP;

    // Convert every three bytes to 4 ASCII characters.

    for (idx = 0; idx < max; idx++) {
      if ((idx % 3 === 0) && idx) {
        result += map[(bits >> 18) & 0x3F];
        result += map[(bits >> 12) & 0x3F];
        result += map[(bits >> 6) & 0x3F];
        result += map[bits & 0x3F];
      }

      bits = (bits << 8) + object[idx];
    }

    // Dump tail

    tail = max % 3;

    if (tail === 0) {
      result += map[(bits >> 18) & 0x3F];
      result += map[(bits >> 12) & 0x3F];
      result += map[(bits >> 6) & 0x3F];
      result += map[bits & 0x3F];
    } else if (tail === 2) {
      result += map[(bits >> 10) & 0x3F];
      result += map[(bits >> 4) & 0x3F];
      result += map[(bits << 2) & 0x3F];
      result += map[64];
    } else if (tail === 1) {
      result += map[(bits >> 2) & 0x3F];
      result += map[(bits << 4) & 0x3F];
      result += map[64];
      result += map[64];
    }

    return result;
  }

  function isBinary(obj) {
    return Object.prototype.toString.call(obj) ===  '[object Uint8Array]';
  }

  var binary = new type('tag:yaml.org,2002:binary', {
    kind: 'scalar',
    resolve: resolveYamlBinary,
    construct: constructYamlBinary,
    predicate: isBinary,
    represent: representYamlBinary
  });

  var _hasOwnProperty$3 = Object.prototype.hasOwnProperty;
  var _toString$2       = Object.prototype.toString;

  function resolveYamlOmap(data) {
    if (data === null) return true;

    var objectKeys = [], index, length, pair, pairKey, pairHasKey,
        object = data;

    for (index = 0, length = object.length; index < length; index += 1) {
      pair = object[index];
      pairHasKey = false;

      if (_toString$2.call(pair) !== '[object Object]') return false;

      for (pairKey in pair) {
        if (_hasOwnProperty$3.call(pair, pairKey)) {
          if (!pairHasKey) pairHasKey = true;
          else return false;
        }
      }

      if (!pairHasKey) return false;

      if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey);
      else return false;
    }

    return true;
  }

  function constructYamlOmap(data) {
    return data !== null ? data : [];
  }

  var omap = new type('tag:yaml.org,2002:omap', {
    kind: 'sequence',
    resolve: resolveYamlOmap,
    construct: constructYamlOmap
  });

  var _toString$1 = Object.prototype.toString;

  function resolveYamlPairs(data) {
    if (data === null) return true;

    var index, length, pair, keys, result,
        object = data;

    result = new Array(object.length);

    for (index = 0, length = object.length; index < length; index += 1) {
      pair = object[index];

      if (_toString$1.call(pair) !== '[object Object]') return false;

      keys = Object.keys(pair);

      if (keys.length !== 1) return false;

      result[index] = [ keys[0], pair[keys[0]] ];
    }

    return true;
  }

  function constructYamlPairs(data) {
    if (data === null) return [];

    var index, length, pair, keys, result,
        object = data;

    result = new Array(object.length);

    for (index = 0, length = object.length; index < length; index += 1) {
      pair = object[index];

      keys = Object.keys(pair);

      result[index] = [ keys[0], pair[keys[0]] ];
    }

    return result;
  }

  var pairs = new type('tag:yaml.org,2002:pairs', {
    kind: 'sequence',
    resolve: resolveYamlPairs,
    construct: constructYamlPairs
  });

  var _hasOwnProperty$2 = Object.prototype.hasOwnProperty;

  function resolveYamlSet(data) {
    if (data === null) return true;

    var key, object = data;

    for (key in object) {
      if (_hasOwnProperty$2.call(object, key)) {
        if (object[key] !== null) return false;
      }
    }

    return true;
  }

  function constructYamlSet(data) {
    return data !== null ? data : {};
  }

  var set = new type('tag:yaml.org,2002:set', {
    kind: 'mapping',
    resolve: resolveYamlSet,
    construct: constructYamlSet
  });

  var _default = core.extend({
    implicit: [
      timestamp,
      merge
    ],
    explicit: [
      binary,
      omap,
      pairs,
      set
    ]
  });

  /*eslint-disable max-len,no-use-before-define*/







  var _hasOwnProperty$1 = Object.prototype.hasOwnProperty;


  var CONTEXT_FLOW_IN   = 1;
  var CONTEXT_FLOW_OUT  = 2;
  var CONTEXT_BLOCK_IN  = 3;
  var CONTEXT_BLOCK_OUT = 4;


  var CHOMPING_CLIP  = 1;
  var CHOMPING_STRIP = 2;
  var CHOMPING_KEEP  = 3;


  var PATTERN_NON_PRINTABLE         = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
  var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/;
  var PATTERN_FLOW_INDICATORS       = /[,\[\]\{\}]/;
  var PATTERN_TAG_HANDLE            = /^(?:!|!!|![a-z\-]+!)$/i;
  var PATTERN_TAG_URI               = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;


  function _class(obj) { return Object.prototype.toString.call(obj); }

  function is_EOL(c) {
    return (c === 0x0A/* LF */) || (c === 0x0D/* CR */);
  }

  function is_WHITE_SPACE(c) {
    return (c === 0x09/* Tab */) || (c === 0x20/* Space */);
  }

  function is_WS_OR_EOL(c) {
    return (c === 0x09/* Tab */) ||
           (c === 0x20/* Space */) ||
           (c === 0x0A/* LF */) ||
           (c === 0x0D/* CR */);
  }

  function is_FLOW_INDICATOR(c) {
    return c === 0x2C/* , */ ||
           c === 0x5B/* [ */ ||
           c === 0x5D/* ] */ ||
           c === 0x7B/* { */ ||
           c === 0x7D/* } */;
  }

  function fromHexCode(c) {
    var lc;

    if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {
      return c - 0x30;
    }

    /*eslint-disable no-bitwise*/
    lc = c | 0x20;

    if ((0x61/* a */ <= lc) && (lc <= 0x66/* f */)) {
      return lc - 0x61 + 10;
    }

    return -1;
  }

  function escapedHexLen(c) {
    if (c === 0x78/* x */) { return 2; }
    if (c === 0x75/* u */) { return 4; }
    if (c === 0x55/* U */) { return 8; }
    return 0;
  }

  function fromDecimalCode(c) {
    if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {
      return c - 0x30;
    }

    return -1;
  }

  function simpleEscapeSequence(c) {
    /* eslint-disable indent */
    return (c === 0x30/* 0 */) ? '\x00' :
          (c === 0x61/* a */) ? '\x07' :
          (c === 0x62/* b */) ? '\x08' :
          (c === 0x74/* t */) ? '\x09' :
          (c === 0x09/* Tab */) ? '\x09' :
          (c === 0x6E/* n */) ? '\x0A' :
          (c === 0x76/* v */) ? '\x0B' :
          (c === 0x66/* f */) ? '\x0C' :
          (c === 0x72/* r */) ? '\x0D' :
          (c === 0x65/* e */) ? '\x1B' :
          (c === 0x20/* Space */) ? ' ' :
          (c === 0x22/* " */) ? '\x22' :
          (c === 0x2F/* / */) ? '/' :
          (c === 0x5C/* \ */) ? '\x5C' :
          (c === 0x4E/* N */) ? '\x85' :
          (c === 0x5F/* _ */) ? '\xA0' :
          (c === 0x4C/* L */) ? '\u2028' :
          (c === 0x50/* P */) ? '\u2029' : '';
  }

  function charFromCodepoint(c) {
    if (c <= 0xFFFF) {
      return String.fromCharCode(c);
    }
    // Encode UTF-16 surrogate pair
    // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF
    return String.fromCharCode(
      ((c - 0x010000) >> 10) + 0xD800,
      ((c - 0x010000) & 0x03FF) + 0xDC00
    );
  }

  var simpleEscapeCheck = new Array(256); // integer, for fast access
  var simpleEscapeMap = new Array(256);
  for (var i = 0; i < 256; i++) {
    simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0;
    simpleEscapeMap[i] = simpleEscapeSequence(i);
  }


  function State$1(input, options) {
    this.input = input;

    this.filename  = options['filename']  || null;
    this.schema    = options['schema']    || _default;
    this.onWarning = options['onWarning'] || null;
    // (Hidden) Remove? makes the loader to expect YAML 1.1 documents
    // if such documents have no explicit %YAML directive
    this.legacy    = options['legacy']    || false;

    this.json      = options['json']      || false;
    this.listener  = options['listener']  || null;

    this.implicitTypes = this.schema.compiledImplicit;
    this.typeMap       = this.schema.compiledTypeMap;

    this.length     = input.length;
    this.position   = 0;
    this.line       = 0;
    this.lineStart  = 0;
    this.lineIndent = 0;

    // position of first leading tab in the current line,
    // used to make sure there are no tabs in the indentation
    this.firstTabInLine = -1;

    this.documents = [];

    /*
    this.version;
    this.checkLineBreaks;
    this.tagMap;
    this.anchorMap;
    this.tag;
    this.anchor;
    this.kind;
    this.result;*/

  }


  function generateError(state, message) {
    var mark = {
      name:     state.filename,
      buffer:   state.input.slice(0, -1), // omit trailing \0
      position: state.position,
      line:     state.line,
      column:   state.position - state.lineStart
    };

    mark.snippet = snippet(mark);

    return new exception(message, mark);
  }

  function throwError(state, message) {
    throw generateError(state, message);
  }

  function throwWarning(state, message) {
    if (state.onWarning) {
      state.onWarning.call(null, generateError(state, message));
    }
  }


  var directiveHandlers = {

    YAML: function handleYamlDirective(state, name, args) {

      var match, major, minor;

      if (state.version !== null) {
        throwError(state, 'duplication of %YAML directive');
      }

      if (args.length !== 1) {
        throwError(state, 'YAML directive accepts exactly one argument');
      }

      match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]);

      if (match === null) {
        throwError(state, 'ill-formed argument of the YAML directive');
      }

      major = parseInt(match[1], 10);
      minor = parseInt(match[2], 10);

      if (major !== 1) {
        throwError(state, 'unacceptable YAML version of the document');
      }

      state.version = args[0];
      state.checkLineBreaks = (minor < 2);

      if (minor !== 1 && minor !== 2) {
        throwWarning(state, 'unsupported YAML version of the document');
      }
    },

    TAG: function handleTagDirective(state, name, args) {

      var handle, prefix;

      if (args.length !== 2) {
        throwError(state, 'TAG directive accepts exactly two arguments');
      }

      handle = args[0];
      prefix = args[1];

      if (!PATTERN_TAG_HANDLE.test(handle)) {
        throwError(state, 'ill-formed tag handle (first argument) of the TAG directive');
      }

      if (_hasOwnProperty$1.call(state.tagMap, handle)) {
        throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle');
      }

      if (!PATTERN_TAG_URI.test(prefix)) {
        throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive');
      }

      try {
        prefix = decodeURIComponent(prefix);
      } catch (err) {
        throwError(state, 'tag prefix is malformed: ' + prefix);
      }

      state.tagMap[handle] = prefix;
    }
  };


  function captureSegment(state, start, end, checkJson) {
    var _position, _length, _character, _result;

    if (start < end) {
      _result = state.input.slice(start, end);

      if (checkJson) {
        for (_position = 0, _length = _result.length; _position < _length; _position += 1) {
          _character = _result.charCodeAt(_position);
          if (!(_character === 0x09 ||
                (0x20 <= _character && _character <= 0x10FFFF))) {
            throwError(state, 'expected valid JSON character');
          }
        }
      } else if (PATTERN_NON_PRINTABLE.test(_result)) {
        throwError(state, 'the stream contains non-printable characters');
      }

      state.result += _result;
    }
  }

  function mergeMappings(state, destination, source, overridableKeys) {
    var sourceKeys, key, index, quantity;

    if (!common.isObject(source)) {
      throwError(state, 'cannot merge mappings; the provided source object is unacceptable');
    }

    sourceKeys = Object.keys(source);

    for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
      key = sourceKeys[index];

      if (!_hasOwnProperty$1.call(destination, key)) {
        destination[key] = source[key];
        overridableKeys[key] = true;
      }
    }
  }

  function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode,
    startLine, startLineStart, startPos) {

    var index, quantity;

    // The output is a plain object here, so keys can only be strings.
    // We need to convert keyNode to a string, but doing so can hang the process
    // (deeply nested arrays that explode exponentially using aliases).
    if (Array.isArray(keyNode)) {
      keyNode = Array.prototype.slice.call(keyNode);

      for (index = 0, quantity = keyNode.length; index < quantity; index += 1) {
        if (Array.isArray(keyNode[index])) {
          throwError(state, 'nested arrays are not supported inside keys');
        }

        if (typeof keyNode === 'object' && _class(keyNode[index]) === '[object Object]') {
          keyNode[index] = '[object Object]';
        }
      }
    }

    // Avoid code execution in load() via toString property
    // (still use its own toString for arrays, timestamps,
    // and whatever user schema extensions happen to have @@toStringTag)
    if (typeof keyNode === 'object' && _class(keyNode) === '[object Object]') {
      keyNode = '[object Object]';
    }


    keyNode = String(keyNode);

    if (_result === null) {
      _result = {};
    }

    if (keyTag === 'tag:yaml.org,2002:merge') {
      if (Array.isArray(valueNode)) {
        for (index = 0, quantity = valueNode.length; index < quantity; index += 1) {
          mergeMappings(state, _result, valueNode[index], overridableKeys);
        }
      } else {
        mergeMappings(state, _result, valueNode, overridableKeys);
      }
    } else {
      if (!state.json &&
          !_hasOwnProperty$1.call(overridableKeys, keyNode) &&
          _hasOwnProperty$1.call(_result, keyNode)) {
        state.line = startLine || state.line;
        state.lineStart = startLineStart || state.lineStart;
        state.position = startPos || state.position;
        throwError(state, 'duplicated mapping key');
      }

      // used for this specific key only because Object.defineProperty is slow
      if (keyNode === '__proto__') {
        Object.defineProperty(_result, keyNode, {
          configurable: true,
          enumerable: true,
          writable: true,
          value: valueNode
        });
      } else {
        _result[keyNode] = valueNode;
      }
      delete overridableKeys[keyNode];
    }

    return _result;
  }

  function readLineBreak(state) {
    var ch;

    ch = state.input.charCodeAt(state.position);

    if (ch === 0x0A/* LF */) {
      state.position++;
    } else if (ch === 0x0D/* CR */) {
      state.position++;
      if (state.input.charCodeAt(state.position) === 0x0A/* LF */) {
        state.position++;
      }
    } else {
      throwError(state, 'a line break is expected');
    }

    state.line += 1;
    state.lineStart = state.position;
    state.firstTabInLine = -1;
  }

  function skipSeparationSpace(state, allowComments, checkIndent) {
    var lineBreaks = 0,
        ch = state.input.charCodeAt(state.position);

    while (ch !== 0) {
      while (is_WHITE_SPACE(ch)) {
        if (ch === 0x09/* Tab */ && state.firstTabInLine === -1) {
          state.firstTabInLine = state.position;
        }
        ch = state.input.charCodeAt(++state.position);
      }

      if (allowComments && ch === 0x23/* # */) {
        do {
          ch = state.input.charCodeAt(++state.position);
        } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0);
      }

      if (is_EOL(ch)) {
        readLineBreak(state);

        ch = state.input.charCodeAt(state.position);
        lineBreaks++;
        state.lineIndent = 0;

        while (ch === 0x20/* Space */) {
          state.lineIndent++;
          ch = state.input.charCodeAt(++state.position);
        }
      } else {
        break;
      }
    }

    if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {
      throwWarning(state, 'deficient indentation');
    }

    return lineBreaks;
  }

  function testDocumentSeparator(state) {
    var _position = state.position,
        ch;

    ch = state.input.charCodeAt(_position);

    // Condition state.position === state.lineStart is tested
    // in parent on each call, for efficiency. No needs to test here again.
    if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) &&
        ch === state.input.charCodeAt(_position + 1) &&
        ch === state.input.charCodeAt(_position + 2)) {

      _position += 3;

      ch = state.input.charCodeAt(_position);

      if (ch === 0 || is_WS_OR_EOL(ch)) {
        return true;
      }
    }

    return false;
  }

  function writeFoldedLines(state, count) {
    if (count === 1) {
      state.result += ' ';
    } else if (count > 1) {
      state.result += common.repeat('\n', count - 1);
    }
  }


  function readPlainScalar(state, nodeIndent, withinFlowCollection) {
    var preceding,
        following,
        captureStart,
        captureEnd,
        hasPendingContent,
        _line,
        _lineStart,
        _lineIndent,
        _kind = state.kind,
        _result = state.result,
        ch;

    ch = state.input.charCodeAt(state.position);

    if (is_WS_OR_EOL(ch)      ||
        is_FLOW_INDICATOR(ch) ||
        ch === 0x23/* # */    ||
        ch === 0x26/* & */    ||
        ch === 0x2A/* * */    ||
        ch === 0x21/* ! */    ||
        ch === 0x7C/* | */    ||
        ch === 0x3E/* > */    ||
        ch === 0x27/* ' */    ||
        ch === 0x22/* " */    ||
        ch === 0x25/* % */    ||
        ch === 0x40/* @ */    ||
        ch === 0x60/* ` */) {
      return false;
    }

    if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) {
      following = state.input.charCodeAt(state.position + 1);

      if (is_WS_OR_EOL(following) ||
          withinFlowCollection && is_FLOW_INDICATOR(following)) {
        return false;
      }
    }

    state.kind = 'scalar';
    state.result = '';
    captureStart = captureEnd = state.position;
    hasPendingContent = false;

    while (ch !== 0) {
      if (ch === 0x3A/* : */) {
        following = state.input.charCodeAt(state.position + 1);

        if (is_WS_OR_EOL(following) ||
            withinFlowCollection && is_FLOW_INDICATOR(following)) {
          break;
        }

      } else if (ch === 0x23/* # */) {
        preceding = state.input.charCodeAt(state.position - 1);

        if (is_WS_OR_EOL(preceding)) {
          break;
        }

      } else if ((state.position === state.lineStart && testDocumentSeparator(state)) ||
                 withinFlowCollection && is_FLOW_INDICATOR(ch)) {
        break;

      } else if (is_EOL(ch)) {
        _line = state.line;
        _lineStart = state.lineStart;
        _lineIndent = state.lineIndent;
        skipSeparationSpace(state, false, -1);

        if (state.lineIndent >= nodeIndent) {
          hasPendingContent = true;
          ch = state.input.charCodeAt(state.position);
          continue;
        } else {
          state.position = captureEnd;
          state.line = _line;
          state.lineStart = _lineStart;
          state.lineIndent = _lineIndent;
          break;
        }
      }

      if (hasPendingContent) {
        captureSegment(state, captureStart, captureEnd, false);
        writeFoldedLines(state, state.line - _line);
        captureStart = captureEnd = state.position;
        hasPendingContent = false;
      }

      if (!is_WHITE_SPACE(ch)) {
        captureEnd = state.position + 1;
      }

      ch = state.input.charCodeAt(++state.position);
    }

    captureSegment(state, captureStart, captureEnd, false);

    if (state.result) {
      return true;
    }

    state.kind = _kind;
    state.result = _result;
    return false;
  }

  function readSingleQuotedScalar(state, nodeIndent) {
    var ch,
        captureStart, captureEnd;

    ch = state.input.charCodeAt(state.position);

    if (ch !== 0x27/* ' */) {
      return false;
    }

    state.kind = 'scalar';
    state.result = '';
    state.position++;
    captureStart = captureEnd = state.position;

    while ((ch = state.input.charCodeAt(state.position)) !== 0) {
      if (ch === 0x27/* ' */) {
        captureSegment(state, captureStart, state.position, true);
        ch = state.input.charCodeAt(++state.position);

        if (ch === 0x27/* ' */) {
          captureStart = state.position;
          state.position++;
          captureEnd = state.position;
        } else {
          return true;
        }

      } else if (is_EOL(ch)) {
        captureSegment(state, captureStart, captureEnd, true);
        writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
        captureStart = captureEnd = state.position;

      } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
        throwError(state, 'unexpected end of the document within a single quoted scalar');

      } else {
        state.position++;
        captureEnd = state.position;
      }
    }

    throwError(state, 'unexpected end of the stream within a single quoted scalar');
  }

  function readDoubleQuotedScalar(state, nodeIndent) {
    var captureStart,
        captureEnd,
        hexLength,
        hexResult,
        tmp,
        ch;

    ch = state.input.charCodeAt(state.position);

    if (ch !== 0x22/* " */) {
      return false;
    }

    state.kind = 'scalar';
    state.result = '';
    state.position++;
    captureStart = captureEnd = state.position;

    while ((ch = state.input.charCodeAt(state.position)) !== 0) {
      if (ch === 0x22/* " */) {
        captureSegment(state, captureStart, state.position, true);
        state.position++;
        return true;

      } else if (ch === 0x5C/* \ */) {
        captureSegment(state, captureStart, state.position, true);
        ch = state.input.charCodeAt(++state.position);

        if (is_EOL(ch)) {
          skipSeparationSpace(state, false, nodeIndent);

          // TODO: rework to inline fn with no type cast?
        } else if (ch < 256 && simpleEscapeCheck[ch]) {
          state.result += simpleEscapeMap[ch];
          state.position++;

        } else if ((tmp = escapedHexLen(ch)) > 0) {
          hexLength = tmp;
          hexResult = 0;

          for (; hexLength > 0; hexLength--) {
            ch = state.input.charCodeAt(++state.position);

            if ((tmp = fromHexCode(ch)) >= 0) {
              hexResult = (hexResult << 4) + tmp;

            } else {
              throwError(state, 'expected hexadecimal character');
            }
          }

          state.result += charFromCodepoint(hexResult);

          state.position++;

        } else {
          throwError(state, 'unknown escape sequence');
        }

        captureStart = captureEnd = state.position;

      } else if (is_EOL(ch)) {
        captureSegment(state, captureStart, captureEnd, true);
        writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
        captureStart = captureEnd = state.position;

      } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
        throwError(state, 'unexpected end of the document within a double quoted scalar');

      } else {
        state.position++;
        captureEnd = state.position;
      }
    }

    throwError(state, 'unexpected end of the stream within a double quoted scalar');
  }

  function readFlowCollection(state, nodeIndent) {
    var readNext = true,
        _line,
        _lineStart,
        _pos,
        _tag     = state.tag,
        _result,
        _anchor  = state.anchor,
        following,
        terminator,
        isPair,
        isExplicitPair,
        isMapping,
        overridableKeys = Object.create(null),
        keyNode,
        keyTag,
        valueNode,
        ch;

    ch = state.input.charCodeAt(state.position);

    if (ch === 0x5B/* [ */) {
      terminator = 0x5D;/* ] */
      isMapping = false;
      _result = [];
    } else if (ch === 0x7B/* { */) {
      terminator = 0x7D;/* } */
      isMapping = true;
      _result = {};
    } else {
      return false;
    }

    if (state.anchor !== null) {
      state.anchorMap[state.anchor] = _result;
    }

    ch = state.input.charCodeAt(++state.position);

    while (ch !== 0) {
      skipSeparationSpace(state, true, nodeIndent);

      ch = state.input.charCodeAt(state.position);

      if (ch === terminator) {
        state.position++;
        state.tag = _tag;
        state.anchor = _anchor;
        state.kind = isMapping ? 'mapping' : 'sequence';
        state.result = _result;
        return true;
      } else if (!readNext) {
        throwError(state, 'missed comma between flow collection entries');
      } else if (ch === 0x2C/* , */) {
        // "flow collection entries can never be completely empty", as per YAML 1.2, section 7.4
        throwError(state, "expected the node content, but found ','");
      }

      keyTag = keyNode = valueNode = null;
      isPair = isExplicitPair = false;

      if (ch === 0x3F/* ? */) {
        following = state.input.charCodeAt(state.position + 1);

        if (is_WS_OR_EOL(following)) {
          isPair = isExplicitPair = true;
          state.position++;
          skipSeparationSpace(state, true, nodeIndent);
        }
      }

      _line = state.line; // Save the current line.
      _lineStart = state.lineStart;
      _pos = state.position;
      composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
      keyTag = state.tag;
      keyNode = state.result;
      skipSeparationSpace(state, true, nodeIndent);

      ch = state.input.charCodeAt(state.position);

      if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) {
        isPair = true;
        ch = state.input.charCodeAt(++state.position);
        skipSeparationSpace(state, true, nodeIndent);
        composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
        valueNode = state.result;
      }

      if (isMapping) {
        storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos);
      } else if (isPair) {
        _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos));
      } else {
        _result.push(keyNode);
      }

      skipSeparationSpace(state, true, nodeIndent);

      ch = state.input.charCodeAt(state.position);

      if (ch === 0x2C/* , */) {
        readNext = true;
        ch = state.input.charCodeAt(++state.position);
      } else {
        readNext = false;
      }
    }

    throwError(state, 'unexpected end of the stream within a flow collection');
  }

  function readBlockScalar(state, nodeIndent) {
    var captureStart,
        folding,
        chomping       = CHOMPING_CLIP,
        didReadContent = false,
        detectedIndent = false,
        textIndent     = nodeIndent,
        emptyLines     = 0,
        atMoreIndented = false,
        tmp,
        ch;

    ch = state.input.charCodeAt(state.position);

    if (ch === 0x7C/* | */) {
      folding = false;
    } else if (ch === 0x3E/* > */) {
      folding = true;
    } else {
      return false;
    }

    state.kind = 'scalar';
    state.result = '';

    while (ch !== 0) {
      ch = state.input.charCodeAt(++state.position);

      if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {
        if (CHOMPING_CLIP === chomping) {
          chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP;
        } else {
          throwError(state, 'repeat of a chomping mode identifier');
        }

      } else if ((tmp = fromDecimalCode(ch)) >= 0) {
        if (tmp === 0) {
          throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one');
        } else if (!detectedIndent) {
          textIndent = nodeIndent + tmp - 1;
          detectedIndent = true;
        } else {
          throwError(state, 'repeat of an indentation width identifier');
        }

      } else {
        break;
      }
    }

    if (is_WHITE_SPACE(ch)) {
      do { ch = state.input.charCodeAt(++state.position); }
      while (is_WHITE_SPACE(ch));

      if (ch === 0x23/* # */) {
        do { ch = state.input.charCodeAt(++state.position); }
        while (!is_EOL(ch) && (ch !== 0));
      }
    }

    while (ch !== 0) {
      readLineBreak(state);
      state.lineIndent = 0;

      ch = state.input.charCodeAt(state.position);

      while ((!detectedIndent || state.lineIndent < textIndent) &&
             (ch === 0x20/* Space */)) {
        state.lineIndent++;
        ch = state.input.charCodeAt(++state.position);
      }

      if (!detectedIndent && state.lineIndent > textIndent) {
        textIndent = state.lineIndent;
      }

      if (is_EOL(ch)) {
        emptyLines++;
        continue;
      }

      // End of the scalar.
      if (state.lineIndent < textIndent) {

        // Perform the chomping.
        if (chomping === CHOMPING_KEEP) {
          state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
        } else if (chomping === CHOMPING_CLIP) {
          if (didReadContent) { // i.e. only if the scalar is not empty.
            state.result += '\n';
          }
        }

        // Break this `while` cycle and go to the funciton's epilogue.
        break;
      }

      // Folded style: use fancy rules to handle line breaks.
      if (folding) {

        // Lines starting with white space characters (more-indented lines) are not folded.
        if (is_WHITE_SPACE(ch)) {
          atMoreIndented = true;
          // except for the first content line (cf. Example 8.1)
          state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);

        // End of more-indented block.
        } else if (atMoreIndented) {
          atMoreIndented = false;
          state.result += common.repeat('\n', emptyLines + 1);

        // Just one line break - perceive as the same line.
        } else if (emptyLines === 0) {
          if (didReadContent) { // i.e. only if we have already read some scalar content.
            state.result += ' ';
          }

        // Several line breaks - perceive as different lines.
        } else {
          state.result += common.repeat('\n', emptyLines);
        }

      // Literal style: just add exact number of line breaks between content lines.
      } else {
        // Keep all line breaks except the header line break.
        state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
      }

      didReadContent = true;
      detectedIndent = true;
      emptyLines = 0;
      captureStart = state.position;

      while (!is_EOL(ch) && (ch !== 0)) {
        ch = state.input.charCodeAt(++state.position);
      }

      captureSegment(state, captureStart, state.position, false);
    }

    return true;
  }

  function readBlockSequence(state, nodeIndent) {
    var _line,
        _tag      = state.tag,
        _anchor   = state.anchor,
        _result   = [],
        following,
        detected  = false,
        ch;

    // there is a leading tab before this token, so it can't be a block sequence/mapping;
    // it can still be flow sequence/mapping or a scalar
    if (state.firstTabInLine !== -1) return false;

    if (state.anchor !== null) {
      state.anchorMap[state.anchor] = _result;
    }

    ch = state.input.charCodeAt(state.position);

    while (ch !== 0) {
      if (state.firstTabInLine !== -1) {
        state.position = state.firstTabInLine;
        throwError(state, 'tab characters must not be used in indentation');
      }

      if (ch !== 0x2D/* - */) {
        break;
      }

      following = state.input.charCodeAt(state.position + 1);

      if (!is_WS_OR_EOL(following)) {
        break;
      }

      detected = true;
      state.position++;

      if (skipSeparationSpace(state, true, -1)) {
        if (state.lineIndent <= nodeIndent) {
          _result.push(null);
          ch = state.input.charCodeAt(state.position);
          continue;
        }
      }

      _line = state.line;
      composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true);
      _result.push(state.result);
      skipSeparationSpace(state, true, -1);

      ch = state.input.charCodeAt(state.position);

      if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {
        throwError(state, 'bad indentation of a sequence entry');
      } else if (state.lineIndent < nodeIndent) {
        break;
      }
    }

    if (detected) {
      state.tag = _tag;
      state.anchor = _anchor;
      state.kind = 'sequence';
      state.result = _result;
      return true;
    }
    return false;
  }

  function readBlockMapping(state, nodeIndent, flowIndent) {
    var following,
        allowCompact,
        _line,
        _keyLine,
        _keyLineStart,
        _keyPos,
        _tag          = state.tag,
        _anchor       = state.anchor,
        _result       = {},
        overridableKeys = Object.create(null),
        keyTag        = null,
        keyNode       = null,
        valueNode     = null,
        atExplicitKey = false,
        detected      = false,
        ch;

    // there is a leading tab before this token, so it can't be a block sequence/mapping;
    // it can still be flow sequence/mapping or a scalar
    if (state.firstTabInLine !== -1) return false;

    if (state.anchor !== null) {
      state.anchorMap[state.anchor] = _result;
    }

    ch = state.input.charCodeAt(state.position);

    while (ch !== 0) {
      if (!atExplicitKey && state.firstTabInLine !== -1) {
        state.position = state.firstTabInLine;
        throwError(state, 'tab characters must not be used in indentation');
      }

      following = state.input.charCodeAt(state.position + 1);
      _line = state.line; // Save the current line.

      //
      // Explicit notation case. There are two separate blocks:
      // first for the key (denoted by "?") and second for the value (denoted by ":")
      //
      if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && is_WS_OR_EOL(following)) {

        if (ch === 0x3F/* ? */) {
          if (atExplicitKey) {
            storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
            keyTag = keyNode = valueNode = null;
          }

          detected = true;
          atExplicitKey = true;
          allowCompact = true;

        } else if (atExplicitKey) {
          // i.e. 0x3A/* : */ === character after the explicit key.
          atExplicitKey = false;
          allowCompact = true;

        } else {
          throwError(state, 'incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line');
        }

        state.position += 1;
        ch = following;

      //
      // Implicit notation case. Flow-style node as the key first, then ":", and the value.
      //
      } else {
        _keyLine = state.line;
        _keyLineStart = state.lineStart;
        _keyPos = state.position;

        if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {
          // Neither implicit nor explicit notation.
          // Reading is done. Go to the epilogue.
          break;
        }

        if (state.line === _line) {
          ch = state.input.charCodeAt(state.position);

          while (is_WHITE_SPACE(ch)) {
            ch = state.input.charCodeAt(++state.position);
          }

          if (ch === 0x3A/* : */) {
            ch = state.input.charCodeAt(++state.position);

            if (!is_WS_OR_EOL(ch)) {
              throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping');
            }

            if (atExplicitKey) {
              storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
              keyTag = keyNode = valueNode = null;
            }

            detected = true;
            atExplicitKey = false;
            allowCompact = false;
            keyTag = state.tag;
            keyNode = state.result;

          } else if (detected) {
            throwError(state, 'can not read an implicit mapping pair; a colon is missed');

          } else {
            state.tag = _tag;
            state.anchor = _anchor;
            return true; // Keep the result of `composeNode`.
          }

        } else if (detected) {
          throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key');

        } else {
          state.tag = _tag;
          state.anchor = _anchor;
          return true; // Keep the result of `composeNode`.
        }
      }

      //
      // Common reading code for both explicit and implicit notations.
      //
      if (state.line === _line || state.lineIndent > nodeIndent) {
        if (atExplicitKey) {
          _keyLine = state.line;
          _keyLineStart = state.lineStart;
          _keyPos = state.position;
        }

        if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {
          if (atExplicitKey) {
            keyNode = state.result;
          } else {
            valueNode = state.result;
          }
        }

        if (!atExplicitKey) {
          storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos);
          keyTag = keyNode = valueNode = null;
        }

        skipSeparationSpace(state, true, -1);
        ch = state.input.charCodeAt(state.position);
      }

      if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {
        throwError(state, 'bad indentation of a mapping entry');
      } else if (state.lineIndent < nodeIndent) {
        break;
      }
    }

    //
    // Epilogue.
    //

    // Special case: last mapping's node contains only the key in explicit notation.
    if (atExplicitKey) {
      storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
    }

    // Expose the resulting mapping.
    if (detected) {
      state.tag = _tag;
      state.anchor = _anchor;
      state.kind = 'mapping';
      state.result = _result;
    }

    return detected;
  }

  function readTagProperty(state) {
    var _position,
        isVerbatim = false,
        isNamed    = false,
        tagHandle,
        tagName,
        ch;

    ch = state.input.charCodeAt(state.position);

    if (ch !== 0x21/* ! */) return false;

    if (state.tag !== null) {
      throwError(state, 'duplication of a tag property');
    }

    ch = state.input.charCodeAt(++state.position);

    if (ch === 0x3C/* < */) {
      isVerbatim = true;
      ch = state.input.charCodeAt(++state.position);

    } else if (ch === 0x21/* ! */) {
      isNamed = true;
      tagHandle = '!!';
      ch = state.input.charCodeAt(++state.position);

    } else {
      tagHandle = '!';
    }

    _position = state.position;

    if (isVerbatim) {
      do { ch = state.input.charCodeAt(++state.position); }
      while (ch !== 0 && ch !== 0x3E/* > */);

      if (state.position < state.length) {
        tagName = state.input.slice(_position, state.position);
        ch = state.input.charCodeAt(++state.position);
      } else {
        throwError(state, 'unexpected end of the stream within a verbatim tag');
      }
    } else {
      while (ch !== 0 && !is_WS_OR_EOL(ch)) {

        if (ch === 0x21/* ! */) {
          if (!isNamed) {
            tagHandle = state.input.slice(_position - 1, state.position + 1);

            if (!PATTERN_TAG_HANDLE.test(tagHandle)) {
              throwError(state, 'named tag handle cannot contain such characters');
            }

            isNamed = true;
            _position = state.position + 1;
          } else {
            throwError(state, 'tag suffix cannot contain exclamation marks');
          }
        }

        ch = state.input.charCodeAt(++state.position);
      }

      tagName = state.input.slice(_position, state.position);

      if (PATTERN_FLOW_INDICATORS.test(tagName)) {
        throwError(state, 'tag suffix cannot contain flow indicator characters');
      }
    }

    if (tagName && !PATTERN_TAG_URI.test(tagName)) {
      throwError(state, 'tag name cannot contain such characters: ' + tagName);
    }

    try {
      tagName = decodeURIComponent(tagName);
    } catch (err) {
      throwError(state, 'tag name is malformed: ' + tagName);
    }

    if (isVerbatim) {
      state.tag = tagName;

    } else if (_hasOwnProperty$1.call(state.tagMap, tagHandle)) {
      state.tag = state.tagMap[tagHandle] + tagName;

    } else if (tagHandle === '!') {
      state.tag = '!' + tagName;

    } else if (tagHandle === '!!') {
      state.tag = 'tag:yaml.org,2002:' + tagName;

    } else {
      throwError(state, 'undeclared tag handle "' + tagHandle + '"');
    }

    return true;
  }

  function readAnchorProperty(state) {
    var _position,
        ch;

    ch = state.input.charCodeAt(state.position);

    if (ch !== 0x26/* & */) return false;

    if (state.anchor !== null) {
      throwError(state, 'duplication of an anchor property');
    }

    ch = state.input.charCodeAt(++state.position);
    _position = state.position;

    while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
      ch = state.input.charCodeAt(++state.position);
    }

    if (state.position === _position) {
      throwError(state, 'name of an anchor node must contain at least one character');
    }

    state.anchor = state.input.slice(_position, state.position);
    return true;
  }

  function readAlias(state) {
    var _position, alias,
        ch;

    ch = state.input.charCodeAt(state.position);

    if (ch !== 0x2A/* * */) return false;

    ch = state.input.charCodeAt(++state.position);
    _position = state.position;

    while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
      ch = state.input.charCodeAt(++state.position);
    }

    if (state.position === _position) {
      throwError(state, 'name of an alias node must contain at least one character');
    }

    alias = state.input.slice(_position, state.position);

    if (!_hasOwnProperty$1.call(state.anchorMap, alias)) {
      throwError(state, 'unidentified alias "' + alias + '"');
    }

    state.result = state.anchorMap[alias];
    skipSeparationSpace(state, true, -1);
    return true;
  }

  function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) {
    var allowBlockStyles,
        allowBlockScalars,
        allowBlockCollections,
        indentStatus = 1, // 1: this>parent, 0: this=parent, -1: this<parent
        atNewLine  = false,
        hasContent = false,
        typeIndex,
        typeQuantity,
        typeList,
        type,
        flowIndent,
        blockIndent;

    if (state.listener !== null) {
      state.listener('open', state);
    }

    state.tag    = null;
    state.anchor = null;
    state.kind   = null;
    state.result = null;

    allowBlockStyles = allowBlockScalars = allowBlockCollections =
      CONTEXT_BLOCK_OUT === nodeContext ||
      CONTEXT_BLOCK_IN  === nodeContext;

    if (allowToSeek) {
      if (skipSeparationSpace(state, true, -1)) {
        atNewLine = true;

        if (state.lineIndent > parentIndent) {
          indentStatus = 1;
        } else if (state.lineIndent === parentIndent) {
          indentStatus = 0;
        } else if (state.lineIndent < parentIndent) {
          indentStatus = -1;
        }
      }
    }

    if (indentStatus === 1) {
      while (readTagProperty(state) || readAnchorProperty(state)) {
        if (skipSeparationSpace(state, true, -1)) {
          atNewLine = true;
          allowBlockCollections = allowBlockStyles;

          if (state.lineIndent > parentIndent) {
            indentStatus = 1;
          } else if (state.lineIndent === parentIndent) {
            indentStatus = 0;
          } else if (state.lineIndent < parentIndent) {
            indentStatus = -1;
          }
        } else {
          allowBlockCollections = false;
        }
      }
    }

    if (allowBlockCollections) {
      allowBlockCollections = atNewLine || allowCompact;
    }

    if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {
      if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {
        flowIndent = parentIndent;
      } else {
        flowIndent = parentIndent + 1;
      }

      blockIndent = state.position - state.lineStart;

      if (indentStatus === 1) {
        if (allowBlockCollections &&
            (readBlockSequence(state, blockIndent) ||
             readBlockMapping(state, blockIndent, flowIndent)) ||
            readFlowCollection(state, flowIndent)) {
          hasContent = true;
        } else {
          if ((allowBlockScalars && readBlockScalar(state, flowIndent)) ||
              readSingleQuotedScalar(state, flowIndent) ||
              readDoubleQuotedScalar(state, flowIndent)) {
            hasContent = true;

          } else if (readAlias(state)) {
            hasContent = true;

            if (state.tag !== null || state.anchor !== null) {
              throwError(state, 'alias node should not have any properties');
            }

          } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {
            hasContent = true;

            if (state.tag === null) {
              state.tag = '?';
            }
          }

          if (state.anchor !== null) {
            state.anchorMap[state.anchor] = state.result;
          }
        }
      } else if (indentStatus === 0) {
        // Special case: block sequences are allowed to have same indentation level as the parent.
        // http://www.yaml.org/spec/1.2/spec.html#id2799784
        hasContent = allowBlockCollections && readBlockSequence(state, blockIndent);
      }
    }

    if (state.tag === null) {
      if (state.anchor !== null) {
        state.anchorMap[state.anchor] = state.result;
      }

    } else if (state.tag === '?') {
      // Implicit resolving is not allowed for non-scalar types, and '?'
      // non-specific tag is only automatically assigned to plain scalars.
      //
      // We only need to check kind conformity in case user explicitly assigns '?'
      // tag, for example like this: "!<?> [0]"
      //
      if (state.result !== null && state.kind !== 'scalar') {
        throwError(state, 'unacceptable node kind for !<?> tag; it should be "scalar", not "' + state.kind + '"');
      }

      for (typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {
        type = state.implicitTypes[typeIndex];

        if (type.resolve(state.result)) { // `state.result` updated in resolver if matched
          state.result = type.construct(state.result);
          state.tag = type.tag;
          if (state.anchor !== null) {
            state.anchorMap[state.anchor] = state.result;
          }
          break;
        }
      }
    } else if (state.tag !== '!') {
      if (_hasOwnProperty$1.call(state.typeMap[state.kind || 'fallback'], state.tag)) {
        type = state.typeMap[state.kind || 'fallback'][state.tag];
      } else {
        // looking for multi type
        type = null;
        typeList = state.typeMap.multi[state.kind || 'fallback'];

        for (typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) {
          if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) {
            type = typeList[typeIndex];
            break;
          }
        }
      }

      if (!type) {
        throwError(state, 'unknown tag !<' + state.tag + '>');
      }

      if (state.result !== null && type.kind !== state.kind) {
        throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be "' + type.kind + '", not "' + state.kind + '"');
      }

      if (!type.resolve(state.result, state.tag)) { // `state.result` updated in resolver if matched
        throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag');
      } else {
        state.result = type.construct(state.result, state.tag);
        if (state.anchor !== null) {
          state.anchorMap[state.anchor] = state.result;
        }
      }
    }

    if (state.listener !== null) {
      state.listener('close', state);
    }
    return state.tag !== null ||  state.anchor !== null || hasContent;
  }

  function readDocument(state) {
    var documentStart = state.position,
        _position,
        directiveName,
        directiveArgs,
        hasDirectives = false,
        ch;

    state.version = null;
    state.checkLineBreaks = state.legacy;
    state.tagMap = Object.create(null);
    state.anchorMap = Object.create(null);

    while ((ch = state.input.charCodeAt(state.position)) !== 0) {
      skipSeparationSpace(state, true, -1);

      ch = state.input.charCodeAt(state.position);

      if (state.lineIndent > 0 || ch !== 0x25/* % */) {
        break;
      }

      hasDirectives = true;
      ch = state.input.charCodeAt(++state.position);
      _position = state.position;

      while (ch !== 0 && !is_WS_OR_EOL(ch)) {
        ch = state.input.charCodeAt(++state.position);
      }

      directiveName = state.input.slice(_position, state.position);
      directiveArgs = [];

      if (directiveName.length < 1) {
        throwError(state, 'directive name must not be less than one character in length');
      }

      while (ch !== 0) {
        while (is_WHITE_SPACE(ch)) {
          ch = state.input.charCodeAt(++state.position);
        }

        if (ch === 0x23/* # */) {
          do { ch = state.input.charCodeAt(++state.position); }
          while (ch !== 0 && !is_EOL(ch));
          break;
        }

        if (is_EOL(ch)) break;

        _position = state.position;

        while (ch !== 0 && !is_WS_OR_EOL(ch)) {
          ch = state.input.charCodeAt(++state.position);
        }

        directiveArgs.push(state.input.slice(_position, state.position));
      }

      if (ch !== 0) readLineBreak(state);

      if (_hasOwnProperty$1.call(directiveHandlers, directiveName)) {
        directiveHandlers[directiveName](state, directiveName, directiveArgs);
      } else {
        throwWarning(state, 'unknown document directive "' + directiveName + '"');
      }
    }

    skipSeparationSpace(state, true, -1);

    if (state.lineIndent === 0 &&
        state.input.charCodeAt(state.position)     === 0x2D/* - */ &&
        state.input.charCodeAt(state.position + 1) === 0x2D/* - */ &&
        state.input.charCodeAt(state.position + 2) === 0x2D/* - */) {
      state.position += 3;
      skipSeparationSpace(state, true, -1);

    } else if (hasDirectives) {
      throwError(state, 'directives end mark is expected');
    }

    composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true);
    skipSeparationSpace(state, true, -1);

    if (state.checkLineBreaks &&
        PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {
      throwWarning(state, 'non-ASCII line breaks are interpreted as content');
    }

    state.documents.push(state.result);

    if (state.position === state.lineStart && testDocumentSeparator(state)) {

      if (state.input.charCodeAt(state.position) === 0x2E/* . */) {
        state.position += 3;
        skipSeparationSpace(state, true, -1);
      }
      return;
    }

    if (state.position < (state.length - 1)) {
      throwError(state, 'end of the stream or a document separator is expected');
    } else {
      return;
    }
  }


  function loadDocuments(input, options) {
    input = String(input);
    options = options || {};

    if (input.length !== 0) {

      // Add tailing `\n` if not exists
      if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ &&
          input.charCodeAt(input.length - 1) !== 0x0D/* CR */) {
        input += '\n';
      }

      // Strip BOM
      if (input.charCodeAt(0) === 0xFEFF) {
        input = input.slice(1);
      }
    }

    var state = new State$1(input, options);

    var nullpos = input.indexOf('\0');

    if (nullpos !== -1) {
      state.position = nullpos;
      throwError(state, 'null byte is not allowed in input');
    }

    // Use 0 as string terminator. That significantly simplifies bounds check.
    state.input += '\0';

    while (state.input.charCodeAt(state.position) === 0x20/* Space */) {
      state.lineIndent += 1;
      state.position += 1;
    }

    while (state.position < (state.length - 1)) {
      readDocument(state);
    }

    return state.documents;
  }


  function loadAll$1(input, iterator, options) {
    if (iterator !== null && typeof iterator === 'object' && typeof options === 'undefined') {
      options = iterator;
      iterator = null;
    }

    var documents = loadDocuments(input, options);

    if (typeof iterator !== 'function') {
      return documents;
    }

    for (var index = 0, length = documents.length; index < length; index += 1) {
      iterator(documents[index]);
    }
  }


  function load$1(input, options) {
    var documents = loadDocuments(input, options);

    if (documents.length === 0) {
      /*eslint-disable no-undefined*/
      return undefined;
    } else if (documents.length === 1) {
      return documents[0];
    }
    throw new exception('expected a single document in the stream, but found more');
  }


  var loadAll_1 = loadAll$1;
  var load_1    = load$1;

  var loader = {
  	loadAll: loadAll_1,
  	load: load_1
  };

  /*eslint-disable no-use-before-define*/





  var _toString       = Object.prototype.toString;
  var _hasOwnProperty = Object.prototype.hasOwnProperty;

  var CHAR_BOM                  = 0xFEFF;
  var CHAR_TAB                  = 0x09; /* Tab */
  var CHAR_LINE_FEED            = 0x0A; /* LF */
  var CHAR_CARRIAGE_RETURN      = 0x0D; /* CR */
  var CHAR_SPACE                = 0x20; /* Space */
  var CHAR_EXCLAMATION          = 0x21; /* ! */
  var CHAR_DOUBLE_QUOTE         = 0x22; /* " */
  var CHAR_SHARP                = 0x23; /* # */
  var CHAR_PERCENT              = 0x25; /* % */
  var CHAR_AMPERSAND            = 0x26; /* & */
  var CHAR_SINGLE_QUOTE         = 0x27; /* ' */
  var CHAR_ASTERISK             = 0x2A; /* * */
  var CHAR_COMMA                = 0x2C; /* , */
  var CHAR_MINUS                = 0x2D; /* - */
  var CHAR_COLON                = 0x3A; /* : */
  var CHAR_EQUALS               = 0x3D; /* = */
  var CHAR_GREATER_THAN         = 0x3E; /* > */
  var CHAR_QUESTION             = 0x3F; /* ? */
  var CHAR_COMMERCIAL_AT        = 0x40; /* @ */
  var CHAR_LEFT_SQUARE_BRACKET  = 0x5B; /* [ */
  var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */
  var CHAR_GRAVE_ACCENT         = 0x60; /* ` */
  var CHAR_LEFT_CURLY_BRACKET   = 0x7B; /* { */
  var CHAR_VERTICAL_LINE        = 0x7C; /* | */
  var CHAR_RIGHT_CURLY_BRACKET  = 0x7D; /* } */

  var ESCAPE_SEQUENCES = {};

  ESCAPE_SEQUENCES[0x00]   = '\\0';
  ESCAPE_SEQUENCES[0x07]   = '\\a';
  ESCAPE_SEQUENCES[0x08]   = '\\b';
  ESCAPE_SEQUENCES[0x09]   = '\\t';
  ESCAPE_SEQUENCES[0x0A]   = '\\n';
  ESCAPE_SEQUENCES[0x0B]   = '\\v';
  ESCAPE_SEQUENCES[0x0C]   = '\\f';
  ESCAPE_SEQUENCES[0x0D]   = '\\r';
  ESCAPE_SEQUENCES[0x1B]   = '\\e';
  ESCAPE_SEQUENCES[0x22]   = '\\"';
  ESCAPE_SEQUENCES[0x5C]   = '\\\\';
  ESCAPE_SEQUENCES[0x85]   = '\\N';
  ESCAPE_SEQUENCES[0xA0]   = '\\_';
  ESCAPE_SEQUENCES[0x2028] = '\\L';
  ESCAPE_SEQUENCES[0x2029] = '\\P';

  var DEPRECATED_BOOLEANS_SYNTAX = [
    'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',
    'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'
  ];

  var DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;

  function compileStyleMap(schema, map) {
    var result, keys, index, length, tag, style, type;

    if (map === null) return {};

    result = {};
    keys = Object.keys(map);

    for (index = 0, length = keys.length; index < length; index += 1) {
      tag = keys[index];
      style = String(map[tag]);

      if (tag.slice(0, 2) === '!!') {
        tag = 'tag:yaml.org,2002:' + tag.slice(2);
      }
      type = schema.compiledTypeMap['fallback'][tag];

      if (type && _hasOwnProperty.call(type.styleAliases, style)) {
        style = type.styleAliases[style];
      }

      result[tag] = style;
    }

    return result;
  }

  function encodeHex(character) {
    var string, handle, length;

    string = character.toString(16).toUpperCase();

    if (character <= 0xFF) {
      handle = 'x';
      length = 2;
    } else if (character <= 0xFFFF) {
      handle = 'u';
      length = 4;
    } else if (character <= 0xFFFFFFFF) {
      handle = 'U';
      length = 8;
    } else {
      throw new exception('code point within a string may not be greater than 0xFFFFFFFF');
    }

    return '\\' + handle + common.repeat('0', length - string.length) + string;
  }


  var QUOTING_TYPE_SINGLE = 1,
      QUOTING_TYPE_DOUBLE = 2;

  function State(options) {
    this.schema        = options['schema'] || _default;
    this.indent        = Math.max(1, (options['indent'] || 2));
    this.noArrayIndent = options['noArrayIndent'] || false;
    this.skipInvalid   = options['skipInvalid'] || false;
    this.flowLevel     = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']);
    this.styleMap      = compileStyleMap(this.schema, options['styles'] || null);
    this.sortKeys      = options['sortKeys'] || false;
    this.lineWidth     = options['lineWidth'] || 80;
    this.noRefs        = options['noRefs'] || false;
    this.noCompatMode  = options['noCompatMode'] || false;
    this.condenseFlow  = options['condenseFlow'] || false;
    this.quotingType   = options['quotingType'] === '"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE;
    this.forceQuotes   = options['forceQuotes'] || false;
    this.replacer      = typeof options['replacer'] === 'function' ? options['replacer'] : null;

    this.implicitTypes = this.schema.compiledImplicit;
    this.explicitTypes = this.schema.compiledExplicit;

    this.tag = null;
    this.result = '';

    this.duplicates = [];
    this.usedDuplicates = null;
  }

  // Indents every line in a string. Empty lines (\n only) are not indented.
  function indentString(string, spaces) {
    var ind = common.repeat(' ', spaces),
        position = 0,
        next = -1,
        result = '',
        line,
        length = string.length;

    while (position < length) {
      next = string.indexOf('\n', position);
      if (next === -1) {
        line = string.slice(position);
        position = length;
      } else {
        line = string.slice(position, next + 1);
        position = next + 1;
      }

      if (line.length && line !== '\n') result += ind;

      result += line;
    }

    return result;
  }

  function generateNextLine(state, level) {
    return '\n' + common.repeat(' ', state.indent * level);
  }

  function testImplicitResolving(state, str) {
    var index, length, type;

    for (index = 0, length = state.implicitTypes.length; index < length; index += 1) {
      type = state.implicitTypes[index];

      if (type.resolve(str)) {
        return true;
      }
    }

    return false;
  }

  // [33] s-white ::= s-space | s-tab
  function isWhitespace(c) {
    return c === CHAR_SPACE || c === CHAR_TAB;
  }

  // Returns true if the character can be printed without escaping.
  // From YAML 1.2: "any allowed characters known to be non-printable
  // should also be escaped. [However,] This isn’t mandatory"
  // Derived from nb-char - \t - #x85 - #xA0 - #x2028 - #x2029.
  function isPrintable(c) {
    return  (0x00020 <= c && c <= 0x00007E)
        || ((0x000A1 <= c && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029)
        || ((0x0E000 <= c && c <= 0x00FFFD) && c !== CHAR_BOM)
        ||  (0x10000 <= c && c <= 0x10FFFF);
  }

  // [34] ns-char ::= nb-char - s-white
  // [27] nb-char ::= c-printable - b-char - c-byte-order-mark
  // [26] b-char  ::= b-line-feed | b-carriage-return
  // Including s-white (for some reason, examples doesn't match specs in this aspect)
  // ns-char ::= c-printable - b-line-feed - b-carriage-return - c-byte-order-mark
  function isNsCharOrWhitespace(c) {
    return isPrintable(c)
      && c !== CHAR_BOM
      // - b-char
      && c !== CHAR_CARRIAGE_RETURN
      && c !== CHAR_LINE_FEED;
  }

  // [127]  ns-plain-safe(c) ::= c = flow-out  ⇒ ns-plain-safe-out
  //                             c = flow-in   ⇒ ns-plain-safe-in
  //                             c = block-key ⇒ ns-plain-safe-out
  //                             c = flow-key  ⇒ ns-plain-safe-in
  // [128] ns-plain-safe-out ::= ns-char
  // [129]  ns-plain-safe-in ::= ns-char - c-flow-indicator
  // [130]  ns-plain-char(c) ::=  ( ns-plain-safe(c) - “:” - “#” )
  //                            | ( /* An ns-char preceding */ “#” )
  //                            | ( “:” /* Followed by an ns-plain-safe(c) */ )
  function isPlainSafe(c, prev, inblock) {
    var cIsNsCharOrWhitespace = isNsCharOrWhitespace(c);
    var cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c);
    return (
      // ns-plain-safe
      inblock ? // c = flow-in
        cIsNsCharOrWhitespace
        : cIsNsCharOrWhitespace
          // - c-flow-indicator
          && c !== CHAR_COMMA
          && c !== CHAR_LEFT_SQUARE_BRACKET
          && c !== CHAR_RIGHT_SQUARE_BRACKET
          && c !== CHAR_LEFT_CURLY_BRACKET
          && c !== CHAR_RIGHT_CURLY_BRACKET
    )
      // ns-plain-char
      && c !== CHAR_SHARP // false on '#'
      && !(prev === CHAR_COLON && !cIsNsChar) // false on ': '
      || (isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP) // change to true on '[^ ]#'
      || (prev === CHAR_COLON && cIsNsChar); // change to true on ':[^ ]'
  }

  // Simplified test for values allowed as the first character in plain style.
  function isPlainSafeFirst(c) {
    // Uses a subset of ns-char - c-indicator
    // where ns-char = nb-char - s-white.
    // No support of ( ( “?” | “:” | “-” ) /* Followed by an ns-plain-safe(c)) */ ) part
    return isPrintable(c) && c !== CHAR_BOM
      && !isWhitespace(c) // - s-white
      // - (c-indicator ::=
      // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”
      && c !== CHAR_MINUS
      && c !== CHAR_QUESTION
      && c !== CHAR_COLON
      && c !== CHAR_COMMA
      && c !== CHAR_LEFT_SQUARE_BRACKET
      && c !== CHAR_RIGHT_SQUARE_BRACKET
      && c !== CHAR_LEFT_CURLY_BRACKET
      && c !== CHAR_RIGHT_CURLY_BRACKET
      // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “"”
      && c !== CHAR_SHARP
      && c !== CHAR_AMPERSAND
      && c !== CHAR_ASTERISK
      && c !== CHAR_EXCLAMATION
      && c !== CHAR_VERTICAL_LINE
      && c !== CHAR_EQUALS
      && c !== CHAR_GREATER_THAN
      && c !== CHAR_SINGLE_QUOTE
      && c !== CHAR_DOUBLE_QUOTE
      // | “%” | “@” | “`”)
      && c !== CHAR_PERCENT
      && c !== CHAR_COMMERCIAL_AT
      && c !== CHAR_GRAVE_ACCENT;
  }

  // Simplified test for values allowed as the last character in plain style.
  function isPlainSafeLast(c) {
    // just not whitespace or colon, it will be checked to be plain character later
    return !isWhitespace(c) && c !== CHAR_COLON;
  }

  // Same as 'string'.codePointAt(pos), but works in older browsers.
  function codePointAt(string, pos) {
    var first = string.charCodeAt(pos), second;
    if (first >= 0xD800 && first <= 0xDBFF && pos + 1 < string.length) {
      second = string.charCodeAt(pos + 1);
      if (second >= 0xDC00 && second <= 0xDFFF) {
        // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
        return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
      }
    }
    return first;
  }

  // Determines whether block indentation indicator is required.
  function needIndentIndicator(string) {
    var leadingSpaceRe = /^\n* /;
    return leadingSpaceRe.test(string);
  }

  var STYLE_PLAIN   = 1,
      STYLE_SINGLE  = 2,
      STYLE_LITERAL = 3,
      STYLE_FOLDED  = 4,
      STYLE_DOUBLE  = 5;

  // Determines which scalar styles are possible and returns the preferred style.
  // lineWidth = -1 => no limit.
  // Pre-conditions: str.length > 0.
  // Post-conditions:
  //    STYLE_PLAIN or STYLE_SINGLE => no \n are in the string.
  //    STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).
  //    STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).
  function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth,
    testAmbiguousType, quotingType, forceQuotes, inblock) {

    var i;
    var char = 0;
    var prevChar = null;
    var hasLineBreak = false;
    var hasFoldableLine = false; // only checked if shouldTrackWidth
    var shouldTrackWidth = lineWidth !== -1;
    var previousLineBreak = -1; // count the first line correctly
    var plain = isPlainSafeFirst(codePointAt(string, 0))
            && isPlainSafeLast(codePointAt(string, string.length - 1));

    if (singleLineOnly || forceQuotes) {
      // Case: no block styles.
      // Check for disallowed characters to rule out plain and single.
      for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
        char = codePointAt(string, i);
        if (!isPrintable(char)) {
          return STYLE_DOUBLE;
        }
        plain = plain && isPlainSafe(char, prevChar, inblock);
        prevChar = char;
      }
    } else {
      // Case: block styles permitted.
      for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
        char = codePointAt(string, i);
        if (char === CHAR_LINE_FEED) {
          hasLineBreak = true;
          // Check if any line can be folded.
          if (shouldTrackWidth) {
            hasFoldableLine = hasFoldableLine ||
              // Foldable line = too long, and not more-indented.
              (i - previousLineBreak - 1 > lineWidth &&
               string[previousLineBreak + 1] !== ' ');
            previousLineBreak = i;
          }
        } else if (!isPrintable(char)) {
          return STYLE_DOUBLE;
        }
        plain = plain && isPlainSafe(char, prevChar, inblock);
        prevChar = char;
      }
      // in case the end is missing a \n
      hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&
        (i - previousLineBreak - 1 > lineWidth &&
         string[previousLineBreak + 1] !== ' '));
    }
    // Although every style can represent \n without escaping, prefer block styles
    // for multiline, since they're more readable and they don't add empty lines.
    // Also prefer folding a super-long line.
    if (!hasLineBreak && !hasFoldableLine) {
      // Strings interpretable as another type have to be quoted;
      // e.g. the string 'true' vs. the boolean true.
      if (plain && !forceQuotes && !testAmbiguousType(string)) {
        return STYLE_PLAIN;
      }
      return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
    }
    // Edge case: block indentation indicator can only have one digit.
    if (indentPerLevel > 9 && needIndentIndicator(string)) {
      return STYLE_DOUBLE;
    }
    // At this point we know block styles are valid.
    // Prefer literal style unless we want to fold.
    if (!forceQuotes) {
      return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
    }
    return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
  }

  // Note: line breaking/folding is implemented for only the folded style.
  // NB. We drop the last trailing newline (if any) of a returned block scalar
  //  since the dumper adds its own newline. This always works:
  //    • No ending newline => unaffected; already using strip "-" chomping.
  //    • Ending newline    => removed then restored.
  //  Importantly, this keeps the "+" chomp indicator from gaining an extra line.
  function writeScalar(state, string, level, iskey, inblock) {
    state.dump = (function () {
      if (string.length === 0) {
        return state.quotingType === QUOTING_TYPE_DOUBLE ? '""' : "''";
      }
      if (!state.noCompatMode) {
        if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) {
          return state.quotingType === QUOTING_TYPE_DOUBLE ? ('"' + string + '"') : ("'" + string + "'");
        }
      }

      var indent = state.indent * Math.max(1, level); // no 0-indent scalars
      // As indentation gets deeper, let the width decrease monotonically
      // to the lower bound min(state.lineWidth, 40).
      // Note that this implies
      //  state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.
      //  state.lineWidth > 40 + state.indent: width decreases until the lower bound.
      // This behaves better than a constant minimum width which disallows narrower options,
      // or an indent threshold which causes the width to suddenly increase.
      var lineWidth = state.lineWidth === -1
        ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);

      // Without knowing if keys are implicit/explicit, assume implicit for safety.
      var singleLineOnly = iskey
        // No block styles in flow mode.
        || (state.flowLevel > -1 && level >= state.flowLevel);
      function testAmbiguity(string) {
        return testImplicitResolving(state, string);
      }

      switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth,
        testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) {

        case STYLE_PLAIN:
          return string;
        case STYLE_SINGLE:
          return "'" + string.replace(/'/g, "''") + "'";
        case STYLE_LITERAL:
          return '|' + blockHeader(string, state.indent)
            + dropEndingNewline(indentString(string, indent));
        case STYLE_FOLDED:
          return '>' + blockHeader(string, state.indent)
            + dropEndingNewline(indentString(foldString(string, lineWidth), indent));
        case STYLE_DOUBLE:
          return '"' + escapeString(string) + '"';
        default:
          throw new exception('impossible error: invalid scalar style');
      }
    }());
  }

  // Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.
  function blockHeader(string, indentPerLevel) {
    var indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : '';

    // note the special case: the string '\n' counts as a "trailing" empty line.
    var clip =          string[string.length - 1] === '\n';
    var keep = clip && (string[string.length - 2] === '\n' || string === '\n');
    var chomp = keep ? '+' : (clip ? '' : '-');

    return indentIndicator + chomp + '\n';
  }

  // (See the note for writeScalar.)
  function dropEndingNewline(string) {
    return string[string.length - 1] === '\n' ? string.slice(0, -1) : string;
  }

  // Note: a long line without a suitable break point will exceed the width limit.
  // Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.
  function foldString(string, width) {
    // In folded style, $k$ consecutive newlines output as $k+1$ newlines—
    // unless they're before or after a more-indented line, or at the very
    // beginning or end, in which case $k$ maps to $k$.
    // Therefore, parse each chunk as newline(s) followed by a content line.
    var lineRe = /(\n+)([^\n]*)/g;

    // first line (possibly an empty line)
    var result = (function () {
      var nextLF = string.indexOf('\n');
      nextLF = nextLF !== -1 ? nextLF : string.length;
      lineRe.lastIndex = nextLF;
      return foldLine(string.slice(0, nextLF), width);
    }());
    // If we haven't reached the first content line yet, don't add an extra \n.
    var prevMoreIndented = string[0] === '\n' || string[0] === ' ';
    var moreIndented;

    // rest of the lines
    var match;
    while ((match = lineRe.exec(string))) {
      var prefix = match[1], line = match[2];
      moreIndented = (line[0] === ' ');
      result += prefix
        + (!prevMoreIndented && !moreIndented && line !== ''
          ? '\n' : '')
        + foldLine(line, width);
      prevMoreIndented = moreIndented;
    }

    return result;
  }

  // Greedy line breaking.
  // Picks the longest line under the limit each time,
  // otherwise settles for the shortest line over the limit.
  // NB. More-indented lines *cannot* be folded, as that would add an extra \n.
  function foldLine(line, width) {
    if (line === '' || line[0] === ' ') return line;

    // Since a more-indented line adds a \n, breaks can't be followed by a space.
    var breakRe = / [^ ]/g; // note: the match index will always be <= length-2.
    var match;
    // start is an inclusive index. end, curr, and next are exclusive.
    var start = 0, end, curr = 0, next = 0;
    var result = '';

    // Invariants: 0 <= start <= length-1.
    //   0 <= curr <= next <= max(0, length-2). curr - start <= width.
    // Inside the loop:
    //   A match implies length >= 2, so curr and next are <= length-2.
    while ((match = breakRe.exec(line))) {
      next = match.index;
      // maintain invariant: curr - start <= width
      if (next - start > width) {
        end = (curr > start) ? curr : next; // derive end <= length-2
        result += '\n' + line.slice(start, end);
        // skip the space that was output as \n
        start = end + 1;                    // derive start <= length-1
      }
      curr = next;
    }

    // By the invariants, start <= length-1, so there is something left over.
    // It is either the whole string or a part starting from non-whitespace.
    result += '\n';
    // Insert a break if the remainder is too long and there is a break available.
    if (line.length - start > width && curr > start) {
      result += line.slice(start, curr) + '\n' + line.slice(curr + 1);
    } else {
      result += line.slice(start);
    }

    return result.slice(1); // drop extra \n joiner
  }

  // Escapes a double-quoted string.
  function escapeString(string) {
    var result = '';
    var char = 0;
    var escapeSeq;

    for (var i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
      char = codePointAt(string, i);
      escapeSeq = ESCAPE_SEQUENCES[char];

      if (!escapeSeq && isPrintable(char)) {
        result += string[i];
        if (char >= 0x10000) result += string[i + 1];
      } else {
        result += escapeSeq || encodeHex(char);
      }
    }

    return result;
  }

  function writeFlowSequence(state, level, object) {
    var _result = '',
        _tag    = state.tag,
        index,
        length,
        value;

    for (index = 0, length = object.length; index < length; index += 1) {
      value = object[index];

      if (state.replacer) {
        value = state.replacer.call(object, String(index), value);
      }

      // Write only valid elements, put null instead of invalid elements.
      if (writeNode(state, level, value, false, false) ||
          (typeof value === 'undefined' &&
           writeNode(state, level, null, false, false))) {

        if (_result !== '') _result += ',' + (!state.condenseFlow ? ' ' : '');
        _result += state.dump;
      }
    }

    state.tag = _tag;
    state.dump = '[' + _result + ']';
  }

  function writeBlockSequence(state, level, object, compact) {
    var _result = '',
        _tag    = state.tag,
        index,
        length,
        value;

    for (index = 0, length = object.length; index < length; index += 1) {
      value = object[index];

      if (state.replacer) {
        value = state.replacer.call(object, String(index), value);
      }

      // Write only valid elements, put null instead of invalid elements.
      if (writeNode(state, level + 1, value, true, true, false, true) ||
          (typeof value === 'undefined' &&
           writeNode(state, level + 1, null, true, true, false, true))) {

        if (!compact || _result !== '') {
          _result += generateNextLine(state, level);
        }

        if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
          _result += '-';
        } else {
          _result += '- ';
        }

        _result += state.dump;
      }
    }

    state.tag = _tag;
    state.dump = _result || '[]'; // Empty sequence if no valid values.
  }

  function writeFlowMapping(state, level, object) {
    var _result       = '',
        _tag          = state.tag,
        objectKeyList = Object.keys(object),
        index,
        length,
        objectKey,
        objectValue,
        pairBuffer;

    for (index = 0, length = objectKeyList.length; index < length; index += 1) {

      pairBuffer = '';
      if (_result !== '') pairBuffer += ', ';

      if (state.condenseFlow) pairBuffer += '"';

      objectKey = objectKeyList[index];
      objectValue = object[objectKey];

      if (state.replacer) {
        objectValue = state.replacer.call(object, objectKey, objectValue);
      }

      if (!writeNode(state, level, objectKey, false, false)) {
        continue; // Skip this pair because of invalid key;
      }

      if (state.dump.length > 1024) pairBuffer += '? ';

      pairBuffer += state.dump + (state.condenseFlow ? '"' : '') + ':' + (state.condenseFlow ? '' : ' ');

      if (!writeNode(state, level, objectValue, false, false)) {
        continue; // Skip this pair because of invalid value.
      }

      pairBuffer += state.dump;

      // Both key and value are valid.
      _result += pairBuffer;
    }

    state.tag = _tag;
    state.dump = '{' + _result + '}';
  }

  function writeBlockMapping(state, level, object, compact) {
    var _result       = '',
        _tag          = state.tag,
        objectKeyList = Object.keys(object),
        index,
        length,
        objectKey,
        objectValue,
        explicitPair,
        pairBuffer;

    // Allow sorting keys so that the output file is deterministic
    if (state.sortKeys === true) {
      // Default sorting
      objectKeyList.sort();
    } else if (typeof state.sortKeys === 'function') {
      // Custom sort function
      objectKeyList.sort(state.sortKeys);
    } else if (state.sortKeys) {
      // Something is wrong
      throw new exception('sortKeys must be a boolean or a function');
    }

    for (index = 0, length = objectKeyList.length; index < length; index += 1) {
      pairBuffer = '';

      if (!compact || _result !== '') {
        pairBuffer += generateNextLine(state, level);
      }

      objectKey = objectKeyList[index];
      objectValue = object[objectKey];

      if (state.replacer) {
        objectValue = state.replacer.call(object, objectKey, objectValue);
      }

      if (!writeNode(state, level + 1, objectKey, true, true, true)) {
        continue; // Skip this pair because of invalid key.
      }

      explicitPair = (state.tag !== null && state.tag !== '?') ||
                     (state.dump && state.dump.length > 1024);

      if (explicitPair) {
        if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
          pairBuffer += '?';
        } else {
          pairBuffer += '? ';
        }
      }

      pairBuffer += state.dump;

      if (explicitPair) {
        pairBuffer += generateNextLine(state, level);
      }

      if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
        continue; // Skip this pair because of invalid value.
      }

      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
        pairBuffer += ':';
      } else {
        pairBuffer += ': ';
      }

      pairBuffer += state.dump;

      // Both key and value are valid.
      _result += pairBuffer;
    }

    state.tag = _tag;
    state.dump = _result || '{}'; // Empty mapping if no valid pairs.
  }

  function detectType(state, object, explicit) {
    var _result, typeList, index, length, type, style;

    typeList = explicit ? state.explicitTypes : state.implicitTypes;

    for (index = 0, length = typeList.length; index < length; index += 1) {
      type = typeList[index];

      if ((type.instanceOf  || type.predicate) &&
          (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&
          (!type.predicate  || type.predicate(object))) {

        if (explicit) {
          if (type.multi && type.representName) {
            state.tag = type.representName(object);
          } else {
            state.tag = type.tag;
          }
        } else {
          state.tag = '?';
        }

        if (type.represent) {
          style = state.styleMap[type.tag] || type.defaultStyle;

          if (_toString.call(type.represent) === '[object Function]') {
            _result = type.represent(object, style);
          } else if (_hasOwnProperty.call(type.represent, style)) {
            _result = type.represent[style](object, style);
          } else {
            throw new exception('!<' + type.tag + '> tag resolver accepts not "' + style + '" style');
          }

          state.dump = _result;
        }

        return true;
      }
    }

    return false;
  }

  // Serializes `object` and writes it to global `result`.
  // Returns true on success, or false on invalid object.
  //
  function writeNode(state, level, object, block, compact, iskey, isblockseq) {
    state.tag = null;
    state.dump = object;

    if (!detectType(state, object, false)) {
      detectType(state, object, true);
    }

    var type = _toString.call(state.dump);
    var inblock = block;
    var tagStr;

    if (block) {
      block = (state.flowLevel < 0 || state.flowLevel > level);
    }

    var objectOrArray = type === '[object Object]' || type === '[object Array]',
        duplicateIndex,
        duplicate;

    if (objectOrArray) {
      duplicateIndex = state.duplicates.indexOf(object);
      duplicate = duplicateIndex !== -1;
    }

    if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {
      compact = false;
    }

    if (duplicate && state.usedDuplicates[duplicateIndex]) {
      state.dump = '*ref_' + duplicateIndex;
    } else {
      if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
        state.usedDuplicates[duplicateIndex] = true;
      }
      if (type === '[object Object]') {
        if (block && (Object.keys(state.dump).length !== 0)) {
          writeBlockMapping(state, level, state.dump, compact);
          if (duplicate) {
            state.dump = '&ref_' + duplicateIndex + state.dump;
          }
        } else {
          writeFlowMapping(state, level, state.dump);
          if (duplicate) {
            state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
          }
        }
      } else if (type === '[object Array]') {
        if (block && (state.dump.length !== 0)) {
          if (state.noArrayIndent && !isblockseq && level > 0) {
            writeBlockSequence(state, level - 1, state.dump, compact);
          } else {
            writeBlockSequence(state, level, state.dump, compact);
          }
          if (duplicate) {
            state.dump = '&ref_' + duplicateIndex + state.dump;
          }
        } else {
          writeFlowSequence(state, level, state.dump);
          if (duplicate) {
            state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
          }
        }
      } else if (type === '[object String]') {
        if (state.tag !== '?') {
          writeScalar(state, state.dump, level, iskey, inblock);
        }
      } else if (type === '[object Undefined]') {
        return false;
      } else {
        if (state.skipInvalid) return false;
        throw new exception('unacceptable kind of an object to dump ' + type);
      }

      if (state.tag !== null && state.tag !== '?') {
        // Need to encode all characters except those allowed by the spec:
        //
        // [35] ns-dec-digit    ::=  [#x30-#x39] /* 0-9 */
        // [36] ns-hex-digit    ::=  ns-dec-digit
        //                         | [#x41-#x46] /* A-F */ | [#x61-#x66] /* a-f */
        // [37] ns-ascii-letter ::=  [#x41-#x5A] /* A-Z */ | [#x61-#x7A] /* a-z */
        // [38] ns-word-char    ::=  ns-dec-digit | ns-ascii-letter | “-”
        // [39] ns-uri-char     ::=  “%” ns-hex-digit ns-hex-digit | ns-word-char | “#”
        //                         | “;” | “/” | “?” | “:” | “@” | “&” | “=” | “+” | “$” | “,”
        //                         | “_” | “.” | “!” | “~” | “*” | “'” | “(” | “)” | “[” | “]”
        //
        // Also need to encode '!' because it has special meaning (end of tag prefix).
        //
        tagStr = encodeURI(
          state.tag[0] === '!' ? state.tag.slice(1) : state.tag
        ).replace(/!/g, '%21');

        if (state.tag[0] === '!') {
          tagStr = '!' + tagStr;
        } else if (tagStr.slice(0, 18) === 'tag:yaml.org,2002:') {
          tagStr = '!!' + tagStr.slice(18);
        } else {
          tagStr = '!<' + tagStr + '>';
        }

        state.dump = tagStr + ' ' + state.dump;
      }
    }

    return true;
  }

  function getDuplicateReferences(object, state) {
    var objects = [],
        duplicatesIndexes = [],
        index,
        length;

    inspectNode(object, objects, duplicatesIndexes);

    for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) {
      state.duplicates.push(objects[duplicatesIndexes[index]]);
    }
    state.usedDuplicates = new Array(length);
  }

  function inspectNode(object, objects, duplicatesIndexes) {
    var objectKeyList,
        index,
        length;

    if (object !== null && typeof object === 'object') {
      index = objects.indexOf(object);
      if (index !== -1) {
        if (duplicatesIndexes.indexOf(index) === -1) {
          duplicatesIndexes.push(index);
        }
      } else {
        objects.push(object);

        if (Array.isArray(object)) {
          for (index = 0, length = object.length; index < length; index += 1) {
            inspectNode(object[index], objects, duplicatesIndexes);
          }
        } else {
          objectKeyList = Object.keys(object);

          for (index = 0, length = objectKeyList.length; index < length; index += 1) {
            inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes);
          }
        }
      }
    }
  }

  function dump$1(input, options) {
    options = options || {};

    var state = new State(options);

    if (!state.noRefs) getDuplicateReferences(input, state);

    var value = input;

    if (state.replacer) {
      value = state.replacer.call({ '': value }, '', value);
    }

    if (writeNode(state, 0, value, true, true)) return state.dump + '\n';

    return '';
  }

  var dump_1 = dump$1;

  var dumper = {
  	dump: dump_1
  };

  function renamed(from, to) {
    return function () {
      throw new Error('Function yaml.' + from + ' is removed in js-yaml 4. ' +
        'Use yaml.' + to + ' instead, which is now safe by default.');
    };
  }


  var Type                = type;
  var Schema              = schema;
  var FAILSAFE_SCHEMA     = failsafe;
  var JSON_SCHEMA         = json;
  var CORE_SCHEMA         = core;
  var DEFAULT_SCHEMA      = _default;
  var load                = loader.load;
  var loadAll             = loader.loadAll;
  var dump                = dumper.dump;
  var YAMLException       = exception;

  // Re-export all types in case user wants to create custom schema
  var types = {
    binary:    binary,
    float:     float,
    map:       map,
    null:      _null,
    pairs:     pairs,
    set:       set,
    timestamp: timestamp,
    bool:      bool,
    int:       int,
    merge:     merge,
    omap:      omap,
    seq:       seq,
    str:       str
  };

  // Removed functions from JS-YAML 3.0.x
  var safeLoad            = renamed('safeLoad', 'load');
  var safeLoadAll         = renamed('safeLoadAll', 'loadAll');
  var safeDump            = renamed('safeDump', 'dump');

  var jsYaml = {
  	Type: Type,
  	Schema: Schema,
  	FAILSAFE_SCHEMA: FAILSAFE_SCHEMA,
  	JSON_SCHEMA: JSON_SCHEMA,
  	CORE_SCHEMA: CORE_SCHEMA,
  	DEFAULT_SCHEMA: DEFAULT_SCHEMA,
  	load: load,
  	loadAll: loadAll,
  	dump: dump,
  	YAMLException: YAMLException,
  	types: types,
  	safeLoad: safeLoad,
  	safeLoadAll: safeLoadAll,
  	safeDump: safeDump
  };

  exports.CORE_SCHEMA = CORE_SCHEMA;
  exports.DEFAULT_SCHEMA = DEFAULT_SCHEMA;
  exports.FAILSAFE_SCHEMA = FAILSAFE_SCHEMA;
  exports.JSON_SCHEMA = JSON_SCHEMA;
  exports.Schema = Schema;
  exports.Type = Type;
  exports.YAMLException = YAMLException;
  exports.default = jsYaml;
  exports.dump = dump;
  exports.load = load;
  exports.loadAll = loadAll;
  exports.safeDump = safeDump;
  exports.safeLoad = safeLoad;
  exports.safeLoadAll = safeLoadAll;
  exports.types = types;

  Object.defineProperty(exports, '__esModule', { value: true });

})));
/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).jsyaml={})}(this,(function(e){"use strict";function t(e){return null==e}var n={isNothing:t,isObject:function(e){return"object"==typeof e&&null!==e},toArray:function(e){return Array.isArray(e)?e:t(e)?[]:[e]},repeat:function(e,t){var n,i="";for(n=0;n<t;n+=1)i+=e;return i},isNegativeZero:function(e){return 0===e&&Number.NEGATIVE_INFINITY===1/e},extend:function(e,t){var n,i,r,o;if(t)for(n=0,i=(o=Object.keys(t)).length;n<i;n+=1)e[r=o[n]]=t[r];return e}};function i(e,t){var n="",i=e.reason||"(unknown reason)";return e.mark?(e.mark.name&&(n+='in "'+e.mark.name+'" '),n+="("+(e.mark.line+1)+":"+(e.mark.column+1)+")",!t&&e.mark.snippet&&(n+="\n\n"+e.mark.snippet),i+" "+n):i}function r(e,t){Error.call(this),this.name="YAMLException",this.reason=e,this.mark=t,this.message=i(this,!1),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack||""}r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r.prototype.toString=function(e){return this.name+": "+i(this,e)};var o=r;function a(e,t,n,i,r){var o="",a="",l=Math.floor(r/2)-1;return i-t>l&&(t=i-l+(o=" ... ").length),n-i>l&&(n=i+l-(a=" ...").length),{str:o+e.slice(t,n).replace(/\t/g,"→")+a,pos:i-t+o.length}}function l(e,t){return n.repeat(" ",t-e.length)+e}var c=function(e,t){if(t=Object.create(t||null),!e.buffer)return null;t.maxLength||(t.maxLength=79),"number"!=typeof t.indent&&(t.indent=1),"number"!=typeof t.linesBefore&&(t.linesBefore=3),"number"!=typeof t.linesAfter&&(t.linesAfter=2);for(var i,r=/\r?\n|\r|\0/g,o=[0],c=[],s=-1;i=r.exec(e.buffer);)c.push(i.index),o.push(i.index+i[0].length),e.position<=i.index&&s<0&&(s=o.length-2);s<0&&(s=o.length-1);var u,p,f="",d=Math.min(e.line+t.linesAfter,c.length).toString().length,h=t.maxLength-(t.indent+d+3);for(u=1;u<=t.linesBefore&&!(s-u<0);u++)p=a(e.buffer,o[s-u],c[s-u],e.position-(o[s]-o[s-u]),h),f=n.repeat(" ",t.indent)+l((e.line-u+1).toString(),d)+" | "+p.str+"\n"+f;for(p=a(e.buffer,o[s],c[s],e.position,h),f+=n.repeat(" ",t.indent)+l((e.line+1).toString(),d)+" | "+p.str+"\n",f+=n.repeat("-",t.indent+d+3+p.pos)+"^\n",u=1;u<=t.linesAfter&&!(s+u>=c.length);u++)p=a(e.buffer,o[s+u],c[s+u],e.position-(o[s]-o[s+u]),h),f+=n.repeat(" ",t.indent)+l((e.line+u+1).toString(),d)+" | "+p.str+"\n";return f.replace(/\n$/,"")},s=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],u=["scalar","sequence","mapping"];var p=function(e,t){if(t=t||{},Object.keys(t).forEach((function(t){if(-1===s.indexOf(t))throw new o('Unknown option "'+t+'" is met in definition of "'+e+'" YAML type.')})),this.options=t,this.tag=e,this.kind=t.kind||null,this.resolve=t.resolve||function(){return!0},this.construct=t.construct||function(e){return e},this.instanceOf=t.instanceOf||null,this.predicate=t.predicate||null,this.represent=t.represent||null,this.representName=t.representName||null,this.defaultStyle=t.defaultStyle||null,this.multi=t.multi||!1,this.styleAliases=function(e){var t={};return null!==e&&Object.keys(e).forEach((function(n){e[n].forEach((function(e){t[String(e)]=n}))})),t}(t.styleAliases||null),-1===u.indexOf(this.kind))throw new o('Unknown kind "'+this.kind+'" is specified for "'+e+'" YAML type.')};function f(e,t){var n=[];return e[t].forEach((function(e){var t=n.length;n.forEach((function(n,i){n.tag===e.tag&&n.kind===e.kind&&n.multi===e.multi&&(t=i)})),n[t]=e})),n}function d(e){return this.extend(e)}d.prototype.extend=function(e){var t=[],n=[];if(e instanceof p)n.push(e);else if(Array.isArray(e))n=n.concat(e);else{if(!e||!Array.isArray(e.implicit)&&!Array.isArray(e.explicit))throw new o("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })");e.implicit&&(t=t.concat(e.implicit)),e.explicit&&(n=n.concat(e.explicit))}t.forEach((function(e){if(!(e instanceof p))throw new o("Specified list of YAML types (or a single Type object) contains a non-Type object.");if(e.loadKind&&"scalar"!==e.loadKind)throw new o("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.");if(e.multi)throw new o("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.")})),n.forEach((function(e){if(!(e instanceof p))throw new o("Specified list of YAML types (or a single Type object) contains a non-Type object.")}));var i=Object.create(d.prototype);return i.implicit=(this.implicit||[]).concat(t),i.explicit=(this.explicit||[]).concat(n),i.compiledImplicit=f(i,"implicit"),i.compiledExplicit=f(i,"explicit"),i.compiledTypeMap=function(){var e,t,n={scalar:{},sequence:{},mapping:{},fallback:{},multi:{scalar:[],sequence:[],mapping:[],fallback:[]}};function i(e){e.multi?(n.multi[e.kind].push(e),n.multi.fallback.push(e)):n[e.kind][e.tag]=n.fallback[e.tag]=e}for(e=0,t=arguments.length;e<t;e+=1)arguments[e].forEach(i);return n}(i.compiledImplicit,i.compiledExplicit),i};var h=d,g=new p("tag:yaml.org,2002:str",{kind:"scalar",construct:function(e){return null!==e?e:""}}),m=new p("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(e){return null!==e?e:[]}}),y=new p("tag:yaml.org,2002:map",{kind:"mapping",construct:function(e){return null!==e?e:{}}}),b=new h({explicit:[g,m,y]});var A=new p("tag:yaml.org,2002:null",{kind:"scalar",resolve:function(e){if(null===e)return!0;var t=e.length;return 1===t&&"~"===e||4===t&&("null"===e||"Null"===e||"NULL"===e)},construct:function(){return null},predicate:function(e){return null===e},represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"},empty:function(){return""}},defaultStyle:"lowercase"});var v=new p("tag:yaml.org,2002:bool",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t=e.length;return 4===t&&("true"===e||"True"===e||"TRUE"===e)||5===t&&("false"===e||"False"===e||"FALSE"===e)},construct:function(e){return"true"===e||"True"===e||"TRUE"===e},predicate:function(e){return"[object Boolean]"===Object.prototype.toString.call(e)},represent:{lowercase:function(e){return e?"true":"false"},uppercase:function(e){return e?"TRUE":"FALSE"},camelcase:function(e){return e?"True":"False"}},defaultStyle:"lowercase"});function w(e){return 48<=e&&e<=55}function k(e){return 48<=e&&e<=57}var C=new p("tag:yaml.org,2002:int",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t,n,i=e.length,r=0,o=!1;if(!i)return!1;if("-"!==(t=e[r])&&"+"!==t||(t=e[++r]),"0"===t){if(r+1===i)return!0;if("b"===(t=e[++r])){for(r++;r<i;r++)if("_"!==(t=e[r])){if("0"!==t&&"1"!==t)return!1;o=!0}return o&&"_"!==t}if("x"===t){for(r++;r<i;r++)if("_"!==(t=e[r])){if(!(48<=(n=e.charCodeAt(r))&&n<=57||65<=n&&n<=70||97<=n&&n<=102))return!1;o=!0}return o&&"_"!==t}if("o"===t){for(r++;r<i;r++)if("_"!==(t=e[r])){if(!w(e.charCodeAt(r)))return!1;o=!0}return o&&"_"!==t}}if("_"===t)return!1;for(;r<i;r++)if("_"!==(t=e[r])){if(!k(e.charCodeAt(r)))return!1;o=!0}return!(!o||"_"===t)},construct:function(e){var t,n=e,i=1;if(-1!==n.indexOf("_")&&(n=n.replace(/_/g,"")),"-"!==(t=n[0])&&"+"!==t||("-"===t&&(i=-1),t=(n=n.slice(1))[0]),"0"===n)return 0;if("0"===t){if("b"===n[1])return i*parseInt(n.slice(2),2);if("x"===n[1])return i*parseInt(n.slice(2),16);if("o"===n[1])return i*parseInt(n.slice(2),8)}return i*parseInt(n,10)},predicate:function(e){return"[object Number]"===Object.prototype.toString.call(e)&&e%1==0&&!n.isNegativeZero(e)},represent:{binary:function(e){return e>=0?"0b"+e.toString(2):"-0b"+e.toString(2).slice(1)},octal:function(e){return e>=0?"0o"+e.toString(8):"-0o"+e.toString(8).slice(1)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return e>=0?"0x"+e.toString(16).toUpperCase():"-0x"+e.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}}),x=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");var I=/^[-+]?[0-9]+e/;var S=new p("tag:yaml.org,2002:float",{kind:"scalar",resolve:function(e){return null!==e&&!(!x.test(e)||"_"===e[e.length-1])},construct:function(e){var t,n;return n="-"===(t=e.replace(/_/g,"").toLowerCase())[0]?-1:1,"+-".indexOf(t[0])>=0&&(t=t.slice(1)),".inf"===t?1===n?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:".nan"===t?NaN:n*parseFloat(t,10)},predicate:function(e){return"[object Number]"===Object.prototype.toString.call(e)&&(e%1!=0||n.isNegativeZero(e))},represent:function(e,t){var i;if(isNaN(e))switch(t){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===e)switch(t){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===e)switch(t){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(n.isNegativeZero(e))return"-0.0";return i=e.toString(10),I.test(i)?i.replace("e",".e"):i},defaultStyle:"lowercase"}),O=b.extend({implicit:[A,v,C,S]}),j=O,T=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),N=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");var F=new p("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:function(e){return null!==e&&(null!==T.exec(e)||null!==N.exec(e))},construct:function(e){var t,n,i,r,o,a,l,c,s=0,u=null;if(null===(t=T.exec(e))&&(t=N.exec(e)),null===t)throw new Error("Date resolve error");if(n=+t[1],i=+t[2]-1,r=+t[3],!t[4])return new Date(Date.UTC(n,i,r));if(o=+t[4],a=+t[5],l=+t[6],t[7]){for(s=t[7].slice(0,3);s.length<3;)s+="0";s=+s}return t[9]&&(u=6e4*(60*+t[10]+ +(t[11]||0)),"-"===t[9]&&(u=-u)),c=new Date(Date.UTC(n,i,r,o,a,l,s)),u&&c.setTime(c.getTime()-u),c},instanceOf:Date,represent:function(e){return e.toISOString()}});var E=new p("tag:yaml.org,2002:merge",{kind:"scalar",resolve:function(e){return"<<"===e||null===e}}),M="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";var L=new p("tag:yaml.org,2002:binary",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t,n,i=0,r=e.length,o=M;for(n=0;n<r;n++)if(!((t=o.indexOf(e.charAt(n)))>64)){if(t<0)return!1;i+=6}return i%8==0},construct:function(e){var t,n,i=e.replace(/[\r\n=]/g,""),r=i.length,o=M,a=0,l=[];for(t=0;t<r;t++)t%4==0&&t&&(l.push(a>>16&255),l.push(a>>8&255),l.push(255&a)),a=a<<6|o.indexOf(i.charAt(t));return 0===(n=r%4*6)?(l.push(a>>16&255),l.push(a>>8&255),l.push(255&a)):18===n?(l.push(a>>10&255),l.push(a>>2&255)):12===n&&l.push(a>>4&255),new Uint8Array(l)},predicate:function(e){return"[object Uint8Array]"===Object.prototype.toString.call(e)},represent:function(e){var t,n,i="",r=0,o=e.length,a=M;for(t=0;t<o;t++)t%3==0&&t&&(i+=a[r>>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]),r=(r<<8)+e[t];return 0===(n=o%3)?(i+=a[r>>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]):2===n?(i+=a[r>>10&63],i+=a[r>>4&63],i+=a[r<<2&63],i+=a[64]):1===n&&(i+=a[r>>2&63],i+=a[r<<4&63],i+=a[64],i+=a[64]),i}}),_=Object.prototype.hasOwnProperty,D=Object.prototype.toString;var U=new p("tag:yaml.org,2002:omap",{kind:"sequence",resolve:function(e){if(null===e)return!0;var t,n,i,r,o,a=[],l=e;for(t=0,n=l.length;t<n;t+=1){if(i=l[t],o=!1,"[object Object]"!==D.call(i))return!1;for(r in i)if(_.call(i,r)){if(o)return!1;o=!0}if(!o)return!1;if(-1!==a.indexOf(r))return!1;a.push(r)}return!0},construct:function(e){return null!==e?e:[]}}),q=Object.prototype.toString;var Y=new p("tag:yaml.org,2002:pairs",{kind:"sequence",resolve:function(e){if(null===e)return!0;var t,n,i,r,o,a=e;for(o=new Array(a.length),t=0,n=a.length;t<n;t+=1){if(i=a[t],"[object Object]"!==q.call(i))return!1;if(1!==(r=Object.keys(i)).length)return!1;o[t]=[r[0],i[r[0]]]}return!0},construct:function(e){if(null===e)return[];var t,n,i,r,o,a=e;for(o=new Array(a.length),t=0,n=a.length;t<n;t+=1)i=a[t],r=Object.keys(i),o[t]=[r[0],i[r[0]]];return o}}),R=Object.prototype.hasOwnProperty;var B=new p("tag:yaml.org,2002:set",{kind:"mapping",resolve:function(e){if(null===e)return!0;var t,n=e;for(t in n)if(R.call(n,t)&&null!==n[t])return!1;return!0},construct:function(e){return null!==e?e:{}}}),K=j.extend({implicit:[F,E],explicit:[L,U,Y,B]}),P=Object.prototype.hasOwnProperty,W=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,H=/[\x85\u2028\u2029]/,$=/[,\[\]\{\}]/,G=/^(?:!|!!|![a-z\-]+!)$/i,V=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;function Z(e){return Object.prototype.toString.call(e)}function J(e){return 10===e||13===e}function Q(e){return 9===e||32===e}function z(e){return 9===e||32===e||10===e||13===e}function X(e){return 44===e||91===e||93===e||123===e||125===e}function ee(e){var t;return 48<=e&&e<=57?e-48:97<=(t=32|e)&&t<=102?t-97+10:-1}function te(e){return 48===e?"\0":97===e?"":98===e?"\b":116===e||9===e?"\t":110===e?"\n":118===e?"\v":102===e?"\f":114===e?"\r":101===e?"":32===e?" ":34===e?'"':47===e?"/":92===e?"\\":78===e?"":95===e?" ":76===e?"\u2028":80===e?"\u2029":""}function ne(e){return e<=65535?String.fromCharCode(e):String.fromCharCode(55296+(e-65536>>10),56320+(e-65536&1023))}for(var ie=new Array(256),re=new Array(256),oe=0;oe<256;oe++)ie[oe]=te(oe)?1:0,re[oe]=te(oe);function ae(e,t){this.input=e,this.filename=t.filename||null,this.schema=t.schema||K,this.onWarning=t.onWarning||null,this.legacy=t.legacy||!1,this.json=t.json||!1,this.listener=t.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=e.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.firstTabInLine=-1,this.documents=[]}function le(e,t){var n={name:e.filename,buffer:e.input.slice(0,-1),position:e.position,line:e.line,column:e.position-e.lineStart};return n.snippet=c(n),new o(t,n)}function ce(e,t){throw le(e,t)}function se(e,t){e.onWarning&&e.onWarning.call(null,le(e,t))}var ue={YAML:function(e,t,n){var i,r,o;null!==e.version&&ce(e,"duplication of %YAML directive"),1!==n.length&&ce(e,"YAML directive accepts exactly one argument"),null===(i=/^([0-9]+)\.([0-9]+)$/.exec(n[0]))&&ce(e,"ill-formed argument of the YAML directive"),r=parseInt(i[1],10),o=parseInt(i[2],10),1!==r&&ce(e,"unacceptable YAML version of the document"),e.version=n[0],e.checkLineBreaks=o<2,1!==o&&2!==o&&se(e,"unsupported YAML version of the document")},TAG:function(e,t,n){var i,r;2!==n.length&&ce(e,"TAG directive accepts exactly two arguments"),i=n[0],r=n[1],G.test(i)||ce(e,"ill-formed tag handle (first argument) of the TAG directive"),P.call(e.tagMap,i)&&ce(e,'there is a previously declared suffix for "'+i+'" tag handle'),V.test(r)||ce(e,"ill-formed tag prefix (second argument) of the TAG directive");try{r=decodeURIComponent(r)}catch(t){ce(e,"tag prefix is malformed: "+r)}e.tagMap[i]=r}};function pe(e,t,n,i){var r,o,a,l;if(t<n){if(l=e.input.slice(t,n),i)for(r=0,o=l.length;r<o;r+=1)9===(a=l.charCodeAt(r))||32<=a&&a<=1114111||ce(e,"expected valid JSON character");else W.test(l)&&ce(e,"the stream contains non-printable characters");e.result+=l}}function fe(e,t,i,r){var o,a,l,c;for(n.isObject(i)||ce(e,"cannot merge mappings; the provided source object is unacceptable"),l=0,c=(o=Object.keys(i)).length;l<c;l+=1)a=o[l],P.call(t,a)||(t[a]=i[a],r[a]=!0)}function de(e,t,n,i,r,o,a,l,c){var s,u;if(Array.isArray(r))for(s=0,u=(r=Array.prototype.slice.call(r)).length;s<u;s+=1)Array.isArray(r[s])&&ce(e,"nested arrays are not supported inside keys"),"object"==typeof r&&"[object Object]"===Z(r[s])&&(r[s]="[object Object]");if("object"==typeof r&&"[object Object]"===Z(r)&&(r="[object Object]"),r=String(r),null===t&&(t={}),"tag:yaml.org,2002:merge"===i)if(Array.isArray(o))for(s=0,u=o.length;s<u;s+=1)fe(e,t,o[s],n);else fe(e,t,o,n);else e.json||P.call(n,r)||!P.call(t,r)||(e.line=a||e.line,e.lineStart=l||e.lineStart,e.position=c||e.position,ce(e,"duplicated mapping key")),"__proto__"===r?Object.defineProperty(t,r,{configurable:!0,enumerable:!0,writable:!0,value:o}):t[r]=o,delete n[r];return t}function he(e){var t;10===(t=e.input.charCodeAt(e.position))?e.position++:13===t?(e.position++,10===e.input.charCodeAt(e.position)&&e.position++):ce(e,"a line break is expected"),e.line+=1,e.lineStart=e.position,e.firstTabInLine=-1}function ge(e,t,n){for(var i=0,r=e.input.charCodeAt(e.position);0!==r;){for(;Q(r);)9===r&&-1===e.firstTabInLine&&(e.firstTabInLine=e.position),r=e.input.charCodeAt(++e.position);if(t&&35===r)do{r=e.input.charCodeAt(++e.position)}while(10!==r&&13!==r&&0!==r);if(!J(r))break;for(he(e),r=e.input.charCodeAt(e.position),i++,e.lineIndent=0;32===r;)e.lineIndent++,r=e.input.charCodeAt(++e.position)}return-1!==n&&0!==i&&e.lineIndent<n&&se(e,"deficient indentation"),i}function me(e){var t,n=e.position;return!(45!==(t=e.input.charCodeAt(n))&&46!==t||t!==e.input.charCodeAt(n+1)||t!==e.input.charCodeAt(n+2)||(n+=3,0!==(t=e.input.charCodeAt(n))&&!z(t)))}function ye(e,t){1===t?e.result+=" ":t>1&&(e.result+=n.repeat("\n",t-1))}function be(e,t){var n,i,r=e.tag,o=e.anchor,a=[],l=!1;if(-1!==e.firstTabInLine)return!1;for(null!==e.anchor&&(e.anchorMap[e.anchor]=a),i=e.input.charCodeAt(e.position);0!==i&&(-1!==e.firstTabInLine&&(e.position=e.firstTabInLine,ce(e,"tab characters must not be used in indentation")),45===i)&&z(e.input.charCodeAt(e.position+1));)if(l=!0,e.position++,ge(e,!0,-1)&&e.lineIndent<=t)a.push(null),i=e.input.charCodeAt(e.position);else if(n=e.line,we(e,t,3,!1,!0),a.push(e.result),ge(e,!0,-1),i=e.input.charCodeAt(e.position),(e.line===n||e.lineIndent>t)&&0!==i)ce(e,"bad indentation of a sequence entry");else if(e.lineIndent<t)break;return!!l&&(e.tag=r,e.anchor=o,e.kind="sequence",e.result=a,!0)}function Ae(e){var t,n,i,r,o=!1,a=!1;if(33!==(r=e.input.charCodeAt(e.position)))return!1;if(null!==e.tag&&ce(e,"duplication of a tag property"),60===(r=e.input.charCodeAt(++e.position))?(o=!0,r=e.input.charCodeAt(++e.position)):33===r?(a=!0,n="!!",r=e.input.charCodeAt(++e.position)):n="!",t=e.position,o){do{r=e.input.charCodeAt(++e.position)}while(0!==r&&62!==r);e.position<e.length?(i=e.input.slice(t,e.position),r=e.input.charCodeAt(++e.position)):ce(e,"unexpected end of the stream within a verbatim tag")}else{for(;0!==r&&!z(r);)33===r&&(a?ce(e,"tag suffix cannot contain exclamation marks"):(n=e.input.slice(t-1,e.position+1),G.test(n)||ce(e,"named tag handle cannot contain such characters"),a=!0,t=e.position+1)),r=e.input.charCodeAt(++e.position);i=e.input.slice(t,e.position),$.test(i)&&ce(e,"tag suffix cannot contain flow indicator characters")}i&&!V.test(i)&&ce(e,"tag name cannot contain such characters: "+i);try{i=decodeURIComponent(i)}catch(t){ce(e,"tag name is malformed: "+i)}return o?e.tag=i:P.call(e.tagMap,n)?e.tag=e.tagMap[n]+i:"!"===n?e.tag="!"+i:"!!"===n?e.tag="tag:yaml.org,2002:"+i:ce(e,'undeclared tag handle "'+n+'"'),!0}function ve(e){var t,n;if(38!==(n=e.input.charCodeAt(e.position)))return!1;for(null!==e.anchor&&ce(e,"duplication of an anchor property"),n=e.input.charCodeAt(++e.position),t=e.position;0!==n&&!z(n)&&!X(n);)n=e.input.charCodeAt(++e.position);return e.position===t&&ce(e,"name of an anchor node must contain at least one character"),e.anchor=e.input.slice(t,e.position),!0}function we(e,t,i,r,o){var a,l,c,s,u,p,f,d,h,g=1,m=!1,y=!1;if(null!==e.listener&&e.listener("open",e),e.tag=null,e.anchor=null,e.kind=null,e.result=null,a=l=c=4===i||3===i,r&&ge(e,!0,-1)&&(m=!0,e.lineIndent>t?g=1:e.lineIndent===t?g=0:e.lineIndent<t&&(g=-1)),1===g)for(;Ae(e)||ve(e);)ge(e,!0,-1)?(m=!0,c=a,e.lineIndent>t?g=1:e.lineIndent===t?g=0:e.lineIndent<t&&(g=-1)):c=!1;if(c&&(c=m||o),1!==g&&4!==i||(d=1===i||2===i?t:t+1,h=e.position-e.lineStart,1===g?c&&(be(e,h)||function(e,t,n){var i,r,o,a,l,c,s,u=e.tag,p=e.anchor,f={},d=Object.create(null),h=null,g=null,m=null,y=!1,b=!1;if(-1!==e.firstTabInLine)return!1;for(null!==e.anchor&&(e.anchorMap[e.anchor]=f),s=e.input.charCodeAt(e.position);0!==s;){if(y||-1===e.firstTabInLine||(e.position=e.firstTabInLine,ce(e,"tab characters must not be used in indentation")),i=e.input.charCodeAt(e.position+1),o=e.line,63!==s&&58!==s||!z(i)){if(a=e.line,l=e.lineStart,c=e.position,!we(e,n,2,!1,!0))break;if(e.line===o){for(s=e.input.charCodeAt(e.position);Q(s);)s=e.input.charCodeAt(++e.position);if(58===s)z(s=e.input.charCodeAt(++e.position))||ce(e,"a whitespace character is expected after the key-value separator within a block mapping"),y&&(de(e,f,d,h,g,null,a,l,c),h=g=m=null),b=!0,y=!1,r=!1,h=e.tag,g=e.result;else{if(!b)return e.tag=u,e.anchor=p,!0;ce(e,"can not read an implicit mapping pair; a colon is missed")}}else{if(!b)return e.tag=u,e.anchor=p,!0;ce(e,"can not read a block mapping entry; a multiline key may not be an implicit key")}}else 63===s?(y&&(de(e,f,d,h,g,null,a,l,c),h=g=m=null),b=!0,y=!0,r=!0):y?(y=!1,r=!0):ce(e,"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line"),e.position+=1,s=i;if((e.line===o||e.lineIndent>t)&&(y&&(a=e.line,l=e.lineStart,c=e.position),we(e,t,4,!0,r)&&(y?g=e.result:m=e.result),y||(de(e,f,d,h,g,m,a,l,c),h=g=m=null),ge(e,!0,-1),s=e.input.charCodeAt(e.position)),(e.line===o||e.lineIndent>t)&&0!==s)ce(e,"bad indentation of a mapping entry");else if(e.lineIndent<t)break}return y&&de(e,f,d,h,g,null,a,l,c),b&&(e.tag=u,e.anchor=p,e.kind="mapping",e.result=f),b}(e,h,d))||function(e,t){var n,i,r,o,a,l,c,s,u,p,f,d,h=!0,g=e.tag,m=e.anchor,y=Object.create(null);if(91===(d=e.input.charCodeAt(e.position)))a=93,s=!1,o=[];else{if(123!==d)return!1;a=125,s=!0,o={}}for(null!==e.anchor&&(e.anchorMap[e.anchor]=o),d=e.input.charCodeAt(++e.position);0!==d;){if(ge(e,!0,t),(d=e.input.charCodeAt(e.position))===a)return e.position++,e.tag=g,e.anchor=m,e.kind=s?"mapping":"sequence",e.result=o,!0;h?44===d&&ce(e,"expected the node content, but found ','"):ce(e,"missed comma between flow collection entries"),f=null,l=c=!1,63===d&&z(e.input.charCodeAt(e.position+1))&&(l=c=!0,e.position++,ge(e,!0,t)),n=e.line,i=e.lineStart,r=e.position,we(e,t,1,!1,!0),p=e.tag,u=e.result,ge(e,!0,t),d=e.input.charCodeAt(e.position),!c&&e.line!==n||58!==d||(l=!0,d=e.input.charCodeAt(++e.position),ge(e,!0,t),we(e,t,1,!1,!0),f=e.result),s?de(e,o,y,p,u,f,n,i,r):l?o.push(de(e,null,y,p,u,f,n,i,r)):o.push(u),ge(e,!0,t),44===(d=e.input.charCodeAt(e.position))?(h=!0,d=e.input.charCodeAt(++e.position)):h=!1}ce(e,"unexpected end of the stream within a flow collection")}(e,d)?y=!0:(l&&function(e,t){var i,r,o,a,l,c=1,s=!1,u=!1,p=t,f=0,d=!1;if(124===(a=e.input.charCodeAt(e.position)))r=!1;else{if(62!==a)return!1;r=!0}for(e.kind="scalar",e.result="";0!==a;)if(43===(a=e.input.charCodeAt(++e.position))||45===a)1===c?c=43===a?3:2:ce(e,"repeat of a chomping mode identifier");else{if(!((o=48<=(l=a)&&l<=57?l-48:-1)>=0))break;0===o?ce(e,"bad explicit indentation width of a block scalar; it cannot be less than one"):u?ce(e,"repeat of an indentation width identifier"):(p=t+o-1,u=!0)}if(Q(a)){do{a=e.input.charCodeAt(++e.position)}while(Q(a));if(35===a)do{a=e.input.charCodeAt(++e.position)}while(!J(a)&&0!==a)}for(;0!==a;){for(he(e),e.lineIndent=0,a=e.input.charCodeAt(e.position);(!u||e.lineIndent<p)&&32===a;)e.lineIndent++,a=e.input.charCodeAt(++e.position);if(!u&&e.lineIndent>p&&(p=e.lineIndent),J(a))f++;else{if(e.lineIndent<p){3===c?e.result+=n.repeat("\n",s?1+f:f):1===c&&s&&(e.result+="\n");break}for(r?Q(a)?(d=!0,e.result+=n.repeat("\n",s?1+f:f)):d?(d=!1,e.result+=n.repeat("\n",f+1)):0===f?s&&(e.result+=" "):e.result+=n.repeat("\n",f):e.result+=n.repeat("\n",s?1+f:f),s=!0,u=!0,f=0,i=e.position;!J(a)&&0!==a;)a=e.input.charCodeAt(++e.position);pe(e,i,e.position,!1)}}return!0}(e,d)||function(e,t){var n,i,r;if(39!==(n=e.input.charCodeAt(e.position)))return!1;for(e.kind="scalar",e.result="",e.position++,i=r=e.position;0!==(n=e.input.charCodeAt(e.position));)if(39===n){if(pe(e,i,e.position,!0),39!==(n=e.input.charCodeAt(++e.position)))return!0;i=e.position,e.position++,r=e.position}else J(n)?(pe(e,i,r,!0),ye(e,ge(e,!1,t)),i=r=e.position):e.position===e.lineStart&&me(e)?ce(e,"unexpected end of the document within a single quoted scalar"):(e.position++,r=e.position);ce(e,"unexpected end of the stream within a single quoted scalar")}(e,d)||function(e,t){var n,i,r,o,a,l,c;if(34!==(l=e.input.charCodeAt(e.position)))return!1;for(e.kind="scalar",e.result="",e.position++,n=i=e.position;0!==(l=e.input.charCodeAt(e.position));){if(34===l)return pe(e,n,e.position,!0),e.position++,!0;if(92===l){if(pe(e,n,e.position,!0),J(l=e.input.charCodeAt(++e.position)))ge(e,!1,t);else if(l<256&&ie[l])e.result+=re[l],e.position++;else if((a=120===(c=l)?2:117===c?4:85===c?8:0)>0){for(r=a,o=0;r>0;r--)(a=ee(l=e.input.charCodeAt(++e.position)))>=0?o=(o<<4)+a:ce(e,"expected hexadecimal character");e.result+=ne(o),e.position++}else ce(e,"unknown escape sequence");n=i=e.position}else J(l)?(pe(e,n,i,!0),ye(e,ge(e,!1,t)),n=i=e.position):e.position===e.lineStart&&me(e)?ce(e,"unexpected end of the document within a double quoted scalar"):(e.position++,i=e.position)}ce(e,"unexpected end of the stream within a double quoted scalar")}(e,d)?y=!0:!function(e){var t,n,i;if(42!==(i=e.input.charCodeAt(e.position)))return!1;for(i=e.input.charCodeAt(++e.position),t=e.position;0!==i&&!z(i)&&!X(i);)i=e.input.charCodeAt(++e.position);return e.position===t&&ce(e,"name of an alias node must contain at least one character"),n=e.input.slice(t,e.position),P.call(e.anchorMap,n)||ce(e,'unidentified alias "'+n+'"'),e.result=e.anchorMap[n],ge(e,!0,-1),!0}(e)?function(e,t,n){var i,r,o,a,l,c,s,u,p=e.kind,f=e.result;if(z(u=e.input.charCodeAt(e.position))||X(u)||35===u||38===u||42===u||33===u||124===u||62===u||39===u||34===u||37===u||64===u||96===u)return!1;if((63===u||45===u)&&(z(i=e.input.charCodeAt(e.position+1))||n&&X(i)))return!1;for(e.kind="scalar",e.result="",r=o=e.position,a=!1;0!==u;){if(58===u){if(z(i=e.input.charCodeAt(e.position+1))||n&&X(i))break}else if(35===u){if(z(e.input.charCodeAt(e.position-1)))break}else{if(e.position===e.lineStart&&me(e)||n&&X(u))break;if(J(u)){if(l=e.line,c=e.lineStart,s=e.lineIndent,ge(e,!1,-1),e.lineIndent>=t){a=!0,u=e.input.charCodeAt(e.position);continue}e.position=o,e.line=l,e.lineStart=c,e.lineIndent=s;break}}a&&(pe(e,r,o,!1),ye(e,e.line-l),r=o=e.position,a=!1),Q(u)||(o=e.position+1),u=e.input.charCodeAt(++e.position)}return pe(e,r,o,!1),!!e.result||(e.kind=p,e.result=f,!1)}(e,d,1===i)&&(y=!0,null===e.tag&&(e.tag="?")):(y=!0,null===e.tag&&null===e.anchor||ce(e,"alias node should not have any properties")),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):0===g&&(y=c&&be(e,h))),null===e.tag)null!==e.anchor&&(e.anchorMap[e.anchor]=e.result);else if("?"===e.tag){for(null!==e.result&&"scalar"!==e.kind&&ce(e,'unacceptable node kind for !<?> tag; it should be "scalar", not "'+e.kind+'"'),s=0,u=e.implicitTypes.length;s<u;s+=1)if((f=e.implicitTypes[s]).resolve(e.result)){e.result=f.construct(e.result),e.tag=f.tag,null!==e.anchor&&(e.anchorMap[e.anchor]=e.result);break}}else if("!"!==e.tag){if(P.call(e.typeMap[e.kind||"fallback"],e.tag))f=e.typeMap[e.kind||"fallback"][e.tag];else for(f=null,s=0,u=(p=e.typeMap.multi[e.kind||"fallback"]).length;s<u;s+=1)if(e.tag.slice(0,p[s].tag.length)===p[s].tag){f=p[s];break}f||ce(e,"unknown tag !<"+e.tag+">"),null!==e.result&&f.kind!==e.kind&&ce(e,"unacceptable node kind for !<"+e.tag+'> tag; it should be "'+f.kind+'", not "'+e.kind+'"'),f.resolve(e.result,e.tag)?(e.result=f.construct(e.result,e.tag),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):ce(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")}return null!==e.listener&&e.listener("close",e),null!==e.tag||null!==e.anchor||y}function ke(e){var t,n,i,r,o=e.position,a=!1;for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap=Object.create(null),e.anchorMap=Object.create(null);0!==(r=e.input.charCodeAt(e.position))&&(ge(e,!0,-1),r=e.input.charCodeAt(e.position),!(e.lineIndent>0||37!==r));){for(a=!0,r=e.input.charCodeAt(++e.position),t=e.position;0!==r&&!z(r);)r=e.input.charCodeAt(++e.position);for(i=[],(n=e.input.slice(t,e.position)).length<1&&ce(e,"directive name must not be less than one character in length");0!==r;){for(;Q(r);)r=e.input.charCodeAt(++e.position);if(35===r){do{r=e.input.charCodeAt(++e.position)}while(0!==r&&!J(r));break}if(J(r))break;for(t=e.position;0!==r&&!z(r);)r=e.input.charCodeAt(++e.position);i.push(e.input.slice(t,e.position))}0!==r&&he(e),P.call(ue,n)?ue[n](e,n,i):se(e,'unknown document directive "'+n+'"')}ge(e,!0,-1),0===e.lineIndent&&45===e.input.charCodeAt(e.position)&&45===e.input.charCodeAt(e.position+1)&&45===e.input.charCodeAt(e.position+2)?(e.position+=3,ge(e,!0,-1)):a&&ce(e,"directives end mark is expected"),we(e,e.lineIndent-1,4,!1,!0),ge(e,!0,-1),e.checkLineBreaks&&H.test(e.input.slice(o,e.position))&&se(e,"non-ASCII line breaks are interpreted as content"),e.documents.push(e.result),e.position===e.lineStart&&me(e)?46===e.input.charCodeAt(e.position)&&(e.position+=3,ge(e,!0,-1)):e.position<e.length-1&&ce(e,"end of the stream or a document separator is expected")}function Ce(e,t){t=t||{},0!==(e=String(e)).length&&(10!==e.charCodeAt(e.length-1)&&13!==e.charCodeAt(e.length-1)&&(e+="\n"),65279===e.charCodeAt(0)&&(e=e.slice(1)));var n=new ae(e,t),i=e.indexOf("\0");for(-1!==i&&(n.position=i,ce(n,"null byte is not allowed in input")),n.input+="\0";32===n.input.charCodeAt(n.position);)n.lineIndent+=1,n.position+=1;for(;n.position<n.length-1;)ke(n);return n.documents}var xe={loadAll:function(e,t,n){null!==t&&"object"==typeof t&&void 0===n&&(n=t,t=null);var i=Ce(e,n);if("function"!=typeof t)return i;for(var r=0,o=i.length;r<o;r+=1)t(i[r])},load:function(e,t){var n=Ce(e,t);if(0!==n.length){if(1===n.length)return n[0];throw new o("expected a single document in the stream, but found more")}}},Ie=Object.prototype.toString,Se=Object.prototype.hasOwnProperty,Oe=65279,je={0:"\\0",7:"\\a",8:"\\b",9:"\\t",10:"\\n",11:"\\v",12:"\\f",13:"\\r",27:"\\e",34:'\\"',92:"\\\\",133:"\\N",160:"\\_",8232:"\\L",8233:"\\P"},Te=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"],Ne=/^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;function Fe(e){var t,i,r;if(t=e.toString(16).toUpperCase(),e<=255)i="x",r=2;else if(e<=65535)i="u",r=4;else{if(!(e<=4294967295))throw new o("code point within a string may not be greater than 0xFFFFFFFF");i="U",r=8}return"\\"+i+n.repeat("0",r-t.length)+t}function Ee(e){this.schema=e.schema||K,this.indent=Math.max(1,e.indent||2),this.noArrayIndent=e.noArrayIndent||!1,this.skipInvalid=e.skipInvalid||!1,this.flowLevel=n.isNothing(e.flowLevel)?-1:e.flowLevel,this.styleMap=function(e,t){var n,i,r,o,a,l,c;if(null===t)return{};for(n={},r=0,o=(i=Object.keys(t)).length;r<o;r+=1)a=i[r],l=String(t[a]),"!!"===a.slice(0,2)&&(a="tag:yaml.org,2002:"+a.slice(2)),(c=e.compiledTypeMap.fallback[a])&&Se.call(c.styleAliases,l)&&(l=c.styleAliases[l]),n[a]=l;return n}(this.schema,e.styles||null),this.sortKeys=e.sortKeys||!1,this.lineWidth=e.lineWidth||80,this.noRefs=e.noRefs||!1,this.noCompatMode=e.noCompatMode||!1,this.condenseFlow=e.condenseFlow||!1,this.quotingType='"'===e.quotingType?2:1,this.forceQuotes=e.forceQuotes||!1,this.replacer="function"==typeof e.replacer?e.replacer:null,this.implicitTypes=this.schema.compiledImplicit,this.explicitTypes=this.schema.compiledExplicit,this.tag=null,this.result="",this.duplicates=[],this.usedDuplicates=null}function Me(e,t){for(var i,r=n.repeat(" ",t),o=0,a=-1,l="",c=e.length;o<c;)-1===(a=e.indexOf("\n",o))?(i=e.slice(o),o=c):(i=e.slice(o,a+1),o=a+1),i.length&&"\n"!==i&&(l+=r),l+=i;return l}function Le(e,t){return"\n"+n.repeat(" ",e.indent*t)}function _e(e){return 32===e||9===e}function De(e){return 32<=e&&e<=126||161<=e&&e<=55295&&8232!==e&&8233!==e||57344<=e&&e<=65533&&e!==Oe||65536<=e&&e<=1114111}function Ue(e){return De(e)&&e!==Oe&&13!==e&&10!==e}function qe(e,t,n){var i=Ue(e),r=i&&!_e(e);return(n?i:i&&44!==e&&91!==e&&93!==e&&123!==e&&125!==e)&&35!==e&&!(58===t&&!r)||Ue(t)&&!_e(t)&&35===e||58===t&&r}function Ye(e,t){var n,i=e.charCodeAt(t);return i>=55296&&i<=56319&&t+1<e.length&&(n=e.charCodeAt(t+1))>=56320&&n<=57343?1024*(i-55296)+n-56320+65536:i}function Re(e){return/^\n* /.test(e)}function Be(e,t,n,i,r,o,a,l){var c,s,u=0,p=null,f=!1,d=!1,h=-1!==i,g=-1,m=De(s=Ye(e,0))&&s!==Oe&&!_e(s)&&45!==s&&63!==s&&58!==s&&44!==s&&91!==s&&93!==s&&123!==s&&125!==s&&35!==s&&38!==s&&42!==s&&33!==s&&124!==s&&61!==s&&62!==s&&39!==s&&34!==s&&37!==s&&64!==s&&96!==s&&function(e){return!_e(e)&&58!==e}(Ye(e,e.length-1));if(t||a)for(c=0;c<e.length;u>=65536?c+=2:c++){if(!De(u=Ye(e,c)))return 5;m=m&&qe(u,p,l),p=u}else{for(c=0;c<e.length;u>=65536?c+=2:c++){if(10===(u=Ye(e,c)))f=!0,h&&(d=d||c-g-1>i&&" "!==e[g+1],g=c);else if(!De(u))return 5;m=m&&qe(u,p,l),p=u}d=d||h&&c-g-1>i&&" "!==e[g+1]}return f||d?n>9&&Re(e)?5:a?2===o?5:2:d?4:3:!m||a||r(e)?2===o?5:2:1}function Ke(e,t,n,i,r){e.dump=function(){if(0===t.length)return 2===e.quotingType?'""':"''";if(!e.noCompatMode&&(-1!==Te.indexOf(t)||Ne.test(t)))return 2===e.quotingType?'"'+t+'"':"'"+t+"'";var a=e.indent*Math.max(1,n),l=-1===e.lineWidth?-1:Math.max(Math.min(e.lineWidth,40),e.lineWidth-a),c=i||e.flowLevel>-1&&n>=e.flowLevel;switch(Be(t,c,e.indent,l,(function(t){return function(e,t){var n,i;for(n=0,i=e.implicitTypes.length;n<i;n+=1)if(e.implicitTypes[n].resolve(t))return!0;return!1}(e,t)}),e.quotingType,e.forceQuotes&&!i,r)){case 1:return t;case 2:return"'"+t.replace(/'/g,"''")+"'";case 3:return"|"+Pe(t,e.indent)+We(Me(t,a));case 4:return">"+Pe(t,e.indent)+We(Me(function(e,t){var n,i,r=/(\n+)([^\n]*)/g,o=(l=e.indexOf("\n"),l=-1!==l?l:e.length,r.lastIndex=l,He(e.slice(0,l),t)),a="\n"===e[0]||" "===e[0];var l;for(;i=r.exec(e);){var c=i[1],s=i[2];n=" "===s[0],o+=c+(a||n||""===s?"":"\n")+He(s,t),a=n}return o}(t,l),a));case 5:return'"'+function(e){for(var t,n="",i=0,r=0;r<e.length;i>=65536?r+=2:r++)i=Ye(e,r),!(t=je[i])&&De(i)?(n+=e[r],i>=65536&&(n+=e[r+1])):n+=t||Fe(i);return n}(t)+'"';default:throw new o("impossible error: invalid scalar style")}}()}function Pe(e,t){var n=Re(e)?String(t):"",i="\n"===e[e.length-1];return n+(i&&("\n"===e[e.length-2]||"\n"===e)?"+":i?"":"-")+"\n"}function We(e){return"\n"===e[e.length-1]?e.slice(0,-1):e}function He(e,t){if(""===e||" "===e[0])return e;for(var n,i,r=/ [^ ]/g,o=0,a=0,l=0,c="";n=r.exec(e);)(l=n.index)-o>t&&(i=a>o?a:l,c+="\n"+e.slice(o,i),o=i+1),a=l;return c+="\n",e.length-o>t&&a>o?c+=e.slice(o,a)+"\n"+e.slice(a+1):c+=e.slice(o),c.slice(1)}function $e(e,t,n,i){var r,o,a,l="",c=e.tag;for(r=0,o=n.length;r<o;r+=1)a=n[r],e.replacer&&(a=e.replacer.call(n,String(r),a)),(Ve(e,t+1,a,!0,!0,!1,!0)||void 0===a&&Ve(e,t+1,null,!0,!0,!1,!0))&&(i&&""===l||(l+=Le(e,t)),e.dump&&10===e.dump.charCodeAt(0)?l+="-":l+="- ",l+=e.dump);e.tag=c,e.dump=l||"[]"}function Ge(e,t,n){var i,r,a,l,c,s;for(a=0,l=(r=n?e.explicitTypes:e.implicitTypes).length;a<l;a+=1)if(((c=r[a]).instanceOf||c.predicate)&&(!c.instanceOf||"object"==typeof t&&t instanceof c.instanceOf)&&(!c.predicate||c.predicate(t))){if(n?c.multi&&c.representName?e.tag=c.representName(t):e.tag=c.tag:e.tag="?",c.represent){if(s=e.styleMap[c.tag]||c.defaultStyle,"[object Function]"===Ie.call(c.represent))i=c.represent(t,s);else{if(!Se.call(c.represent,s))throw new o("!<"+c.tag+'> tag resolver accepts not "'+s+'" style');i=c.represent[s](t,s)}e.dump=i}return!0}return!1}function Ve(e,t,n,i,r,a,l){e.tag=null,e.dump=n,Ge(e,n,!1)||Ge(e,n,!0);var c,s=Ie.call(e.dump),u=i;i&&(i=e.flowLevel<0||e.flowLevel>t);var p,f,d="[object Object]"===s||"[object Array]"===s;if(d&&(f=-1!==(p=e.duplicates.indexOf(n))),(null!==e.tag&&"?"!==e.tag||f||2!==e.indent&&t>0)&&(r=!1),f&&e.usedDuplicates[p])e.dump="*ref_"+p;else{if(d&&f&&!e.usedDuplicates[p]&&(e.usedDuplicates[p]=!0),"[object Object]"===s)i&&0!==Object.keys(e.dump).length?(!function(e,t,n,i){var r,a,l,c,s,u,p="",f=e.tag,d=Object.keys(n);if(!0===e.sortKeys)d.sort();else if("function"==typeof e.sortKeys)d.sort(e.sortKeys);else if(e.sortKeys)throw new o("sortKeys must be a boolean or a function");for(r=0,a=d.length;r<a;r+=1)u="",i&&""===p||(u+=Le(e,t)),c=n[l=d[r]],e.replacer&&(c=e.replacer.call(n,l,c)),Ve(e,t+1,l,!0,!0,!0)&&((s=null!==e.tag&&"?"!==e.tag||e.dump&&e.dump.length>1024)&&(e.dump&&10===e.dump.charCodeAt(0)?u+="?":u+="? "),u+=e.dump,s&&(u+=Le(e,t)),Ve(e,t+1,c,!0,s)&&(e.dump&&10===e.dump.charCodeAt(0)?u+=":":u+=": ",p+=u+=e.dump));e.tag=f,e.dump=p||"{}"}(e,t,e.dump,r),f&&(e.dump="&ref_"+p+e.dump)):(!function(e,t,n){var i,r,o,a,l,c="",s=e.tag,u=Object.keys(n);for(i=0,r=u.length;i<r;i+=1)l="",""!==c&&(l+=", "),e.condenseFlow&&(l+='"'),a=n[o=u[i]],e.replacer&&(a=e.replacer.call(n,o,a)),Ve(e,t,o,!1,!1)&&(e.dump.length>1024&&(l+="? "),l+=e.dump+(e.condenseFlow?'"':"")+":"+(e.condenseFlow?"":" "),Ve(e,t,a,!1,!1)&&(c+=l+=e.dump));e.tag=s,e.dump="{"+c+"}"}(e,t,e.dump),f&&(e.dump="&ref_"+p+" "+e.dump));else if("[object Array]"===s)i&&0!==e.dump.length?(e.noArrayIndent&&!l&&t>0?$e(e,t-1,e.dump,r):$e(e,t,e.dump,r),f&&(e.dump="&ref_"+p+e.dump)):(!function(e,t,n){var i,r,o,a="",l=e.tag;for(i=0,r=n.length;i<r;i+=1)o=n[i],e.replacer&&(o=e.replacer.call(n,String(i),o)),(Ve(e,t,o,!1,!1)||void 0===o&&Ve(e,t,null,!1,!1))&&(""!==a&&(a+=","+(e.condenseFlow?"":" ")),a+=e.dump);e.tag=l,e.dump="["+a+"]"}(e,t,e.dump),f&&(e.dump="&ref_"+p+" "+e.dump));else{if("[object String]"!==s){if("[object Undefined]"===s)return!1;if(e.skipInvalid)return!1;throw new o("unacceptable kind of an object to dump "+s)}"?"!==e.tag&&Ke(e,e.dump,t,a,u)}null!==e.tag&&"?"!==e.tag&&(c=encodeURI("!"===e.tag[0]?e.tag.slice(1):e.tag).replace(/!/g,"%21"),c="!"===e.tag[0]?"!"+c:"tag:yaml.org,2002:"===c.slice(0,18)?"!!"+c.slice(18):"!<"+c+">",e.dump=c+" "+e.dump)}return!0}function Ze(e,t){var n,i,r=[],o=[];for(Je(e,r,o),n=0,i=o.length;n<i;n+=1)t.duplicates.push(r[o[n]]);t.usedDuplicates=new Array(i)}function Je(e,t,n){var i,r,o;if(null!==e&&"object"==typeof e)if(-1!==(r=t.indexOf(e)))-1===n.indexOf(r)&&n.push(r);else if(t.push(e),Array.isArray(e))for(r=0,o=e.length;r<o;r+=1)Je(e[r],t,n);else for(r=0,o=(i=Object.keys(e)).length;r<o;r+=1)Je(e[i[r]],t,n)}function Qe(e,t){return function(){throw new Error("Function yaml."+e+" is removed in js-yaml 4. Use yaml."+t+" instead, which is now safe by default.")}}var ze=p,Xe=h,et=b,tt=O,nt=j,it=K,rt=xe.load,ot=xe.loadAll,at={dump:function(e,t){var n=new Ee(t=t||{});n.noRefs||Ze(e,n);var i=e;return n.replacer&&(i=n.replacer.call({"":i},"",i)),Ve(n,0,i,!0,!0)?n.dump+"\n":""}}.dump,lt=o,ct={binary:L,float:S,map:y,null:A,pairs:Y,set:B,timestamp:F,bool:v,int:C,merge:E,omap:U,seq:m,str:g},st=Qe("safeLoad","load"),ut=Qe("safeLoadAll","loadAll"),pt=Qe("safeDump","dump"),ft={Type:ze,Schema:Xe,FAILSAFE_SCHEMA:et,JSON_SCHEMA:tt,CORE_SCHEMA:nt,DEFAULT_SCHEMA:it,load:rt,loadAll:ot,dump:at,YAMLException:lt,types:ct,safeLoad:st,safeLoadAll:ut,safeDump:pt};e.CORE_SCHEMA=nt,e.DEFAULT_SCHEMA=it,e.FAILSAFE_SCHEMA=et,e.JSON_SCHEMA=tt,e.Schema=Xe,e.Type=ze,e.YAMLException=lt,e.default=ft,e.dump=at,e.load=rt,e.loadAll=ot,e.safeDump=pt,e.safeLoad=st,e.safeLoadAll=ut,e.types=ct,Object.defineProperty(e,"__esModule",{value:!0})}));

/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */
function isNothing(subject) {
  return (typeof subject === 'undefined') || (subject === null);
}


function isObject(subject) {
  return (typeof subject === 'object') && (subject !== null);
}


function toArray(sequence) {
  if (Array.isArray(sequence)) return sequence;
  else if (isNothing(sequence)) return [];

  return [ sequence ];
}


function extend(target, source) {
  var index, length, key, sourceKeys;

  if (source) {
    sourceKeys = Object.keys(source);

    for (index = 0, length = sourceKeys.length; index < length; index += 1) {
      key = sourceKeys[index];
      target[key] = source[key];
    }
  }

  return target;
}


function repeat(string, count) {
  var result = '', cycle;

  for (cycle = 0; cycle < count; cycle += 1) {
    result += string;
  }

  return result;
}


function isNegativeZero(number) {
  return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number);
}


var isNothing_1      = isNothing;
var isObject_1       = isObject;
var toArray_1        = toArray;
var repeat_1         = repeat;
var isNegativeZero_1 = isNegativeZero;
var extend_1         = extend;

var common = {
	isNothing: isNothing_1,
	isObject: isObject_1,
	toArray: toArray_1,
	repeat: repeat_1,
	isNegativeZero: isNegativeZero_1,
	extend: extend_1
};

// YAML error class. http://stackoverflow.com/questions/8458984


function formatError(exception, compact) {
  var where = '', message = exception.reason || '(unknown reason)';

  if (!exception.mark) return message;

  if (exception.mark.name) {
    where += 'in "' + exception.mark.name + '" ';
  }

  where += '(' + (exception.mark.line + 1) + ':' + (exception.mark.column + 1) + ')';

  if (!compact && exception.mark.snippet) {
    where += '\n\n' + exception.mark.snippet;
  }

  return message + ' ' + where;
}


function YAMLException$1(reason, mark) {
  // Super constructor
  Error.call(this);

  this.name = 'YAMLException';
  this.reason = reason;
  this.mark = mark;
  this.message = formatError(this, false);

  // Include stack trace in error object
  if (Error.captureStackTrace) {
    // Chrome and NodeJS
    Error.captureStackTrace(this, this.constructor);
  } else {
    // FF, IE 10+ and Safari 6+. Fallback for others
    this.stack = (new Error()).stack || '';
  }
}


// Inherit from Error
YAMLException$1.prototype = Object.create(Error.prototype);
YAMLException$1.prototype.constructor = YAMLException$1;


YAMLException$1.prototype.toString = function toString(compact) {
  return this.name + ': ' + formatError(this, compact);
};


var exception = YAMLException$1;

// get snippet for a single line, respecting maxLength
function getLine(buffer, lineStart, lineEnd, position, maxLineLength) {
  var head = '';
  var tail = '';
  var maxHalfLength = Math.floor(maxLineLength / 2) - 1;

  if (position - lineStart > maxHalfLength) {
    head = ' ... ';
    lineStart = position - maxHalfLength + head.length;
  }

  if (lineEnd - position > maxHalfLength) {
    tail = ' ...';
    lineEnd = position + maxHalfLength - tail.length;
  }

  return {
    str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, '→') + tail,
    pos: position - lineStart + head.length // relative position
  };
}


function padStart(string, max) {
  return common.repeat(' ', max - string.length) + string;
}


function makeSnippet(mark, options) {
  options = Object.create(options || null);

  if (!mark.buffer) return null;

  if (!options.maxLength) options.maxLength = 79;
  if (typeof options.indent      !== 'number') options.indent      = 1;
  if (typeof options.linesBefore !== 'number') options.linesBefore = 3;
  if (typeof options.linesAfter  !== 'number') options.linesAfter  = 2;

  var re = /\r?\n|\r|\0/g;
  var lineStarts = [ 0 ];
  var lineEnds = [];
  var match;
  var foundLineNo = -1;

  while ((match = re.exec(mark.buffer))) {
    lineEnds.push(match.index);
    lineStarts.push(match.index + match[0].length);

    if (mark.position <= match.index && foundLineNo < 0) {
      foundLineNo = lineStarts.length - 2;
    }
  }

  if (foundLineNo < 0) foundLineNo = lineStarts.length - 1;

  var result = '', i, line;
  var lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length;
  var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3);

  for (i = 1; i <= options.linesBefore; i++) {
    if (foundLineNo - i < 0) break;
    line = getLine(
      mark.buffer,
      lineStarts[foundLineNo - i],
      lineEnds[foundLineNo - i],
      mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),
      maxLineLength
    );
    result = common.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) +
      ' | ' + line.str + '\n' + result;
  }

  line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength);
  result += common.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) +
    ' | ' + line.str + '\n';
  result += common.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\n';

  for (i = 1; i <= options.linesAfter; i++) {
    if (foundLineNo + i >= lineEnds.length) break;
    line = getLine(
      mark.buffer,
      lineStarts[foundLineNo + i],
      lineEnds[foundLineNo + i],
      mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),
      maxLineLength
    );
    result += common.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) +
      ' | ' + line.str + '\n';
  }

  return result.replace(/\n$/, '');
}


var snippet = makeSnippet;

var TYPE_CONSTRUCTOR_OPTIONS = [
  'kind',
  'multi',
  'resolve',
  'construct',
  'instanceOf',
  'predicate',
  'represent',
  'representName',
  'defaultStyle',
  'styleAliases'
];

var YAML_NODE_KINDS = [
  'scalar',
  'sequence',
  'mapping'
];

function compileStyleAliases(map) {
  var result = {};

  if (map !== null) {
    Object.keys(map).forEach(function (style) {
      map[style].forEach(function (alias) {
        result[String(alias)] = style;
      });
    });
  }

  return result;
}

function Type$1(tag, options) {
  options = options || {};

  Object.keys(options).forEach(function (name) {
    if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {
      throw new exception('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.');
    }
  });

  // TODO: Add tag format check.
  this.options       = options; // keep original options in case user wants to extend this type later
  this.tag           = tag;
  this.kind          = options['kind']          || null;
  this.resolve       = options['resolve']       || function () { return true; };
  this.construct     = options['construct']     || function (data) { return data; };
  this.instanceOf    = options['instanceOf']    || null;
  this.predicate     = options['predicate']     || null;
  this.represent     = options['represent']     || null;
  this.representName = options['representName'] || null;
  this.defaultStyle  = options['defaultStyle']  || null;
  this.multi         = options['multi']         || false;
  this.styleAliases  = compileStyleAliases(options['styleAliases'] || null);

  if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {
    throw new exception('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.');
  }
}

var type = Type$1;

/*eslint-disable max-len*/





function compileList(schema, name) {
  var result = [];

  schema[name].forEach(function (currentType) {
    var newIndex = result.length;

    result.forEach(function (previousType, previousIndex) {
      if (previousType.tag === currentType.tag &&
          previousType.kind === currentType.kind &&
          previousType.multi === currentType.multi) {

        newIndex = previousIndex;
      }
    });

    result[newIndex] = currentType;
  });

  return result;
}


function compileMap(/* lists... */) {
  var result = {
        scalar: {},
        sequence: {},
        mapping: {},
        fallback: {},
        multi: {
          scalar: [],
          sequence: [],
          mapping: [],
          fallback: []
        }
      }, index, length;

  function collectType(type) {
    if (type.multi) {
      result.multi[type.kind].push(type);
      result.multi['fallback'].push(type);
    } else {
      result[type.kind][type.tag] = result['fallback'][type.tag] = type;
    }
  }

  for (index = 0, length = arguments.length; index < length; index += 1) {
    arguments[index].forEach(collectType);
  }
  return result;
}


function Schema$1(definition) {
  return this.extend(definition);
}


Schema$1.prototype.extend = function extend(definition) {
  var implicit = [];
  var explicit = [];

  if (definition instanceof type) {
    // Schema.extend(type)
    explicit.push(definition);

  } else if (Array.isArray(definition)) {
    // Schema.extend([ type1, type2, ... ])
    explicit = explicit.concat(definition);

  } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) {
    // Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] })
    if (definition.implicit) implicit = implicit.concat(definition.implicit);
    if (definition.explicit) explicit = explicit.concat(definition.explicit);

  } else {
    throw new exception('Schema.extend argument should be a Type, [ Type ], ' +
      'or a schema definition ({ implicit: [...], explicit: [...] })');
  }

  implicit.forEach(function (type$1) {
    if (!(type$1 instanceof type)) {
      throw new exception('Specified list of YAML types (or a single Type object) contains a non-Type object.');
    }

    if (type$1.loadKind && type$1.loadKind !== 'scalar') {
      throw new exception('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.');
    }

    if (type$1.multi) {
      throw new exception('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.');
    }
  });

  explicit.forEach(function (type$1) {
    if (!(type$1 instanceof type)) {
      throw new exception('Specified list of YAML types (or a single Type object) contains a non-Type object.');
    }
  });

  var result = Object.create(Schema$1.prototype);

  result.implicit = (this.implicit || []).concat(implicit);
  result.explicit = (this.explicit || []).concat(explicit);

  result.compiledImplicit = compileList(result, 'implicit');
  result.compiledExplicit = compileList(result, 'explicit');
  result.compiledTypeMap  = compileMap(result.compiledImplicit, result.compiledExplicit);

  return result;
};


var schema = Schema$1;

var str = new type('tag:yaml.org,2002:str', {
  kind: 'scalar',
  construct: function (data) { return data !== null ? data : ''; }
});

var seq = new type('tag:yaml.org,2002:seq', {
  kind: 'sequence',
  construct: function (data) { return data !== null ? data : []; }
});

var map = new type('tag:yaml.org,2002:map', {
  kind: 'mapping',
  construct: function (data) { return data !== null ? data : {}; }
});

var failsafe = new schema({
  explicit: [
    str,
    seq,
    map
  ]
});

function resolveYamlNull(data) {
  if (data === null) return true;

  var max = data.length;

  return (max === 1 && data === '~') ||
         (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'));
}

function constructYamlNull() {
  return null;
}

function isNull(object) {
  return object === null;
}

var _null = new type('tag:yaml.org,2002:null', {
  kind: 'scalar',
  resolve: resolveYamlNull,
  construct: constructYamlNull,
  predicate: isNull,
  represent: {
    canonical: function () { return '~';    },
    lowercase: function () { return 'null'; },
    uppercase: function () { return 'NULL'; },
    camelcase: function () { return 'Null'; },
    empty:     function () { return '';     }
  },
  defaultStyle: 'lowercase'
});

function resolveYamlBoolean(data) {
  if (data === null) return false;

  var max = data.length;

  return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||
         (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'));
}

function constructYamlBoolean(data) {
  return data === 'true' ||
         data === 'True' ||
         data === 'TRUE';
}

function isBoolean(object) {
  return Object.prototype.toString.call(object) === '[object Boolean]';
}

var bool = new type('tag:yaml.org,2002:bool', {
  kind: 'scalar',
  resolve: resolveYamlBoolean,
  construct: constructYamlBoolean,
  predicate: isBoolean,
  represent: {
    lowercase: function (object) { return object ? 'true' : 'false'; },
    uppercase: function (object) { return object ? 'TRUE' : 'FALSE'; },
    camelcase: function (object) { return object ? 'True' : 'False'; }
  },
  defaultStyle: 'lowercase'
});

function isHexCode(c) {
  return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) ||
         ((0x41/* A */ <= c) && (c <= 0x46/* F */)) ||
         ((0x61/* a */ <= c) && (c <= 0x66/* f */));
}

function isOctCode(c) {
  return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */));
}

function isDecCode(c) {
  return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */));
}

function resolveYamlInteger(data) {
  if (data === null) return false;

  var max = data.length,
      index = 0,
      hasDigits = false,
      ch;

  if (!max) return false;

  ch = data[index];

  // sign
  if (ch === '-' || ch === '+') {
    ch = data[++index];
  }

  if (ch === '0') {
    // 0
    if (index + 1 === max) return true;
    ch = data[++index];

    // base 2, base 8, base 16

    if (ch === 'b') {
      // base 2
      index++;

      for (; index < max; index++) {
        ch = data[index];
        if (ch === '_') continue;
        if (ch !== '0' && ch !== '1') return false;
        hasDigits = true;
      }
      return hasDigits && ch !== '_';
    }


    if (ch === 'x') {
      // base 16
      index++;

      for (; index < max; index++) {
        ch = data[index];
        if (ch === '_') continue;
        if (!isHexCode(data.charCodeAt(index))) return false;
        hasDigits = true;
      }
      return hasDigits && ch !== '_';
    }


    if (ch === 'o') {
      // base 8
      index++;

      for (; index < max; index++) {
        ch = data[index];
        if (ch === '_') continue;
        if (!isOctCode(data.charCodeAt(index))) return false;
        hasDigits = true;
      }
      return hasDigits && ch !== '_';
    }
  }

  // base 10 (except 0)

  // value should not start with `_`;
  if (ch === '_') return false;

  for (; index < max; index++) {
    ch = data[index];
    if (ch === '_') continue;
    if (!isDecCode(data.charCodeAt(index))) {
      return false;
    }
    hasDigits = true;
  }

  // Should have digits and should not end with `_`
  if (!hasDigits || ch === '_') return false;

  return true;
}

function constructYamlInteger(data) {
  var value = data, sign = 1, ch;

  if (value.indexOf('_') !== -1) {
    value = value.replace(/_/g, '');
  }

  ch = value[0];

  if (ch === '-' || ch === '+') {
    if (ch === '-') sign = -1;
    value = value.slice(1);
    ch = value[0];
  }

  if (value === '0') return 0;

  if (ch === '0') {
    if (value[1] === 'b') return sign * parseInt(value.slice(2), 2);
    if (value[1] === 'x') return sign * parseInt(value.slice(2), 16);
    if (value[1] === 'o') return sign * parseInt(value.slice(2), 8);
  }

  return sign * parseInt(value, 10);
}

function isInteger(object) {
  return (Object.prototype.toString.call(object)) === '[object Number]' &&
         (object % 1 === 0 && !common.isNegativeZero(object));
}

var int = new type('tag:yaml.org,2002:int', {
  kind: 'scalar',
  resolve: resolveYamlInteger,
  construct: constructYamlInteger,
  predicate: isInteger,
  represent: {
    binary:      function (obj) { return obj >= 0 ? '0b' + obj.toString(2) : '-0b' + obj.toString(2).slice(1); },
    octal:       function (obj) { return obj >= 0 ? '0o'  + obj.toString(8) : '-0o'  + obj.toString(8).slice(1); },
    decimal:     function (obj) { return obj.toString(10); },
    /* eslint-disable max-len */
    hexadecimal: function (obj) { return obj >= 0 ? '0x' + obj.toString(16).toUpperCase() :  '-0x' + obj.toString(16).toUpperCase().slice(1); }
  },
  defaultStyle: 'decimal',
  styleAliases: {
    binary:      [ 2,  'bin' ],
    octal:       [ 8,  'oct' ],
    decimal:     [ 10, 'dec' ],
    hexadecimal: [ 16, 'hex' ]
  }
});

var YAML_FLOAT_PATTERN = new RegExp(
  // 2.5e4, 2.5 and integers
  '^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?' +
  // .2e4, .2
  // special case, seems not from spec
  '|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?' +
  // .inf
  '|[-+]?\\.(?:inf|Inf|INF)' +
  // .nan
  '|\\.(?:nan|NaN|NAN))$');

function resolveYamlFloat(data) {
  if (data === null) return false;

  if (!YAML_FLOAT_PATTERN.test(data) ||
      // Quick hack to not allow integers end with `_`
      // Probably should update regexp & check speed
      data[data.length - 1] === '_') {
    return false;
  }

  return true;
}

function constructYamlFloat(data) {
  var value, sign;

  value  = data.replace(/_/g, '').toLowerCase();
  sign   = value[0] === '-' ? -1 : 1;

  if ('+-'.indexOf(value[0]) >= 0) {
    value = value.slice(1);
  }

  if (value === '.inf') {
    return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;

  } else if (value === '.nan') {
    return NaN;
  }
  return sign * parseFloat(value, 10);
}


var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;

function representYamlFloat(object, style) {
  var res;

  if (isNaN(object)) {
    switch (style) {
      case 'lowercase': return '.nan';
      case 'uppercase': return '.NAN';
      case 'camelcase': return '.NaN';
    }
  } else if (Number.POSITIVE_INFINITY === object) {
    switch (style) {
      case 'lowercase': return '.inf';
      case 'uppercase': return '.INF';
      case 'camelcase': return '.Inf';
    }
  } else if (Number.NEGATIVE_INFINITY === object) {
    switch (style) {
      case 'lowercase': return '-.inf';
      case 'uppercase': return '-.INF';
      case 'camelcase': return '-.Inf';
    }
  } else if (common.isNegativeZero(object)) {
    return '-0.0';
  }

  res = object.toString(10);

  // JS stringifier can build scientific format without dots: 5e-100,
  // while YAML requres dot: 5.e-100. Fix it with simple hack

  return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res;
}

function isFloat(object) {
  return (Object.prototype.toString.call(object) === '[object Number]') &&
         (object % 1 !== 0 || common.isNegativeZero(object));
}

var float = new type('tag:yaml.org,2002:float', {
  kind: 'scalar',
  resolve: resolveYamlFloat,
  construct: constructYamlFloat,
  predicate: isFloat,
  represent: representYamlFloat,
  defaultStyle: 'lowercase'
});

var json = failsafe.extend({
  implicit: [
    _null,
    bool,
    int,
    float
  ]
});

var core = json;

var YAML_DATE_REGEXP = new RegExp(
  '^([0-9][0-9][0-9][0-9])'          + // [1] year
  '-([0-9][0-9])'                    + // [2] month
  '-([0-9][0-9])$');                   // [3] day

var YAML_TIMESTAMP_REGEXP = new RegExp(
  '^([0-9][0-9][0-9][0-9])'          + // [1] year
  '-([0-9][0-9]?)'                   + // [2] month
  '-([0-9][0-9]?)'                   + // [3] day
  '(?:[Tt]|[ \\t]+)'                 + // ...
  '([0-9][0-9]?)'                    + // [4] hour
  ':([0-9][0-9])'                    + // [5] minute
  ':([0-9][0-9])'                    + // [6] second
  '(?:\\.([0-9]*))?'                 + // [7] fraction
  '(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tz_hour
  '(?::([0-9][0-9]))?))?$');           // [11] tz_minute

function resolveYamlTimestamp(data) {
  if (data === null) return false;
  if (YAML_DATE_REGEXP.exec(data) !== null) return true;
  if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;
  return false;
}

function constructYamlTimestamp(data) {
  var match, year, month, day, hour, minute, second, fraction = 0,
      delta = null, tz_hour, tz_minute, date;

  match = YAML_DATE_REGEXP.exec(data);
  if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);

  if (match === null) throw new Error('Date resolve error');

  // match: [1] year [2] month [3] day

  year = +(match[1]);
  month = +(match[2]) - 1; // JS month starts with 0
  day = +(match[3]);

  if (!match[4]) { // no hour
    return new Date(Date.UTC(year, month, day));
  }

  // match: [4] hour [5] minute [6] second [7] fraction

  hour = +(match[4]);
  minute = +(match[5]);
  second = +(match[6]);

  if (match[7]) {
    fraction = match[7].slice(0, 3);
    while (fraction.length < 3) { // milli-seconds
      fraction += '0';
    }
    fraction = +fraction;
  }

  // match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute

  if (match[9]) {
    tz_hour = +(match[10]);
    tz_minute = +(match[11] || 0);
    delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds
    if (match[9] === '-') delta = -delta;
  }

  date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction));

  if (delta) date.setTime(date.getTime() - delta);

  return date;
}

function representYamlTimestamp(object /*, style*/) {
  return object.toISOString();
}

var timestamp = new type('tag:yaml.org,2002:timestamp', {
  kind: 'scalar',
  resolve: resolveYamlTimestamp,
  construct: constructYamlTimestamp,
  instanceOf: Date,
  represent: representYamlTimestamp
});

function resolveYamlMerge(data) {
  return data === '<<' || data === null;
}

var merge = new type('tag:yaml.org,2002:merge', {
  kind: 'scalar',
  resolve: resolveYamlMerge
});

/*eslint-disable no-bitwise*/





// [ 64, 65, 66 ] -> [ padding, CR, LF ]
var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r';


function resolveYamlBinary(data) {
  if (data === null) return false;

  var code, idx, bitlen = 0, max = data.length, map = BASE64_MAP;

  // Convert one by one.
  for (idx = 0; idx < max; idx++) {
    code = map.indexOf(data.charAt(idx));

    // Skip CR/LF
    if (code > 64) continue;

    // Fail on illegal characters
    if (code < 0) return false;

    bitlen += 6;
  }

  // If there are any bits left, source was corrupted
  return (bitlen % 8) === 0;
}

function constructYamlBinary(data) {
  var idx, tailbits,
      input = data.replace(/[\r\n=]/g, ''), // remove CR/LF & padding to simplify scan
      max = input.length,
      map = BASE64_MAP,
      bits = 0,
      result = [];

  // Collect by 6*4 bits (3 bytes)

  for (idx = 0; idx < max; idx++) {
    if ((idx % 4 === 0) && idx) {
      result.push((bits >> 16) & 0xFF);
      result.push((bits >> 8) & 0xFF);
      result.push(bits & 0xFF);
    }

    bits = (bits << 6) | map.indexOf(input.charAt(idx));
  }

  // Dump tail

  tailbits = (max % 4) * 6;

  if (tailbits === 0) {
    result.push((bits >> 16) & 0xFF);
    result.push((bits >> 8) & 0xFF);
    result.push(bits & 0xFF);
  } else if (tailbits === 18) {
    result.push((bits >> 10) & 0xFF);
    result.push((bits >> 2) & 0xFF);
  } else if (tailbits === 12) {
    result.push((bits >> 4) & 0xFF);
  }

  return new Uint8Array(result);
}

function representYamlBinary(object /*, style*/) {
  var result = '', bits = 0, idx, tail,
      max = object.length,
      map = BASE64_MAP;

  // Convert every three bytes to 4 ASCII characters.

  for (idx = 0; idx < max; idx++) {
    if ((idx % 3 === 0) && idx) {
      result += map[(bits >> 18) & 0x3F];
      result += map[(bits >> 12) & 0x3F];
      result += map[(bits >> 6) & 0x3F];
      result += map[bits & 0x3F];
    }

    bits = (bits << 8) + object[idx];
  }

  // Dump tail

  tail = max % 3;

  if (tail === 0) {
    result += map[(bits >> 18) & 0x3F];
    result += map[(bits >> 12) & 0x3F];
    result += map[(bits >> 6) & 0x3F];
    result += map[bits & 0x3F];
  } else if (tail === 2) {
    result += map[(bits >> 10) & 0x3F];
    result += map[(bits >> 4) & 0x3F];
    result += map[(bits << 2) & 0x3F];
    result += map[64];
  } else if (tail === 1) {
    result += map[(bits >> 2) & 0x3F];
    result += map[(bits << 4) & 0x3F];
    result += map[64];
    result += map[64];
  }

  return result;
}

function isBinary(obj) {
  return Object.prototype.toString.call(obj) ===  '[object Uint8Array]';
}

var binary = new type('tag:yaml.org,2002:binary', {
  kind: 'scalar',
  resolve: resolveYamlBinary,
  construct: constructYamlBinary,
  predicate: isBinary,
  represent: representYamlBinary
});

var _hasOwnProperty$3 = Object.prototype.hasOwnProperty;
var _toString$2       = Object.prototype.toString;

function resolveYamlOmap(data) {
  if (data === null) return true;

  var objectKeys = [], index, length, pair, pairKey, pairHasKey,
      object = data;

  for (index = 0, length = object.length; index < length; index += 1) {
    pair = object[index];
    pairHasKey = false;

    if (_toString$2.call(pair) !== '[object Object]') return false;

    for (pairKey in pair) {
      if (_hasOwnProperty$3.call(pair, pairKey)) {
        if (!pairHasKey) pairHasKey = true;
        else return false;
      }
    }

    if (!pairHasKey) return false;

    if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey);
    else return false;
  }

  return true;
}

function constructYamlOmap(data) {
  return data !== null ? data : [];
}

var omap = new type('tag:yaml.org,2002:omap', {
  kind: 'sequence',
  resolve: resolveYamlOmap,
  construct: constructYamlOmap
});

var _toString$1 = Object.prototype.toString;

function resolveYamlPairs(data) {
  if (data === null) return true;

  var index, length, pair, keys, result,
      object = data;

  result = new Array(object.length);

  for (index = 0, length = object.length; index < length; index += 1) {
    pair = object[index];

    if (_toString$1.call(pair) !== '[object Object]') return false;

    keys = Object.keys(pair);

    if (keys.length !== 1) return false;

    result[index] = [ keys[0], pair[keys[0]] ];
  }

  return true;
}

function constructYamlPairs(data) {
  if (data === null) return [];

  var index, length, pair, keys, result,
      object = data;

  result = new Array(object.length);

  for (index = 0, length = object.length; index < length; index += 1) {
    pair = object[index];

    keys = Object.keys(pair);

    result[index] = [ keys[0], pair[keys[0]] ];
  }

  return result;
}

var pairs = new type('tag:yaml.org,2002:pairs', {
  kind: 'sequence',
  resolve: resolveYamlPairs,
  construct: constructYamlPairs
});

var _hasOwnProperty$2 = Object.prototype.hasOwnProperty;

function resolveYamlSet(data) {
  if (data === null) return true;

  var key, object = data;

  for (key in object) {
    if (_hasOwnProperty$2.call(object, key)) {
      if (object[key] !== null) return false;
    }
  }

  return true;
}

function constructYamlSet(data) {
  return data !== null ? data : {};
}

var set = new type('tag:yaml.org,2002:set', {
  kind: 'mapping',
  resolve: resolveYamlSet,
  construct: constructYamlSet
});

var _default = core.extend({
  implicit: [
    timestamp,
    merge
  ],
  explicit: [
    binary,
    omap,
    pairs,
    set
  ]
});

/*eslint-disable max-len,no-use-before-define*/







var _hasOwnProperty$1 = Object.prototype.hasOwnProperty;


var CONTEXT_FLOW_IN   = 1;
var CONTEXT_FLOW_OUT  = 2;
var CONTEXT_BLOCK_IN  = 3;
var CONTEXT_BLOCK_OUT = 4;


var CHOMPING_CLIP  = 1;
var CHOMPING_STRIP = 2;
var CHOMPING_KEEP  = 3;


var PATTERN_NON_PRINTABLE         = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/;
var PATTERN_FLOW_INDICATORS       = /[,\[\]\{\}]/;
var PATTERN_TAG_HANDLE            = /^(?:!|!!|![a-z\-]+!)$/i;
var PATTERN_TAG_URI               = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;


function _class(obj) { return Object.prototype.toString.call(obj); }

function is_EOL(c) {
  return (c === 0x0A/* LF */) || (c === 0x0D/* CR */);
}

function is_WHITE_SPACE(c) {
  return (c === 0x09/* Tab */) || (c === 0x20/* Space */);
}

function is_WS_OR_EOL(c) {
  return (c === 0x09/* Tab */) ||
         (c === 0x20/* Space */) ||
         (c === 0x0A/* LF */) ||
         (c === 0x0D/* CR */);
}

function is_FLOW_INDICATOR(c) {
  return c === 0x2C/* , */ ||
         c === 0x5B/* [ */ ||
         c === 0x5D/* ] */ ||
         c === 0x7B/* { */ ||
         c === 0x7D/* } */;
}

function fromHexCode(c) {
  var lc;

  if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {
    return c - 0x30;
  }

  /*eslint-disable no-bitwise*/
  lc = c | 0x20;

  if ((0x61/* a */ <= lc) && (lc <= 0x66/* f */)) {
    return lc - 0x61 + 10;
  }

  return -1;
}

function escapedHexLen(c) {
  if (c === 0x78/* x */) { return 2; }
  if (c === 0x75/* u */) { return 4; }
  if (c === 0x55/* U */) { return 8; }
  return 0;
}

function fromDecimalCode(c) {
  if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {
    return c - 0x30;
  }

  return -1;
}

function simpleEscapeSequence(c) {
  /* eslint-disable indent */
  return (c === 0x30/* 0 */) ? '\x00' :
        (c === 0x61/* a */) ? '\x07' :
        (c === 0x62/* b */) ? '\x08' :
        (c === 0x74/* t */) ? '\x09' :
        (c === 0x09/* Tab */) ? '\x09' :
        (c === 0x6E/* n */) ? '\x0A' :
        (c === 0x76/* v */) ? '\x0B' :
        (c === 0x66/* f */) ? '\x0C' :
        (c === 0x72/* r */) ? '\x0D' :
        (c === 0x65/* e */) ? '\x1B' :
        (c === 0x20/* Space */) ? ' ' :
        (c === 0x22/* " */) ? '\x22' :
        (c === 0x2F/* / */) ? '/' :
        (c === 0x5C/* \ */) ? '\x5C' :
        (c === 0x4E/* N */) ? '\x85' :
        (c === 0x5F/* _ */) ? '\xA0' :
        (c === 0x4C/* L */) ? '\u2028' :
        (c === 0x50/* P */) ? '\u2029' : '';
}

function charFromCodepoint(c) {
  if (c <= 0xFFFF) {
    return String.fromCharCode(c);
  }
  // Encode UTF-16 surrogate pair
  // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF
  return String.fromCharCode(
    ((c - 0x010000) >> 10) + 0xD800,
    ((c - 0x010000) & 0x03FF) + 0xDC00
  );
}

var simpleEscapeCheck = new Array(256); // integer, for fast access
var simpleEscapeMap = new Array(256);
for (var i = 0; i < 256; i++) {
  simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0;
  simpleEscapeMap[i] = simpleEscapeSequence(i);
}


function State$1(input, options) {
  this.input = input;

  this.filename  = options['filename']  || null;
  this.schema    = options['schema']    || _default;
  this.onWarning = options['onWarning'] || null;
  // (Hidden) Remove? makes the loader to expect YAML 1.1 documents
  // if such documents have no explicit %YAML directive
  this.legacy    = options['legacy']    || false;

  this.json      = options['json']      || false;
  this.listener  = options['listener']  || null;

  this.implicitTypes = this.schema.compiledImplicit;
  this.typeMap       = this.schema.compiledTypeMap;

  this.length     = input.length;
  this.position   = 0;
  this.line       = 0;
  this.lineStart  = 0;
  this.lineIndent = 0;

  // position of first leading tab in the current line,
  // used to make sure there are no tabs in the indentation
  this.firstTabInLine = -1;

  this.documents = [];

  /*
  this.version;
  this.checkLineBreaks;
  this.tagMap;
  this.anchorMap;
  this.tag;
  this.anchor;
  this.kind;
  this.result;*/

}


function generateError(state, message) {
  var mark = {
    name:     state.filename,
    buffer:   state.input.slice(0, -1), // omit trailing \0
    position: state.position,
    line:     state.line,
    column:   state.position - state.lineStart
  };

  mark.snippet = snippet(mark);

  return new exception(message, mark);
}

function throwError(state, message) {
  throw generateError(state, message);
}

function throwWarning(state, message) {
  if (state.onWarning) {
    state.onWarning.call(null, generateError(state, message));
  }
}


var directiveHandlers = {

  YAML: function handleYamlDirective(state, name, args) {

    var match, major, minor;

    if (state.version !== null) {
      throwError(state, 'duplication of %YAML directive');
    }

    if (args.length !== 1) {
      throwError(state, 'YAML directive accepts exactly one argument');
    }

    match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]);

    if (match === null) {
      throwError(state, 'ill-formed argument of the YAML directive');
    }

    major = parseInt(match[1], 10);
    minor = parseInt(match[2], 10);

    if (major !== 1) {
      throwError(state, 'unacceptable YAML version of the document');
    }

    state.version = args[0];
    state.checkLineBreaks = (minor < 2);

    if (minor !== 1 && minor !== 2) {
      throwWarning(state, 'unsupported YAML version of the document');
    }
  },

  TAG: function handleTagDirective(state, name, args) {

    var handle, prefix;

    if (args.length !== 2) {
      throwError(state, 'TAG directive accepts exactly two arguments');
    }

    handle = args[0];
    prefix = args[1];

    if (!PATTERN_TAG_HANDLE.test(handle)) {
      throwError(state, 'ill-formed tag handle (first argument) of the TAG directive');
    }

    if (_hasOwnProperty$1.call(state.tagMap, handle)) {
      throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle');
    }

    if (!PATTERN_TAG_URI.test(prefix)) {
      throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive');
    }

    try {
      prefix = decodeURIComponent(prefix);
    } catch (err) {
      throwError(state, 'tag prefix is malformed: ' + prefix);
    }

    state.tagMap[handle] = prefix;
  }
};


function captureSegment(state, start, end, checkJson) {
  var _position, _length, _character, _result;

  if (start < end) {
    _result = state.input.slice(start, end);

    if (checkJson) {
      for (_position = 0, _length = _result.length; _position < _length; _position += 1) {
        _character = _result.charCodeAt(_position);
        if (!(_character === 0x09 ||
              (0x20 <= _character && _character <= 0x10FFFF))) {
          throwError(state, 'expected valid JSON character');
        }
      }
    } else if (PATTERN_NON_PRINTABLE.test(_result)) {
      throwError(state, 'the stream contains non-printable characters');
    }

    state.result += _result;
  }
}

function mergeMappings(state, destination, source, overridableKeys) {
  var sourceKeys, key, index, quantity;

  if (!common.isObject(source)) {
    throwError(state, 'cannot merge mappings; the provided source object is unacceptable');
  }

  sourceKeys = Object.keys(source);

  for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
    key = sourceKeys[index];

    if (!_hasOwnProperty$1.call(destination, key)) {
      destination[key] = source[key];
      overridableKeys[key] = true;
    }
  }
}

function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode,
  startLine, startLineStart, startPos) {

  var index, quantity;

  // The output is a plain object here, so keys can only be strings.
  // We need to convert keyNode to a string, but doing so can hang the process
  // (deeply nested arrays that explode exponentially using aliases).
  if (Array.isArray(keyNode)) {
    keyNode = Array.prototype.slice.call(keyNode);

    for (index = 0, quantity = keyNode.length; index < quantity; index += 1) {
      if (Array.isArray(keyNode[index])) {
        throwError(state, 'nested arrays are not supported inside keys');
      }

      if (typeof keyNode === 'object' && _class(keyNode[index]) === '[object Object]') {
        keyNode[index] = '[object Object]';
      }
    }
  }

  // Avoid code execution in load() via toString property
  // (still use its own toString for arrays, timestamps,
  // and whatever user schema extensions happen to have @@toStringTag)
  if (typeof keyNode === 'object' && _class(keyNode) === '[object Object]') {
    keyNode = '[object Object]';
  }


  keyNode = String(keyNode);

  if (_result === null) {
    _result = {};
  }

  if (keyTag === 'tag:yaml.org,2002:merge') {
    if (Array.isArray(valueNode)) {
      for (index = 0, quantity = valueNode.length; index < quantity; index += 1) {
        mergeMappings(state, _result, valueNode[index], overridableKeys);
      }
    } else {
      mergeMappings(state, _result, valueNode, overridableKeys);
    }
  } else {
    if (!state.json &&
        !_hasOwnProperty$1.call(overridableKeys, keyNode) &&
        _hasOwnProperty$1.call(_result, keyNode)) {
      state.line = startLine || state.line;
      state.lineStart = startLineStart || state.lineStart;
      state.position = startPos || state.position;
      throwError(state, 'duplicated mapping key');
    }

    // used for this specific key only because Object.defineProperty is slow
    if (keyNode === '__proto__') {
      Object.defineProperty(_result, keyNode, {
        configurable: true,
        enumerable: true,
        writable: true,
        value: valueNode
      });
    } else {
      _result[keyNode] = valueNode;
    }
    delete overridableKeys[keyNode];
  }

  return _result;
}

function readLineBreak(state) {
  var ch;

  ch = state.input.charCodeAt(state.position);

  if (ch === 0x0A/* LF */) {
    state.position++;
  } else if (ch === 0x0D/* CR */) {
    state.position++;
    if (state.input.charCodeAt(state.position) === 0x0A/* LF */) {
      state.position++;
    }
  } else {
    throwError(state, 'a line break is expected');
  }

  state.line += 1;
  state.lineStart = state.position;
  state.firstTabInLine = -1;
}

function skipSeparationSpace(state, allowComments, checkIndent) {
  var lineBreaks = 0,
      ch = state.input.charCodeAt(state.position);

  while (ch !== 0) {
    while (is_WHITE_SPACE(ch)) {
      if (ch === 0x09/* Tab */ && state.firstTabInLine === -1) {
        state.firstTabInLine = state.position;
      }
      ch = state.input.charCodeAt(++state.position);
    }

    if (allowComments && ch === 0x23/* # */) {
      do {
        ch = state.input.charCodeAt(++state.position);
      } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0);
    }

    if (is_EOL(ch)) {
      readLineBreak(state);

      ch = state.input.charCodeAt(state.position);
      lineBreaks++;
      state.lineIndent = 0;

      while (ch === 0x20/* Space */) {
        state.lineIndent++;
        ch = state.input.charCodeAt(++state.position);
      }
    } else {
      break;
    }
  }

  if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {
    throwWarning(state, 'deficient indentation');
  }

  return lineBreaks;
}

function testDocumentSeparator(state) {
  var _position = state.position,
      ch;

  ch = state.input.charCodeAt(_position);

  // Condition state.position === state.lineStart is tested
  // in parent on each call, for efficiency. No needs to test here again.
  if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) &&
      ch === state.input.charCodeAt(_position + 1) &&
      ch === state.input.charCodeAt(_position + 2)) {

    _position += 3;

    ch = state.input.charCodeAt(_position);

    if (ch === 0 || is_WS_OR_EOL(ch)) {
      return true;
    }
  }

  return false;
}

function writeFoldedLines(state, count) {
  if (count === 1) {
    state.result += ' ';
  } else if (count > 1) {
    state.result += common.repeat('\n', count - 1);
  }
}


function readPlainScalar(state, nodeIndent, withinFlowCollection) {
  var preceding,
      following,
      captureStart,
      captureEnd,
      hasPendingContent,
      _line,
      _lineStart,
      _lineIndent,
      _kind = state.kind,
      _result = state.result,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (is_WS_OR_EOL(ch)      ||
      is_FLOW_INDICATOR(ch) ||
      ch === 0x23/* # */    ||
      ch === 0x26/* & */    ||
      ch === 0x2A/* * */    ||
      ch === 0x21/* ! */    ||
      ch === 0x7C/* | */    ||
      ch === 0x3E/* > */    ||
      ch === 0x27/* ' */    ||
      ch === 0x22/* " */    ||
      ch === 0x25/* % */    ||
      ch === 0x40/* @ */    ||
      ch === 0x60/* ` */) {
    return false;
  }

  if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) {
    following = state.input.charCodeAt(state.position + 1);

    if (is_WS_OR_EOL(following) ||
        withinFlowCollection && is_FLOW_INDICATOR(following)) {
      return false;
    }
  }

  state.kind = 'scalar';
  state.result = '';
  captureStart = captureEnd = state.position;
  hasPendingContent = false;

  while (ch !== 0) {
    if (ch === 0x3A/* : */) {
      following = state.input.charCodeAt(state.position + 1);

      if (is_WS_OR_EOL(following) ||
          withinFlowCollection && is_FLOW_INDICATOR(following)) {
        break;
      }

    } else if (ch === 0x23/* # */) {
      preceding = state.input.charCodeAt(state.position - 1);

      if (is_WS_OR_EOL(preceding)) {
        break;
      }

    } else if ((state.position === state.lineStart && testDocumentSeparator(state)) ||
               withinFlowCollection && is_FLOW_INDICATOR(ch)) {
      break;

    } else if (is_EOL(ch)) {
      _line = state.line;
      _lineStart = state.lineStart;
      _lineIndent = state.lineIndent;
      skipSeparationSpace(state, false, -1);

      if (state.lineIndent >= nodeIndent) {
        hasPendingContent = true;
        ch = state.input.charCodeAt(state.position);
        continue;
      } else {
        state.position = captureEnd;
        state.line = _line;
        state.lineStart = _lineStart;
        state.lineIndent = _lineIndent;
        break;
      }
    }

    if (hasPendingContent) {
      captureSegment(state, captureStart, captureEnd, false);
      writeFoldedLines(state, state.line - _line);
      captureStart = captureEnd = state.position;
      hasPendingContent = false;
    }

    if (!is_WHITE_SPACE(ch)) {
      captureEnd = state.position + 1;
    }

    ch = state.input.charCodeAt(++state.position);
  }

  captureSegment(state, captureStart, captureEnd, false);

  if (state.result) {
    return true;
  }

  state.kind = _kind;
  state.result = _result;
  return false;
}

function readSingleQuotedScalar(state, nodeIndent) {
  var ch,
      captureStart, captureEnd;

  ch = state.input.charCodeAt(state.position);

  if (ch !== 0x27/* ' */) {
    return false;
  }

  state.kind = 'scalar';
  state.result = '';
  state.position++;
  captureStart = captureEnd = state.position;

  while ((ch = state.input.charCodeAt(state.position)) !== 0) {
    if (ch === 0x27/* ' */) {
      captureSegment(state, captureStart, state.position, true);
      ch = state.input.charCodeAt(++state.position);

      if (ch === 0x27/* ' */) {
        captureStart = state.position;
        state.position++;
        captureEnd = state.position;
      } else {
        return true;
      }

    } else if (is_EOL(ch)) {
      captureSegment(state, captureStart, captureEnd, true);
      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
      captureStart = captureEnd = state.position;

    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
      throwError(state, 'unexpected end of the document within a single quoted scalar');

    } else {
      state.position++;
      captureEnd = state.position;
    }
  }

  throwError(state, 'unexpected end of the stream within a single quoted scalar');
}

function readDoubleQuotedScalar(state, nodeIndent) {
  var captureStart,
      captureEnd,
      hexLength,
      hexResult,
      tmp,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (ch !== 0x22/* " */) {
    return false;
  }

  state.kind = 'scalar';
  state.result = '';
  state.position++;
  captureStart = captureEnd = state.position;

  while ((ch = state.input.charCodeAt(state.position)) !== 0) {
    if (ch === 0x22/* " */) {
      captureSegment(state, captureStart, state.position, true);
      state.position++;
      return true;

    } else if (ch === 0x5C/* \ */) {
      captureSegment(state, captureStart, state.position, true);
      ch = state.input.charCodeAt(++state.position);

      if (is_EOL(ch)) {
        skipSeparationSpace(state, false, nodeIndent);

        // TODO: rework to inline fn with no type cast?
      } else if (ch < 256 && simpleEscapeCheck[ch]) {
        state.result += simpleEscapeMap[ch];
        state.position++;

      } else if ((tmp = escapedHexLen(ch)) > 0) {
        hexLength = tmp;
        hexResult = 0;

        for (; hexLength > 0; hexLength--) {
          ch = state.input.charCodeAt(++state.position);

          if ((tmp = fromHexCode(ch)) >= 0) {
            hexResult = (hexResult << 4) + tmp;

          } else {
            throwError(state, 'expected hexadecimal character');
          }
        }

        state.result += charFromCodepoint(hexResult);

        state.position++;

      } else {
        throwError(state, 'unknown escape sequence');
      }

      captureStart = captureEnd = state.position;

    } else if (is_EOL(ch)) {
      captureSegment(state, captureStart, captureEnd, true);
      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
      captureStart = captureEnd = state.position;

    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
      throwError(state, 'unexpected end of the document within a double quoted scalar');

    } else {
      state.position++;
      captureEnd = state.position;
    }
  }

  throwError(state, 'unexpected end of the stream within a double quoted scalar');
}

function readFlowCollection(state, nodeIndent) {
  var readNext = true,
      _line,
      _lineStart,
      _pos,
      _tag     = state.tag,
      _result,
      _anchor  = state.anchor,
      following,
      terminator,
      isPair,
      isExplicitPair,
      isMapping,
      overridableKeys = Object.create(null),
      keyNode,
      keyTag,
      valueNode,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (ch === 0x5B/* [ */) {
    terminator = 0x5D;/* ] */
    isMapping = false;
    _result = [];
  } else if (ch === 0x7B/* { */) {
    terminator = 0x7D;/* } */
    isMapping = true;
    _result = {};
  } else {
    return false;
  }

  if (state.anchor !== null) {
    state.anchorMap[state.anchor] = _result;
  }

  ch = state.input.charCodeAt(++state.position);

  while (ch !== 0) {
    skipSeparationSpace(state, true, nodeIndent);

    ch = state.input.charCodeAt(state.position);

    if (ch === terminator) {
      state.position++;
      state.tag = _tag;
      state.anchor = _anchor;
      state.kind = isMapping ? 'mapping' : 'sequence';
      state.result = _result;
      return true;
    } else if (!readNext) {
      throwError(state, 'missed comma between flow collection entries');
    } else if (ch === 0x2C/* , */) {
      // "flow collection entries can never be completely empty", as per YAML 1.2, section 7.4
      throwError(state, "expected the node content, but found ','");
    }

    keyTag = keyNode = valueNode = null;
    isPair = isExplicitPair = false;

    if (ch === 0x3F/* ? */) {
      following = state.input.charCodeAt(state.position + 1);

      if (is_WS_OR_EOL(following)) {
        isPair = isExplicitPair = true;
        state.position++;
        skipSeparationSpace(state, true, nodeIndent);
      }
    }

    _line = state.line; // Save the current line.
    _lineStart = state.lineStart;
    _pos = state.position;
    composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
    keyTag = state.tag;
    keyNode = state.result;
    skipSeparationSpace(state, true, nodeIndent);

    ch = state.input.charCodeAt(state.position);

    if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) {
      isPair = true;
      ch = state.input.charCodeAt(++state.position);
      skipSeparationSpace(state, true, nodeIndent);
      composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
      valueNode = state.result;
    }

    if (isMapping) {
      storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos);
    } else if (isPair) {
      _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos));
    } else {
      _result.push(keyNode);
    }

    skipSeparationSpace(state, true, nodeIndent);

    ch = state.input.charCodeAt(state.position);

    if (ch === 0x2C/* , */) {
      readNext = true;
      ch = state.input.charCodeAt(++state.position);
    } else {
      readNext = false;
    }
  }

  throwError(state, 'unexpected end of the stream within a flow collection');
}

function readBlockScalar(state, nodeIndent) {
  var captureStart,
      folding,
      chomping       = CHOMPING_CLIP,
      didReadContent = false,
      detectedIndent = false,
      textIndent     = nodeIndent,
      emptyLines     = 0,
      atMoreIndented = false,
      tmp,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (ch === 0x7C/* | */) {
    folding = false;
  } else if (ch === 0x3E/* > */) {
    folding = true;
  } else {
    return false;
  }

  state.kind = 'scalar';
  state.result = '';

  while (ch !== 0) {
    ch = state.input.charCodeAt(++state.position);

    if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {
      if (CHOMPING_CLIP === chomping) {
        chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP;
      } else {
        throwError(state, 'repeat of a chomping mode identifier');
      }

    } else if ((tmp = fromDecimalCode(ch)) >= 0) {
      if (tmp === 0) {
        throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one');
      } else if (!detectedIndent) {
        textIndent = nodeIndent + tmp - 1;
        detectedIndent = true;
      } else {
        throwError(state, 'repeat of an indentation width identifier');
      }

    } else {
      break;
    }
  }

  if (is_WHITE_SPACE(ch)) {
    do { ch = state.input.charCodeAt(++state.position); }
    while (is_WHITE_SPACE(ch));

    if (ch === 0x23/* # */) {
      do { ch = state.input.charCodeAt(++state.position); }
      while (!is_EOL(ch) && (ch !== 0));
    }
  }

  while (ch !== 0) {
    readLineBreak(state);
    state.lineIndent = 0;

    ch = state.input.charCodeAt(state.position);

    while ((!detectedIndent || state.lineIndent < textIndent) &&
           (ch === 0x20/* Space */)) {
      state.lineIndent++;
      ch = state.input.charCodeAt(++state.position);
    }

    if (!detectedIndent && state.lineIndent > textIndent) {
      textIndent = state.lineIndent;
    }

    if (is_EOL(ch)) {
      emptyLines++;
      continue;
    }

    // End of the scalar.
    if (state.lineIndent < textIndent) {

      // Perform the chomping.
      if (chomping === CHOMPING_KEEP) {
        state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
      } else if (chomping === CHOMPING_CLIP) {
        if (didReadContent) { // i.e. only if the scalar is not empty.
          state.result += '\n';
        }
      }

      // Break this `while` cycle and go to the funciton's epilogue.
      break;
    }

    // Folded style: use fancy rules to handle line breaks.
    if (folding) {

      // Lines starting with white space characters (more-indented lines) are not folded.
      if (is_WHITE_SPACE(ch)) {
        atMoreIndented = true;
        // except for the first content line (cf. Example 8.1)
        state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);

      // End of more-indented block.
      } else if (atMoreIndented) {
        atMoreIndented = false;
        state.result += common.repeat('\n', emptyLines + 1);

      // Just one line break - perceive as the same line.
      } else if (emptyLines === 0) {
        if (didReadContent) { // i.e. only if we have already read some scalar content.
          state.result += ' ';
        }

      // Several line breaks - perceive as different lines.
      } else {
        state.result += common.repeat('\n', emptyLines);
      }

    // Literal style: just add exact number of line breaks between content lines.
    } else {
      // Keep all line breaks except the header line break.
      state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
    }

    didReadContent = true;
    detectedIndent = true;
    emptyLines = 0;
    captureStart = state.position;

    while (!is_EOL(ch) && (ch !== 0)) {
      ch = state.input.charCodeAt(++state.position);
    }

    captureSegment(state, captureStart, state.position, false);
  }

  return true;
}

function readBlockSequence(state, nodeIndent) {
  var _line,
      _tag      = state.tag,
      _anchor   = state.anchor,
      _result   = [],
      following,
      detected  = false,
      ch;

  // there is a leading tab before this token, so it can't be a block sequence/mapping;
  // it can still be flow sequence/mapping or a scalar
  if (state.firstTabInLine !== -1) return false;

  if (state.anchor !== null) {
    state.anchorMap[state.anchor] = _result;
  }

  ch = state.input.charCodeAt(state.position);

  while (ch !== 0) {
    if (state.firstTabInLine !== -1) {
      state.position = state.firstTabInLine;
      throwError(state, 'tab characters must not be used in indentation');
    }

    if (ch !== 0x2D/* - */) {
      break;
    }

    following = state.input.charCodeAt(state.position + 1);

    if (!is_WS_OR_EOL(following)) {
      break;
    }

    detected = true;
    state.position++;

    if (skipSeparationSpace(state, true, -1)) {
      if (state.lineIndent <= nodeIndent) {
        _result.push(null);
        ch = state.input.charCodeAt(state.position);
        continue;
      }
    }

    _line = state.line;
    composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true);
    _result.push(state.result);
    skipSeparationSpace(state, true, -1);

    ch = state.input.charCodeAt(state.position);

    if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {
      throwError(state, 'bad indentation of a sequence entry');
    } else if (state.lineIndent < nodeIndent) {
      break;
    }
  }

  if (detected) {
    state.tag = _tag;
    state.anchor = _anchor;
    state.kind = 'sequence';
    state.result = _result;
    return true;
  }
  return false;
}

function readBlockMapping(state, nodeIndent, flowIndent) {
  var following,
      allowCompact,
      _line,
      _keyLine,
      _keyLineStart,
      _keyPos,
      _tag          = state.tag,
      _anchor       = state.anchor,
      _result       = {},
      overridableKeys = Object.create(null),
      keyTag        = null,
      keyNode       = null,
      valueNode     = null,
      atExplicitKey = false,
      detected      = false,
      ch;

  // there is a leading tab before this token, so it can't be a block sequence/mapping;
  // it can still be flow sequence/mapping or a scalar
  if (state.firstTabInLine !== -1) return false;

  if (state.anchor !== null) {
    state.anchorMap[state.anchor] = _result;
  }

  ch = state.input.charCodeAt(state.position);

  while (ch !== 0) {
    if (!atExplicitKey && state.firstTabInLine !== -1) {
      state.position = state.firstTabInLine;
      throwError(state, 'tab characters must not be used in indentation');
    }

    following = state.input.charCodeAt(state.position + 1);
    _line = state.line; // Save the current line.

    //
    // Explicit notation case. There are two separate blocks:
    // first for the key (denoted by "?") and second for the value (denoted by ":")
    //
    if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && is_WS_OR_EOL(following)) {

      if (ch === 0x3F/* ? */) {
        if (atExplicitKey) {
          storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
          keyTag = keyNode = valueNode = null;
        }

        detected = true;
        atExplicitKey = true;
        allowCompact = true;

      } else if (atExplicitKey) {
        // i.e. 0x3A/* : */ === character after the explicit key.
        atExplicitKey = false;
        allowCompact = true;

      } else {
        throwError(state, 'incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line');
      }

      state.position += 1;
      ch = following;

    //
    // Implicit notation case. Flow-style node as the key first, then ":", and the value.
    //
    } else {
      _keyLine = state.line;
      _keyLineStart = state.lineStart;
      _keyPos = state.position;

      if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {
        // Neither implicit nor explicit notation.
        // Reading is done. Go to the epilogue.
        break;
      }

      if (state.line === _line) {
        ch = state.input.charCodeAt(state.position);

        while (is_WHITE_SPACE(ch)) {
          ch = state.input.charCodeAt(++state.position);
        }

        if (ch === 0x3A/* : */) {
          ch = state.input.charCodeAt(++state.position);

          if (!is_WS_OR_EOL(ch)) {
            throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping');
          }

          if (atExplicitKey) {
            storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
            keyTag = keyNode = valueNode = null;
          }

          detected = true;
          atExplicitKey = false;
          allowCompact = false;
          keyTag = state.tag;
          keyNode = state.result;

        } else if (detected) {
          throwError(state, 'can not read an implicit mapping pair; a colon is missed');

        } else {
          state.tag = _tag;
          state.anchor = _anchor;
          return true; // Keep the result of `composeNode`.
        }

      } else if (detected) {
        throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key');

      } else {
        state.tag = _tag;
        state.anchor = _anchor;
        return true; // Keep the result of `composeNode`.
      }
    }

    //
    // Common reading code for both explicit and implicit notations.
    //
    if (state.line === _line || state.lineIndent > nodeIndent) {
      if (atExplicitKey) {
        _keyLine = state.line;
        _keyLineStart = state.lineStart;
        _keyPos = state.position;
      }

      if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {
        if (atExplicitKey) {
          keyNode = state.result;
        } else {
          valueNode = state.result;
        }
      }

      if (!atExplicitKey) {
        storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos);
        keyTag = keyNode = valueNode = null;
      }

      skipSeparationSpace(state, true, -1);
      ch = state.input.charCodeAt(state.position);
    }

    if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {
      throwError(state, 'bad indentation of a mapping entry');
    } else if (state.lineIndent < nodeIndent) {
      break;
    }
  }

  //
  // Epilogue.
  //

  // Special case: last mapping's node contains only the key in explicit notation.
  if (atExplicitKey) {
    storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
  }

  // Expose the resulting mapping.
  if (detected) {
    state.tag = _tag;
    state.anchor = _anchor;
    state.kind = 'mapping';
    state.result = _result;
  }

  return detected;
}

function readTagProperty(state) {
  var _position,
      isVerbatim = false,
      isNamed    = false,
      tagHandle,
      tagName,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (ch !== 0x21/* ! */) return false;

  if (state.tag !== null) {
    throwError(state, 'duplication of a tag property');
  }

  ch = state.input.charCodeAt(++state.position);

  if (ch === 0x3C/* < */) {
    isVerbatim = true;
    ch = state.input.charCodeAt(++state.position);

  } else if (ch === 0x21/* ! */) {
    isNamed = true;
    tagHandle = '!!';
    ch = state.input.charCodeAt(++state.position);

  } else {
    tagHandle = '!';
  }

  _position = state.position;

  if (isVerbatim) {
    do { ch = state.input.charCodeAt(++state.position); }
    while (ch !== 0 && ch !== 0x3E/* > */);

    if (state.position < state.length) {
      tagName = state.input.slice(_position, state.position);
      ch = state.input.charCodeAt(++state.position);
    } else {
      throwError(state, 'unexpected end of the stream within a verbatim tag');
    }
  } else {
    while (ch !== 0 && !is_WS_OR_EOL(ch)) {

      if (ch === 0x21/* ! */) {
        if (!isNamed) {
          tagHandle = state.input.slice(_position - 1, state.position + 1);

          if (!PATTERN_TAG_HANDLE.test(tagHandle)) {
            throwError(state, 'named tag handle cannot contain such characters');
          }

          isNamed = true;
          _position = state.position + 1;
        } else {
          throwError(state, 'tag suffix cannot contain exclamation marks');
        }
      }

      ch = state.input.charCodeAt(++state.position);
    }

    tagName = state.input.slice(_position, state.position);

    if (PATTERN_FLOW_INDICATORS.test(tagName)) {
      throwError(state, 'tag suffix cannot contain flow indicator characters');
    }
  }

  if (tagName && !PATTERN_TAG_URI.test(tagName)) {
    throwError(state, 'tag name cannot contain such characters: ' + tagName);
  }

  try {
    tagName = decodeURIComponent(tagName);
  } catch (err) {
    throwError(state, 'tag name is malformed: ' + tagName);
  }

  if (isVerbatim) {
    state.tag = tagName;

  } else if (_hasOwnProperty$1.call(state.tagMap, tagHandle)) {
    state.tag = state.tagMap[tagHandle] + tagName;

  } else if (tagHandle === '!') {
    state.tag = '!' + tagName;

  } else if (tagHandle === '!!') {
    state.tag = 'tag:yaml.org,2002:' + tagName;

  } else {
    throwError(state, 'undeclared tag handle "' + tagHandle + '"');
  }

  return true;
}

function readAnchorProperty(state) {
  var _position,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (ch !== 0x26/* & */) return false;

  if (state.anchor !== null) {
    throwError(state, 'duplication of an anchor property');
  }

  ch = state.input.charCodeAt(++state.position);
  _position = state.position;

  while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
    ch = state.input.charCodeAt(++state.position);
  }

  if (state.position === _position) {
    throwError(state, 'name of an anchor node must contain at least one character');
  }

  state.anchor = state.input.slice(_position, state.position);
  return true;
}

function readAlias(state) {
  var _position, alias,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (ch !== 0x2A/* * */) return false;

  ch = state.input.charCodeAt(++state.position);
  _position = state.position;

  while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
    ch = state.input.charCodeAt(++state.position);
  }

  if (state.position === _position) {
    throwError(state, 'name of an alias node must contain at least one character');
  }

  alias = state.input.slice(_position, state.position);

  if (!_hasOwnProperty$1.call(state.anchorMap, alias)) {
    throwError(state, 'unidentified alias "' + alias + '"');
  }

  state.result = state.anchorMap[alias];
  skipSeparationSpace(state, true, -1);
  return true;
}

function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) {
  var allowBlockStyles,
      allowBlockScalars,
      allowBlockCollections,
      indentStatus = 1, // 1: this>parent, 0: this=parent, -1: this<parent
      atNewLine  = false,
      hasContent = false,
      typeIndex,
      typeQuantity,
      typeList,
      type,
      flowIndent,
      blockIndent;

  if (state.listener !== null) {
    state.listener('open', state);
  }

  state.tag    = null;
  state.anchor = null;
  state.kind   = null;
  state.result = null;

  allowBlockStyles = allowBlockScalars = allowBlockCollections =
    CONTEXT_BLOCK_OUT === nodeContext ||
    CONTEXT_BLOCK_IN  === nodeContext;

  if (allowToSeek) {
    if (skipSeparationSpace(state, true, -1)) {
      atNewLine = true;

      if (state.lineIndent > parentIndent) {
        indentStatus = 1;
      } else if (state.lineIndent === parentIndent) {
        indentStatus = 0;
      } else if (state.lineIndent < parentIndent) {
        indentStatus = -1;
      }
    }
  }

  if (indentStatus === 1) {
    while (readTagProperty(state) || readAnchorProperty(state)) {
      if (skipSeparationSpace(state, true, -1)) {
        atNewLine = true;
        allowBlockCollections = allowBlockStyles;

        if (state.lineIndent > parentIndent) {
          indentStatus = 1;
        } else if (state.lineIndent === parentIndent) {
          indentStatus = 0;
        } else if (state.lineIndent < parentIndent) {
          indentStatus = -1;
        }
      } else {
        allowBlockCollections = false;
      }
    }
  }

  if (allowBlockCollections) {
    allowBlockCollections = atNewLine || allowCompact;
  }

  if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {
    if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {
      flowIndent = parentIndent;
    } else {
      flowIndent = parentIndent + 1;
    }

    blockIndent = state.position - state.lineStart;

    if (indentStatus === 1) {
      if (allowBlockCollections &&
          (readBlockSequence(state, blockIndent) ||
           readBlockMapping(state, blockIndent, flowIndent)) ||
          readFlowCollection(state, flowIndent)) {
        hasContent = true;
      } else {
        if ((allowBlockScalars && readBlockScalar(state, flowIndent)) ||
            readSingleQuotedScalar(state, flowIndent) ||
            readDoubleQuotedScalar(state, flowIndent)) {
          hasContent = true;

        } else if (readAlias(state)) {
          hasContent = true;

          if (state.tag !== null || state.anchor !== null) {
            throwError(state, 'alias node should not have any properties');
          }

        } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {
          hasContent = true;

          if (state.tag === null) {
            state.tag = '?';
          }
        }

        if (state.anchor !== null) {
          state.anchorMap[state.anchor] = state.result;
        }
      }
    } else if (indentStatus === 0) {
      // Special case: block sequences are allowed to have same indentation level as the parent.
      // http://www.yaml.org/spec/1.2/spec.html#id2799784
      hasContent = allowBlockCollections && readBlockSequence(state, blockIndent);
    }
  }

  if (state.tag === null) {
    if (state.anchor !== null) {
      state.anchorMap[state.anchor] = state.result;
    }

  } else if (state.tag === '?') {
    // Implicit resolving is not allowed for non-scalar types, and '?'
    // non-specific tag is only automatically assigned to plain scalars.
    //
    // We only need to check kind conformity in case user explicitly assigns '?'
    // tag, for example like this: "!<?> [0]"
    //
    if (state.result !== null && state.kind !== 'scalar') {
      throwError(state, 'unacceptable node kind for !<?> tag; it should be "scalar", not "' + state.kind + '"');
    }

    for (typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {
      type = state.implicitTypes[typeIndex];

      if (type.resolve(state.result)) { // `state.result` updated in resolver if matched
        state.result = type.construct(state.result);
        state.tag = type.tag;
        if (state.anchor !== null) {
          state.anchorMap[state.anchor] = state.result;
        }
        break;
      }
    }
  } else if (state.tag !== '!') {
    if (_hasOwnProperty$1.call(state.typeMap[state.kind || 'fallback'], state.tag)) {
      type = state.typeMap[state.kind || 'fallback'][state.tag];
    } else {
      // looking for multi type
      type = null;
      typeList = state.typeMap.multi[state.kind || 'fallback'];

      for (typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) {
        if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) {
          type = typeList[typeIndex];
          break;
        }
      }
    }

    if (!type) {
      throwError(state, 'unknown tag !<' + state.tag + '>');
    }

    if (state.result !== null && type.kind !== state.kind) {
      throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be "' + type.kind + '", not "' + state.kind + '"');
    }

    if (!type.resolve(state.result, state.tag)) { // `state.result` updated in resolver if matched
      throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag');
    } else {
      state.result = type.construct(state.result, state.tag);
      if (state.anchor !== null) {
        state.anchorMap[state.anchor] = state.result;
      }
    }
  }

  if (state.listener !== null) {
    state.listener('close', state);
  }
  return state.tag !== null ||  state.anchor !== null || hasContent;
}

function readDocument(state) {
  var documentStart = state.position,
      _position,
      directiveName,
      directiveArgs,
      hasDirectives = false,
      ch;

  state.version = null;
  state.checkLineBreaks = state.legacy;
  state.tagMap = Object.create(null);
  state.anchorMap = Object.create(null);

  while ((ch = state.input.charCodeAt(state.position)) !== 0) {
    skipSeparationSpace(state, true, -1);

    ch = state.input.charCodeAt(state.position);

    if (state.lineIndent > 0 || ch !== 0x25/* % */) {
      break;
    }

    hasDirectives = true;
    ch = state.input.charCodeAt(++state.position);
    _position = state.position;

    while (ch !== 0 && !is_WS_OR_EOL(ch)) {
      ch = state.input.charCodeAt(++state.position);
    }

    directiveName = state.input.slice(_position, state.position);
    directiveArgs = [];

    if (directiveName.length < 1) {
      throwError(state, 'directive name must not be less than one character in length');
    }

    while (ch !== 0) {
      while (is_WHITE_SPACE(ch)) {
        ch = state.input.charCodeAt(++state.position);
      }

      if (ch === 0x23/* # */) {
        do { ch = state.input.charCodeAt(++state.position); }
        while (ch !== 0 && !is_EOL(ch));
        break;
      }

      if (is_EOL(ch)) break;

      _position = state.position;

      while (ch !== 0 && !is_WS_OR_EOL(ch)) {
        ch = state.input.charCodeAt(++state.position);
      }

      directiveArgs.push(state.input.slice(_position, state.position));
    }

    if (ch !== 0) readLineBreak(state);

    if (_hasOwnProperty$1.call(directiveHandlers, directiveName)) {
      directiveHandlers[directiveName](state, directiveName, directiveArgs);
    } else {
      throwWarning(state, 'unknown document directive "' + directiveName + '"');
    }
  }

  skipSeparationSpace(state, true, -1);

  if (state.lineIndent === 0 &&
      state.input.charCodeAt(state.position)     === 0x2D/* - */ &&
      state.input.charCodeAt(state.position + 1) === 0x2D/* - */ &&
      state.input.charCodeAt(state.position + 2) === 0x2D/* - */) {
    state.position += 3;
    skipSeparationSpace(state, true, -1);

  } else if (hasDirectives) {
    throwError(state, 'directives end mark is expected');
  }

  composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true);
  skipSeparationSpace(state, true, -1);

  if (state.checkLineBreaks &&
      PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {
    throwWarning(state, 'non-ASCII line breaks are interpreted as content');
  }

  state.documents.push(state.result);

  if (state.position === state.lineStart && testDocumentSeparator(state)) {

    if (state.input.charCodeAt(state.position) === 0x2E/* . */) {
      state.position += 3;
      skipSeparationSpace(state, true, -1);
    }
    return;
  }

  if (state.position < (state.length - 1)) {
    throwError(state, 'end of the stream or a document separator is expected');
  } else {
    return;
  }
}


function loadDocuments(input, options) {
  input = String(input);
  options = options || {};

  if (input.length !== 0) {

    // Add tailing `\n` if not exists
    if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ &&
        input.charCodeAt(input.length - 1) !== 0x0D/* CR */) {
      input += '\n';
    }

    // Strip BOM
    if (input.charCodeAt(0) === 0xFEFF) {
      input = input.slice(1);
    }
  }

  var state = new State$1(input, options);

  var nullpos = input.indexOf('\0');

  if (nullpos !== -1) {
    state.position = nullpos;
    throwError(state, 'null byte is not allowed in input');
  }

  // Use 0 as string terminator. That significantly simplifies bounds check.
  state.input += '\0';

  while (state.input.charCodeAt(state.position) === 0x20/* Space */) {
    state.lineIndent += 1;
    state.position += 1;
  }

  while (state.position < (state.length - 1)) {
    readDocument(state);
  }

  return state.documents;
}


function loadAll$1(input, iterator, options) {
  if (iterator !== null && typeof iterator === 'object' && typeof options === 'undefined') {
    options = iterator;
    iterator = null;
  }

  var documents = loadDocuments(input, options);

  if (typeof iterator !== 'function') {
    return documents;
  }

  for (var index = 0, length = documents.length; index < length; index += 1) {
    iterator(documents[index]);
  }
}


function load$1(input, options) {
  var documents = loadDocuments(input, options);

  if (documents.length === 0) {
    /*eslint-disable no-undefined*/
    return undefined;
  } else if (documents.length === 1) {
    return documents[0];
  }
  throw new exception('expected a single document in the stream, but found more');
}


var loadAll_1 = loadAll$1;
var load_1    = load$1;

var loader = {
	loadAll: loadAll_1,
	load: load_1
};

/*eslint-disable no-use-before-define*/





var _toString       = Object.prototype.toString;
var _hasOwnProperty = Object.prototype.hasOwnProperty;

var CHAR_BOM                  = 0xFEFF;
var CHAR_TAB                  = 0x09; /* Tab */
var CHAR_LINE_FEED            = 0x0A; /* LF */
var CHAR_CARRIAGE_RETURN      = 0x0D; /* CR */
var CHAR_SPACE                = 0x20; /* Space */
var CHAR_EXCLAMATION          = 0x21; /* ! */
var CHAR_DOUBLE_QUOTE         = 0x22; /* " */
var CHAR_SHARP                = 0x23; /* # */
var CHAR_PERCENT              = 0x25; /* % */
var CHAR_AMPERSAND            = 0x26; /* & */
var CHAR_SINGLE_QUOTE         = 0x27; /* ' */
var CHAR_ASTERISK             = 0x2A; /* * */
var CHAR_COMMA                = 0x2C; /* , */
var CHAR_MINUS                = 0x2D; /* - */
var CHAR_COLON                = 0x3A; /* : */
var CHAR_EQUALS               = 0x3D; /* = */
var CHAR_GREATER_THAN         = 0x3E; /* > */
var CHAR_QUESTION             = 0x3F; /* ? */
var CHAR_COMMERCIAL_AT        = 0x40; /* @ */
var CHAR_LEFT_SQUARE_BRACKET  = 0x5B; /* [ */
var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */
var CHAR_GRAVE_ACCENT         = 0x60; /* ` */
var CHAR_LEFT_CURLY_BRACKET   = 0x7B; /* { */
var CHAR_VERTICAL_LINE        = 0x7C; /* | */
var CHAR_RIGHT_CURLY_BRACKET  = 0x7D; /* } */

var ESCAPE_SEQUENCES = {};

ESCAPE_SEQUENCES[0x00]   = '\\0';
ESCAPE_SEQUENCES[0x07]   = '\\a';
ESCAPE_SEQUENCES[0x08]   = '\\b';
ESCAPE_SEQUENCES[0x09]   = '\\t';
ESCAPE_SEQUENCES[0x0A]   = '\\n';
ESCAPE_SEQUENCES[0x0B]   = '\\v';
ESCAPE_SEQUENCES[0x0C]   = '\\f';
ESCAPE_SEQUENCES[0x0D]   = '\\r';
ESCAPE_SEQUENCES[0x1B]   = '\\e';
ESCAPE_SEQUENCES[0x22]   = '\\"';
ESCAPE_SEQUENCES[0x5C]   = '\\\\';
ESCAPE_SEQUENCES[0x85]   = '\\N';
ESCAPE_SEQUENCES[0xA0]   = '\\_';
ESCAPE_SEQUENCES[0x2028] = '\\L';
ESCAPE_SEQUENCES[0x2029] = '\\P';

var DEPRECATED_BOOLEANS_SYNTAX = [
  'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',
  'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'
];

var DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;

function compileStyleMap(schema, map) {
  var result, keys, index, length, tag, style, type;

  if (map === null) return {};

  result = {};
  keys = Object.keys(map);

  for (index = 0, length = keys.length; index < length; index += 1) {
    tag = keys[index];
    style = String(map[tag]);

    if (tag.slice(0, 2) === '!!') {
      tag = 'tag:yaml.org,2002:' + tag.slice(2);
    }
    type = schema.compiledTypeMap['fallback'][tag];

    if (type && _hasOwnProperty.call(type.styleAliases, style)) {
      style = type.styleAliases[style];
    }

    result[tag] = style;
  }

  return result;
}

function encodeHex(character) {
  var string, handle, length;

  string = character.toString(16).toUpperCase();

  if (character <= 0xFF) {
    handle = 'x';
    length = 2;
  } else if (character <= 0xFFFF) {
    handle = 'u';
    length = 4;
  } else if (character <= 0xFFFFFFFF) {
    handle = 'U';
    length = 8;
  } else {
    throw new exception('code point within a string may not be greater than 0xFFFFFFFF');
  }

  return '\\' + handle + common.repeat('0', length - string.length) + string;
}


var QUOTING_TYPE_SINGLE = 1,
    QUOTING_TYPE_DOUBLE = 2;

function State(options) {
  this.schema        = options['schema'] || _default;
  this.indent        = Math.max(1, (options['indent'] || 2));
  this.noArrayIndent = options['noArrayIndent'] || false;
  this.skipInvalid   = options['skipInvalid'] || false;
  this.flowLevel     = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']);
  this.styleMap      = compileStyleMap(this.schema, options['styles'] || null);
  this.sortKeys      = options['sortKeys'] || false;
  this.lineWidth     = options['lineWidth'] || 80;
  this.noRefs        = options['noRefs'] || false;
  this.noCompatMode  = options['noCompatMode'] || false;
  this.condenseFlow  = options['condenseFlow'] || false;
  this.quotingType   = options['quotingType'] === '"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE;
  this.forceQuotes   = options['forceQuotes'] || false;
  this.replacer      = typeof options['replacer'] === 'function' ? options['replacer'] : null;

  this.implicitTypes = this.schema.compiledImplicit;
  this.explicitTypes = this.schema.compiledExplicit;

  this.tag = null;
  this.result = '';

  this.duplicates = [];
  this.usedDuplicates = null;
}

// Indents every line in a string. Empty lines (\n only) are not indented.
function indentString(string, spaces) {
  var ind = common.repeat(' ', spaces),
      position = 0,
      next = -1,
      result = '',
      line,
      length = string.length;

  while (position < length) {
    next = string.indexOf('\n', position);
    if (next === -1) {
      line = string.slice(position);
      position = length;
    } else {
      line = string.slice(position, next + 1);
      position = next + 1;
    }

    if (line.length && line !== '\n') result += ind;

    result += line;
  }

  return result;
}

function generateNextLine(state, level) {
  return '\n' + common.repeat(' ', state.indent * level);
}

function testImplicitResolving(state, str) {
  var index, length, type;

  for (index = 0, length = state.implicitTypes.length; index < length; index += 1) {
    type = state.implicitTypes[index];

    if (type.resolve(str)) {
      return true;
    }
  }

  return false;
}

// [33] s-white ::= s-space | s-tab
function isWhitespace(c) {
  return c === CHAR_SPACE || c === CHAR_TAB;
}

// Returns true if the character can be printed without escaping.
// From YAML 1.2: "any allowed characters known to be non-printable
// should also be escaped. [However,] This isn’t mandatory"
// Derived from nb-char - \t - #x85 - #xA0 - #x2028 - #x2029.
function isPrintable(c) {
  return  (0x00020 <= c && c <= 0x00007E)
      || ((0x000A1 <= c && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029)
      || ((0x0E000 <= c && c <= 0x00FFFD) && c !== CHAR_BOM)
      ||  (0x10000 <= c && c <= 0x10FFFF);
}

// [34] ns-char ::= nb-char - s-white
// [27] nb-char ::= c-printable - b-char - c-byte-order-mark
// [26] b-char  ::= b-line-feed | b-carriage-return
// Including s-white (for some reason, examples doesn't match specs in this aspect)
// ns-char ::= c-printable - b-line-feed - b-carriage-return - c-byte-order-mark
function isNsCharOrWhitespace(c) {
  return isPrintable(c)
    && c !== CHAR_BOM
    // - b-char
    && c !== CHAR_CARRIAGE_RETURN
    && c !== CHAR_LINE_FEED;
}

// [127]  ns-plain-safe(c) ::= c = flow-out  ⇒ ns-plain-safe-out
//                             c = flow-in   ⇒ ns-plain-safe-in
//                             c = block-key ⇒ ns-plain-safe-out
//                             c = flow-key  ⇒ ns-plain-safe-in
// [128] ns-plain-safe-out ::= ns-char
// [129]  ns-plain-safe-in ::= ns-char - c-flow-indicator
// [130]  ns-plain-char(c) ::=  ( ns-plain-safe(c) - “:” - “#” )
//                            | ( /* An ns-char preceding */ “#” )
//                            | ( “:” /* Followed by an ns-plain-safe(c) */ )
function isPlainSafe(c, prev, inblock) {
  var cIsNsCharOrWhitespace = isNsCharOrWhitespace(c);
  var cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c);
  return (
    // ns-plain-safe
    inblock ? // c = flow-in
      cIsNsCharOrWhitespace
      : cIsNsCharOrWhitespace
        // - c-flow-indicator
        && c !== CHAR_COMMA
        && c !== CHAR_LEFT_SQUARE_BRACKET
        && c !== CHAR_RIGHT_SQUARE_BRACKET
        && c !== CHAR_LEFT_CURLY_BRACKET
        && c !== CHAR_RIGHT_CURLY_BRACKET
  )
    // ns-plain-char
    && c !== CHAR_SHARP // false on '#'
    && !(prev === CHAR_COLON && !cIsNsChar) // false on ': '
    || (isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP) // change to true on '[^ ]#'
    || (prev === CHAR_COLON && cIsNsChar); // change to true on ':[^ ]'
}

// Simplified test for values allowed as the first character in plain style.
function isPlainSafeFirst(c) {
  // Uses a subset of ns-char - c-indicator
  // where ns-char = nb-char - s-white.
  // No support of ( ( “?” | “:” | “-” ) /* Followed by an ns-plain-safe(c)) */ ) part
  return isPrintable(c) && c !== CHAR_BOM
    && !isWhitespace(c) // - s-white
    // - (c-indicator ::=
    // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”
    && c !== CHAR_MINUS
    && c !== CHAR_QUESTION
    && c !== CHAR_COLON
    && c !== CHAR_COMMA
    && c !== CHAR_LEFT_SQUARE_BRACKET
    && c !== CHAR_RIGHT_SQUARE_BRACKET
    && c !== CHAR_LEFT_CURLY_BRACKET
    && c !== CHAR_RIGHT_CURLY_BRACKET
    // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “"”
    && c !== CHAR_SHARP
    && c !== CHAR_AMPERSAND
    && c !== CHAR_ASTERISK
    && c !== CHAR_EXCLAMATION
    && c !== CHAR_VERTICAL_LINE
    && c !== CHAR_EQUALS
    && c !== CHAR_GREATER_THAN
    && c !== CHAR_SINGLE_QUOTE
    && c !== CHAR_DOUBLE_QUOTE
    // | “%” | “@” | “`”)
    && c !== CHAR_PERCENT
    && c !== CHAR_COMMERCIAL_AT
    && c !== CHAR_GRAVE_ACCENT;
}

// Simplified test for values allowed as the last character in plain style.
function isPlainSafeLast(c) {
  // just not whitespace or colon, it will be checked to be plain character later
  return !isWhitespace(c) && c !== CHAR_COLON;
}

// Same as 'string'.codePointAt(pos), but works in older browsers.
function codePointAt(string, pos) {
  var first = string.charCodeAt(pos), second;
  if (first >= 0xD800 && first <= 0xDBFF && pos + 1 < string.length) {
    second = string.charCodeAt(pos + 1);
    if (second >= 0xDC00 && second <= 0xDFFF) {
      // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
      return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
    }
  }
  return first;
}

// Determines whether block indentation indicator is required.
function needIndentIndicator(string) {
  var leadingSpaceRe = /^\n* /;
  return leadingSpaceRe.test(string);
}

var STYLE_PLAIN   = 1,
    STYLE_SINGLE  = 2,
    STYLE_LITERAL = 3,
    STYLE_FOLDED  = 4,
    STYLE_DOUBLE  = 5;

// Determines which scalar styles are possible and returns the preferred style.
// lineWidth = -1 => no limit.
// Pre-conditions: str.length > 0.
// Post-conditions:
//    STYLE_PLAIN or STYLE_SINGLE => no \n are in the string.
//    STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).
//    STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).
function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth,
  testAmbiguousType, quotingType, forceQuotes, inblock) {

  var i;
  var char = 0;
  var prevChar = null;
  var hasLineBreak = false;
  var hasFoldableLine = false; // only checked if shouldTrackWidth
  var shouldTrackWidth = lineWidth !== -1;
  var previousLineBreak = -1; // count the first line correctly
  var plain = isPlainSafeFirst(codePointAt(string, 0))
          && isPlainSafeLast(codePointAt(string, string.length - 1));

  if (singleLineOnly || forceQuotes) {
    // Case: no block styles.
    // Check for disallowed characters to rule out plain and single.
    for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
      char = codePointAt(string, i);
      if (!isPrintable(char)) {
        return STYLE_DOUBLE;
      }
      plain = plain && isPlainSafe(char, prevChar, inblock);
      prevChar = char;
    }
  } else {
    // Case: block styles permitted.
    for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
      char = codePointAt(string, i);
      if (char === CHAR_LINE_FEED) {
        hasLineBreak = true;
        // Check if any line can be folded.
        if (shouldTrackWidth) {
          hasFoldableLine = hasFoldableLine ||
            // Foldable line = too long, and not more-indented.
            (i - previousLineBreak - 1 > lineWidth &&
             string[previousLineBreak + 1] !== ' ');
          previousLineBreak = i;
        }
      } else if (!isPrintable(char)) {
        return STYLE_DOUBLE;
      }
      plain = plain && isPlainSafe(char, prevChar, inblock);
      prevChar = char;
    }
    // in case the end is missing a \n
    hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&
      (i - previousLineBreak - 1 > lineWidth &&
       string[previousLineBreak + 1] !== ' '));
  }
  // Although every style can represent \n without escaping, prefer block styles
  // for multiline, since they're more readable and they don't add empty lines.
  // Also prefer folding a super-long line.
  if (!hasLineBreak && !hasFoldableLine) {
    // Strings interpretable as another type have to be quoted;
    // e.g. the string 'true' vs. the boolean true.
    if (plain && !forceQuotes && !testAmbiguousType(string)) {
      return STYLE_PLAIN;
    }
    return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
  }
  // Edge case: block indentation indicator can only have one digit.
  if (indentPerLevel > 9 && needIndentIndicator(string)) {
    return STYLE_DOUBLE;
  }
  // At this point we know block styles are valid.
  // Prefer literal style unless we want to fold.
  if (!forceQuotes) {
    return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
  }
  return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
}

// Note: line breaking/folding is implemented for only the folded style.
// NB. We drop the last trailing newline (if any) of a returned block scalar
//  since the dumper adds its own newline. This always works:
//    • No ending newline => unaffected; already using strip "-" chomping.
//    • Ending newline    => removed then restored.
//  Importantly, this keeps the "+" chomp indicator from gaining an extra line.
function writeScalar(state, string, level, iskey, inblock) {
  state.dump = (function () {
    if (string.length === 0) {
      return state.quotingType === QUOTING_TYPE_DOUBLE ? '""' : "''";
    }
    if (!state.noCompatMode) {
      if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) {
        return state.quotingType === QUOTING_TYPE_DOUBLE ? ('"' + string + '"') : ("'" + string + "'");
      }
    }

    var indent = state.indent * Math.max(1, level); // no 0-indent scalars
    // As indentation gets deeper, let the width decrease monotonically
    // to the lower bound min(state.lineWidth, 40).
    // Note that this implies
    //  state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.
    //  state.lineWidth > 40 + state.indent: width decreases until the lower bound.
    // This behaves better than a constant minimum width which disallows narrower options,
    // or an indent threshold which causes the width to suddenly increase.
    var lineWidth = state.lineWidth === -1
      ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);

    // Without knowing if keys are implicit/explicit, assume implicit for safety.
    var singleLineOnly = iskey
      // No block styles in flow mode.
      || (state.flowLevel > -1 && level >= state.flowLevel);
    function testAmbiguity(string) {
      return testImplicitResolving(state, string);
    }

    switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth,
      testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) {

      case STYLE_PLAIN:
        return string;
      case STYLE_SINGLE:
        return "'" + string.replace(/'/g, "''") + "'";
      case STYLE_LITERAL:
        return '|' + blockHeader(string, state.indent)
          + dropEndingNewline(indentString(string, indent));
      case STYLE_FOLDED:
        return '>' + blockHeader(string, state.indent)
          + dropEndingNewline(indentString(foldString(string, lineWidth), indent));
      case STYLE_DOUBLE:
        return '"' + escapeString(string) + '"';
      default:
        throw new exception('impossible error: invalid scalar style');
    }
  }());
}

// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.
function blockHeader(string, indentPerLevel) {
  var indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : '';

  // note the special case: the string '\n' counts as a "trailing" empty line.
  var clip =          string[string.length - 1] === '\n';
  var keep = clip && (string[string.length - 2] === '\n' || string === '\n');
  var chomp = keep ? '+' : (clip ? '' : '-');

  return indentIndicator + chomp + '\n';
}

// (See the note for writeScalar.)
function dropEndingNewline(string) {
  return string[string.length - 1] === '\n' ? string.slice(0, -1) : string;
}

// Note: a long line without a suitable break point will exceed the width limit.
// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.
function foldString(string, width) {
  // In folded style, $k$ consecutive newlines output as $k+1$ newlines—
  // unless they're before or after a more-indented line, or at the very
  // beginning or end, in which case $k$ maps to $k$.
  // Therefore, parse each chunk as newline(s) followed by a content line.
  var lineRe = /(\n+)([^\n]*)/g;

  // first line (possibly an empty line)
  var result = (function () {
    var nextLF = string.indexOf('\n');
    nextLF = nextLF !== -1 ? nextLF : string.length;
    lineRe.lastIndex = nextLF;
    return foldLine(string.slice(0, nextLF), width);
  }());
  // If we haven't reached the first content line yet, don't add an extra \n.
  var prevMoreIndented = string[0] === '\n' || string[0] === ' ';
  var moreIndented;

  // rest of the lines
  var match;
  while ((match = lineRe.exec(string))) {
    var prefix = match[1], line = match[2];
    moreIndented = (line[0] === ' ');
    result += prefix
      + (!prevMoreIndented && !moreIndented && line !== ''
        ? '\n' : '')
      + foldLine(line, width);
    prevMoreIndented = moreIndented;
  }

  return result;
}

// Greedy line breaking.
// Picks the longest line under the limit each time,
// otherwise settles for the shortest line over the limit.
// NB. More-indented lines *cannot* be folded, as that would add an extra \n.
function foldLine(line, width) {
  if (line === '' || line[0] === ' ') return line;

  // Since a more-indented line adds a \n, breaks can't be followed by a space.
  var breakRe = / [^ ]/g; // note: the match index will always be <= length-2.
  var match;
  // start is an inclusive index. end, curr, and next are exclusive.
  var start = 0, end, curr = 0, next = 0;
  var result = '';

  // Invariants: 0 <= start <= length-1.
  //   0 <= curr <= next <= max(0, length-2). curr - start <= width.
  // Inside the loop:
  //   A match implies length >= 2, so curr and next are <= length-2.
  while ((match = breakRe.exec(line))) {
    next = match.index;
    // maintain invariant: curr - start <= width
    if (next - start > width) {
      end = (curr > start) ? curr : next; // derive end <= length-2
      result += '\n' + line.slice(start, end);
      // skip the space that was output as \n
      start = end + 1;                    // derive start <= length-1
    }
    curr = next;
  }

  // By the invariants, start <= length-1, so there is something left over.
  // It is either the whole string or a part starting from non-whitespace.
  result += '\n';
  // Insert a break if the remainder is too long and there is a break available.
  if (line.length - start > width && curr > start) {
    result += line.slice(start, curr) + '\n' + line.slice(curr + 1);
  } else {
    result += line.slice(start);
  }

  return result.slice(1); // drop extra \n joiner
}

// Escapes a double-quoted string.
function escapeString(string) {
  var result = '';
  var char = 0;
  var escapeSeq;

  for (var i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
    char = codePointAt(string, i);
    escapeSeq = ESCAPE_SEQUENCES[char];

    if (!escapeSeq && isPrintable(char)) {
      result += string[i];
      if (char >= 0x10000) result += string[i + 1];
    } else {
      result += escapeSeq || encodeHex(char);
    }
  }

  return result;
}

function writeFlowSequence(state, level, object) {
  var _result = '',
      _tag    = state.tag,
      index,
      length,
      value;

  for (index = 0, length = object.length; index < length; index += 1) {
    value = object[index];

    if (state.replacer) {
      value = state.replacer.call(object, String(index), value);
    }

    // Write only valid elements, put null instead of invalid elements.
    if (writeNode(state, level, value, false, false) ||
        (typeof value === 'undefined' &&
         writeNode(state, level, null, false, false))) {

      if (_result !== '') _result += ',' + (!state.condenseFlow ? ' ' : '');
      _result += state.dump;
    }
  }

  state.tag = _tag;
  state.dump = '[' + _result + ']';
}

function writeBlockSequence(state, level, object, compact) {
  var _result = '',
      _tag    = state.tag,
      index,
      length,
      value;

  for (index = 0, length = object.length; index < length; index += 1) {
    value = object[index];

    if (state.replacer) {
      value = state.replacer.call(object, String(index), value);
    }

    // Write only valid elements, put null instead of invalid elements.
    if (writeNode(state, level + 1, value, true, true, false, true) ||
        (typeof value === 'undefined' &&
         writeNode(state, level + 1, null, true, true, false, true))) {

      if (!compact || _result !== '') {
        _result += generateNextLine(state, level);
      }

      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
        _result += '-';
      } else {
        _result += '- ';
      }

      _result += state.dump;
    }
  }

  state.tag = _tag;
  state.dump = _result || '[]'; // Empty sequence if no valid values.
}

function writeFlowMapping(state, level, object) {
  var _result       = '',
      _tag          = state.tag,
      objectKeyList = Object.keys(object),
      index,
      length,
      objectKey,
      objectValue,
      pairBuffer;

  for (index = 0, length = objectKeyList.length; index < length; index += 1) {

    pairBuffer = '';
    if (_result !== '') pairBuffer += ', ';

    if (state.condenseFlow) pairBuffer += '"';

    objectKey = objectKeyList[index];
    objectValue = object[objectKey];

    if (state.replacer) {
      objectValue = state.replacer.call(object, objectKey, objectValue);
    }

    if (!writeNode(state, level, objectKey, false, false)) {
      continue; // Skip this pair because of invalid key;
    }

    if (state.dump.length > 1024) pairBuffer += '? ';

    pairBuffer += state.dump + (state.condenseFlow ? '"' : '') + ':' + (state.condenseFlow ? '' : ' ');

    if (!writeNode(state, level, objectValue, false, false)) {
      continue; // Skip this pair because of invalid value.
    }

    pairBuffer += state.dump;

    // Both key and value are valid.
    _result += pairBuffer;
  }

  state.tag = _tag;
  state.dump = '{' + _result + '}';
}

function writeBlockMapping(state, level, object, compact) {
  var _result       = '',
      _tag          = state.tag,
      objectKeyList = Object.keys(object),
      index,
      length,
      objectKey,
      objectValue,
      explicitPair,
      pairBuffer;

  // Allow sorting keys so that the output file is deterministic
  if (state.sortKeys === true) {
    // Default sorting
    objectKeyList.sort();
  } else if (typeof state.sortKeys === 'function') {
    // Custom sort function
    objectKeyList.sort(state.sortKeys);
  } else if (state.sortKeys) {
    // Something is wrong
    throw new exception('sortKeys must be a boolean or a function');
  }

  for (index = 0, length = objectKeyList.length; index < length; index += 1) {
    pairBuffer = '';

    if (!compact || _result !== '') {
      pairBuffer += generateNextLine(state, level);
    }

    objectKey = objectKeyList[index];
    objectValue = object[objectKey];

    if (state.replacer) {
      objectValue = state.replacer.call(object, objectKey, objectValue);
    }

    if (!writeNode(state, level + 1, objectKey, true, true, true)) {
      continue; // Skip this pair because of invalid key.
    }

    explicitPair = (state.tag !== null && state.tag !== '?') ||
                   (state.dump && state.dump.length > 1024);

    if (explicitPair) {
      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
        pairBuffer += '?';
      } else {
        pairBuffer += '? ';
      }
    }

    pairBuffer += state.dump;

    if (explicitPair) {
      pairBuffer += generateNextLine(state, level);
    }

    if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
      continue; // Skip this pair because of invalid value.
    }

    if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
      pairBuffer += ':';
    } else {
      pairBuffer += ': ';
    }

    pairBuffer += state.dump;

    // Both key and value are valid.
    _result += pairBuffer;
  }

  state.tag = _tag;
  state.dump = _result || '{}'; // Empty mapping if no valid pairs.
}

function detectType(state, object, explicit) {
  var _result, typeList, index, length, type, style;

  typeList = explicit ? state.explicitTypes : state.implicitTypes;

  for (index = 0, length = typeList.length; index < length; index += 1) {
    type = typeList[index];

    if ((type.instanceOf  || type.predicate) &&
        (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&
        (!type.predicate  || type.predicate(object))) {

      if (explicit) {
        if (type.multi && type.representName) {
          state.tag = type.representName(object);
        } else {
          state.tag = type.tag;
        }
      } else {
        state.tag = '?';
      }

      if (type.represent) {
        style = state.styleMap[type.tag] || type.defaultStyle;

        if (_toString.call(type.represent) === '[object Function]') {
          _result = type.represent(object, style);
        } else if (_hasOwnProperty.call(type.represent, style)) {
          _result = type.represent[style](object, style);
        } else {
          throw new exception('!<' + type.tag + '> tag resolver accepts not "' + style + '" style');
        }

        state.dump = _result;
      }

      return true;
    }
  }

  return false;
}

// Serializes `object` and writes it to global `result`.
// Returns true on success, or false on invalid object.
//
function writeNode(state, level, object, block, compact, iskey, isblockseq) {
  state.tag = null;
  state.dump = object;

  if (!detectType(state, object, false)) {
    detectType(state, object, true);
  }

  var type = _toString.call(state.dump);
  var inblock = block;
  var tagStr;

  if (block) {
    block = (state.flowLevel < 0 || state.flowLevel > level);
  }

  var objectOrArray = type === '[object Object]' || type === '[object Array]',
      duplicateIndex,
      duplicate;

  if (objectOrArray) {
    duplicateIndex = state.duplicates.indexOf(object);
    duplicate = duplicateIndex !== -1;
  }

  if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {
    compact = false;
  }

  if (duplicate && state.usedDuplicates[duplicateIndex]) {
    state.dump = '*ref_' + duplicateIndex;
  } else {
    if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
      state.usedDuplicates[duplicateIndex] = true;
    }
    if (type === '[object Object]') {
      if (block && (Object.keys(state.dump).length !== 0)) {
        writeBlockMapping(state, level, state.dump, compact);
        if (duplicate) {
          state.dump = '&ref_' + duplicateIndex + state.dump;
        }
      } else {
        writeFlowMapping(state, level, state.dump);
        if (duplicate) {
          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
        }
      }
    } else if (type === '[object Array]') {
      if (block && (state.dump.length !== 0)) {
        if (state.noArrayIndent && !isblockseq && level > 0) {
          writeBlockSequence(state, level - 1, state.dump, compact);
        } else {
          writeBlockSequence(state, level, state.dump, compact);
        }
        if (duplicate) {
          state.dump = '&ref_' + duplicateIndex + state.dump;
        }
      } else {
        writeFlowSequence(state, level, state.dump);
        if (duplicate) {
          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
        }
      }
    } else if (type === '[object String]') {
      if (state.tag !== '?') {
        writeScalar(state, state.dump, level, iskey, inblock);
      }
    } else if (type === '[object Undefined]') {
      return false;
    } else {
      if (state.skipInvalid) return false;
      throw new exception('unacceptable kind of an object to dump ' + type);
    }

    if (state.tag !== null && state.tag !== '?') {
      // Need to encode all characters except those allowed by the spec:
      //
      // [35] ns-dec-digit    ::=  [#x30-#x39] /* 0-9 */
      // [36] ns-hex-digit    ::=  ns-dec-digit
      //                         | [#x41-#x46] /* A-F */ | [#x61-#x66] /* a-f */
      // [37] ns-ascii-letter ::=  [#x41-#x5A] /* A-Z */ | [#x61-#x7A] /* a-z */
      // [38] ns-word-char    ::=  ns-dec-digit | ns-ascii-letter | “-”
      // [39] ns-uri-char     ::=  “%” ns-hex-digit ns-hex-digit | ns-word-char | “#”
      //                         | “;” | “/” | “?” | “:” | “@” | “&” | “=” | “+” | “$” | “,”
      //                         | “_” | “.” | “!” | “~” | “*” | “'” | “(” | “)” | “[” | “]”
      //
      // Also need to encode '!' because it has special meaning (end of tag prefix).
      //
      tagStr = encodeURI(
        state.tag[0] === '!' ? state.tag.slice(1) : state.tag
      ).replace(/!/g, '%21');

      if (state.tag[0] === '!') {
        tagStr = '!' + tagStr;
      } else if (tagStr.slice(0, 18) === 'tag:yaml.org,2002:') {
        tagStr = '!!' + tagStr.slice(18);
      } else {
        tagStr = '!<' + tagStr + '>';
      }

      state.dump = tagStr + ' ' + state.dump;
    }
  }

  return true;
}

function getDuplicateReferences(object, state) {
  var objects = [],
      duplicatesIndexes = [],
      index,
      length;

  inspectNode(object, objects, duplicatesIndexes);

  for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) {
    state.duplicates.push(objects[duplicatesIndexes[index]]);
  }
  state.usedDuplicates = new Array(length);
}

function inspectNode(object, objects, duplicatesIndexes) {
  var objectKeyList,
      index,
      length;

  if (object !== null && typeof object === 'object') {
    index = objects.indexOf(object);
    if (index !== -1) {
      if (duplicatesIndexes.indexOf(index) === -1) {
        duplicatesIndexes.push(index);
      }
    } else {
      objects.push(object);

      if (Array.isArray(object)) {
        for (index = 0, length = object.length; index < length; index += 1) {
          inspectNode(object[index], objects, duplicatesIndexes);
        }
      } else {
        objectKeyList = Object.keys(object);

        for (index = 0, length = objectKeyList.length; index < length; index += 1) {
          inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes);
        }
      }
    }
  }
}

function dump$1(input, options) {
  options = options || {};

  var state = new State(options);

  if (!state.noRefs) getDuplicateReferences(input, state);

  var value = input;

  if (state.replacer) {
    value = state.replacer.call({ '': value }, '', value);
  }

  if (writeNode(state, 0, value, true, true)) return state.dump + '\n';

  return '';
}

var dump_1 = dump$1;

var dumper = {
	dump: dump_1
};

function renamed(from, to) {
  return function () {
    throw new Error('Function yaml.' + from + ' is removed in js-yaml 4. ' +
      'Use yaml.' + to + ' instead, which is now safe by default.');
  };
}


var Type                = type;
var Schema              = schema;
var FAILSAFE_SCHEMA     = failsafe;
var JSON_SCHEMA         = json;
var CORE_SCHEMA         = core;
var DEFAULT_SCHEMA      = _default;
var load                = loader.load;
var loadAll             = loader.loadAll;
var dump                = dumper.dump;
var YAMLException       = exception;

// Re-export all types in case user wants to create custom schema
var types = {
  binary:    binary,
  float:     float,
  map:       map,
  null:      _null,
  pairs:     pairs,
  set:       set,
  timestamp: timestamp,
  bool:      bool,
  int:       int,
  merge:     merge,
  omap:      omap,
  seq:       seq,
  str:       str
};

// Removed functions from JS-YAML 3.0.x
var safeLoad            = renamed('safeLoad', 'load');
var safeLoadAll         = renamed('safeLoadAll', 'loadAll');
var safeDump            = renamed('safeDump', 'dump');

var jsYaml = {
	Type: Type,
	Schema: Schema,
	FAILSAFE_SCHEMA: FAILSAFE_SCHEMA,
	JSON_SCHEMA: JSON_SCHEMA,
	CORE_SCHEMA: CORE_SCHEMA,
	DEFAULT_SCHEMA: DEFAULT_SCHEMA,
	load: load,
	loadAll: loadAll,
	dump: dump,
	YAMLException: YAMLException,
	types: types,
	safeLoad: safeLoad,
	safeLoadAll: safeLoadAll,
	safeDump: safeDump
};

export default jsYaml;
export { CORE_SCHEMA, DEFAULT_SCHEMA, FAILSAFE_SCHEMA, JSON_SCHEMA, Schema, Type, YAMLException, dump, load, loadAll, safeDump, safeLoad, safeLoadAll, types };
'use strict';


var loader = require('./lib/loader');
var dumper = require('./lib/dumper');


function renamed(from, to) {
  return function () {
    throw new Error('Function yaml.' + from + ' is removed in js-yaml 4. ' +
      'Use yaml.' + to + ' instead, which is now safe by default.');
  };
}


module.exports.Type                = require('./lib/type');
module.exports.Schema              = require('./lib/schema');
module.exports.FAILSAFE_SCHEMA     = require('./lib/schema/failsafe');
module.exports.JSON_SCHEMA         = require('./lib/schema/json');
module.exports.CORE_SCHEMA         = require('./lib/schema/core');
module.exports.DEFAULT_SCHEMA      = require('./lib/schema/default');
module.exports.load                = loader.load;
module.exports.loadAll             = loader.loadAll;
module.exports.dump                = dumper.dump;
module.exports.YAMLException       = require('./lib/exception');

// Re-export all types in case user wants to create custom schema
module.exports.types = {
  binary:    require('./lib/type/binary'),
  float:     require('./lib/type/float'),
  map:       require('./lib/type/map'),
  null:      require('./lib/type/null'),
  pairs:     require('./lib/type/pairs'),
  set:       require('./lib/type/set'),
  timestamp: require('./lib/type/timestamp'),
  bool:      require('./lib/type/bool'),
  int:       require('./lib/type/int'),
  merge:     require('./lib/type/merge'),
  omap:      require('./lib/type/omap'),
  seq:       require('./lib/type/seq'),
  str:       require('./lib/type/str')
};

// Removed functions from JS-YAML 3.0.x
module.exports.safeLoad            = renamed('safeLoad', 'load');
module.exports.safeLoadAll         = renamed('safeLoadAll', 'loadAll');
module.exports.safeDump            = renamed('safeDump', 'dump');
'use strict';


function isNothing(subject) {
  return (typeof subject === 'undefined') || (subject === null);
}


function isObject(subject) {
  return (typeof subject === 'object') && (subject !== null);
}


function toArray(sequence) {
  if (Array.isArray(sequence)) return sequence;
  else if (isNothing(sequence)) return [];

  return [ sequence ];
}


function extend(target, source) {
  var index, length, key, sourceKeys;

  if (source) {
    sourceKeys = Object.keys(source);

    for (index = 0, length = sourceKeys.length; index < length; index += 1) {
      key = sourceKeys[index];
      target[key] = source[key];
    }
  }

  return target;
}


function repeat(string, count) {
  var result = '', cycle;

  for (cycle = 0; cycle < count; cycle += 1) {
    result += string;
  }

  return result;
}


function isNegativeZero(number) {
  return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number);
}


module.exports.isNothing      = isNothing;
module.exports.isObject       = isObject;
module.exports.toArray        = toArray;
module.exports.repeat         = repeat;
module.exports.isNegativeZero = isNegativeZero;
module.exports.extend         = extend;
'use strict';

/*eslint-disable no-use-before-define*/

var common              = require('./common');
var YAMLException       = require('./exception');
var DEFAULT_SCHEMA      = require('./schema/default');

var _toString       = Object.prototype.toString;
var _hasOwnProperty = Object.prototype.hasOwnProperty;

var CHAR_BOM                  = 0xFEFF;
var CHAR_TAB                  = 0x09; /* Tab */
var CHAR_LINE_FEED            = 0x0A; /* LF */
var CHAR_CARRIAGE_RETURN      = 0x0D; /* CR */
var CHAR_SPACE                = 0x20; /* Space */
var CHAR_EXCLAMATION          = 0x21; /* ! */
var CHAR_DOUBLE_QUOTE         = 0x22; /* " */
var CHAR_SHARP                = 0x23; /* # */
var CHAR_PERCENT              = 0x25; /* % */
var CHAR_AMPERSAND            = 0x26; /* & */
var CHAR_SINGLE_QUOTE         = 0x27; /* ' */
var CHAR_ASTERISK             = 0x2A; /* * */
var CHAR_COMMA                = 0x2C; /* , */
var CHAR_MINUS                = 0x2D; /* - */
var CHAR_COLON                = 0x3A; /* : */
var CHAR_EQUALS               = 0x3D; /* = */
var CHAR_GREATER_THAN         = 0x3E; /* > */
var CHAR_QUESTION             = 0x3F; /* ? */
var CHAR_COMMERCIAL_AT        = 0x40; /* @ */
var CHAR_LEFT_SQUARE_BRACKET  = 0x5B; /* [ */
var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */
var CHAR_GRAVE_ACCENT         = 0x60; /* ` */
var CHAR_LEFT_CURLY_BRACKET   = 0x7B; /* { */
var CHAR_VERTICAL_LINE        = 0x7C; /* | */
var CHAR_RIGHT_CURLY_BRACKET  = 0x7D; /* } */

var ESCAPE_SEQUENCES = {};

ESCAPE_SEQUENCES[0x00]   = '\\0';
ESCAPE_SEQUENCES[0x07]   = '\\a';
ESCAPE_SEQUENCES[0x08]   = '\\b';
ESCAPE_SEQUENCES[0x09]   = '\\t';
ESCAPE_SEQUENCES[0x0A]   = '\\n';
ESCAPE_SEQUENCES[0x0B]   = '\\v';
ESCAPE_SEQUENCES[0x0C]   = '\\f';
ESCAPE_SEQUENCES[0x0D]   = '\\r';
ESCAPE_SEQUENCES[0x1B]   = '\\e';
ESCAPE_SEQUENCES[0x22]   = '\\"';
ESCAPE_SEQUENCES[0x5C]   = '\\\\';
ESCAPE_SEQUENCES[0x85]   = '\\N';
ESCAPE_SEQUENCES[0xA0]   = '\\_';
ESCAPE_SEQUENCES[0x2028] = '\\L';
ESCAPE_SEQUENCES[0x2029] = '\\P';

var DEPRECATED_BOOLEANS_SYNTAX = [
  'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',
  'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'
];

var DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;

function compileStyleMap(schema, map) {
  var result, keys, index, length, tag, style, type;

  if (map === null) return {};

  result = {};
  keys = Object.keys(map);

  for (index = 0, length = keys.length; index < length; index += 1) {
    tag = keys[index];
    style = String(map[tag]);

    if (tag.slice(0, 2) === '!!') {
      tag = 'tag:yaml.org,2002:' + tag.slice(2);
    }
    type = schema.compiledTypeMap['fallback'][tag];

    if (type && _hasOwnProperty.call(type.styleAliases, style)) {
      style = type.styleAliases[style];
    }

    result[tag] = style;
  }

  return result;
}

function encodeHex(character) {
  var string, handle, length;

  string = character.toString(16).toUpperCase();

  if (character <= 0xFF) {
    handle = 'x';
    length = 2;
  } else if (character <= 0xFFFF) {
    handle = 'u';
    length = 4;
  } else if (character <= 0xFFFFFFFF) {
    handle = 'U';
    length = 8;
  } else {
    throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF');
  }

  return '\\' + handle + common.repeat('0', length - string.length) + string;
}


var QUOTING_TYPE_SINGLE = 1,
    QUOTING_TYPE_DOUBLE = 2;

function State(options) {
  this.schema        = options['schema'] || DEFAULT_SCHEMA;
  this.indent        = Math.max(1, (options['indent'] || 2));
  this.noArrayIndent = options['noArrayIndent'] || false;
  this.skipInvalid   = options['skipInvalid'] || false;
  this.flowLevel     = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']);
  this.styleMap      = compileStyleMap(this.schema, options['styles'] || null);
  this.sortKeys      = options['sortKeys'] || false;
  this.lineWidth     = options['lineWidth'] || 80;
  this.noRefs        = options['noRefs'] || false;
  this.noCompatMode  = options['noCompatMode'] || false;
  this.condenseFlow  = options['condenseFlow'] || false;
  this.quotingType   = options['quotingType'] === '"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE;
  this.forceQuotes   = options['forceQuotes'] || false;
  this.replacer      = typeof options['replacer'] === 'function' ? options['replacer'] : null;

  this.implicitTypes = this.schema.compiledImplicit;
  this.explicitTypes = this.schema.compiledExplicit;

  this.tag = null;
  this.result = '';

  this.duplicates = [];
  this.usedDuplicates = null;
}

// Indents every line in a string. Empty lines (\n only) are not indented.
function indentString(string, spaces) {
  var ind = common.repeat(' ', spaces),
      position = 0,
      next = -1,
      result = '',
      line,
      length = string.length;

  while (position < length) {
    next = string.indexOf('\n', position);
    if (next === -1) {
      line = string.slice(position);
      position = length;
    } else {
      line = string.slice(position, next + 1);
      position = next + 1;
    }

    if (line.length && line !== '\n') result += ind;

    result += line;
  }

  return result;
}

function generateNextLine(state, level) {
  return '\n' + common.repeat(' ', state.indent * level);
}

function testImplicitResolving(state, str) {
  var index, length, type;

  for (index = 0, length = state.implicitTypes.length; index < length; index += 1) {
    type = state.implicitTypes[index];

    if (type.resolve(str)) {
      return true;
    }
  }

  return false;
}

// [33] s-white ::= s-space | s-tab
function isWhitespace(c) {
  return c === CHAR_SPACE || c === CHAR_TAB;
}

// Returns true if the character can be printed without escaping.
// From YAML 1.2: "any allowed characters known to be non-printable
// should also be escaped. [However,] This isn’t mandatory"
// Derived from nb-char - \t - #x85 - #xA0 - #x2028 - #x2029.
function isPrintable(c) {
  return  (0x00020 <= c && c <= 0x00007E)
      || ((0x000A1 <= c && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029)
      || ((0x0E000 <= c && c <= 0x00FFFD) && c !== CHAR_BOM)
      ||  (0x10000 <= c && c <= 0x10FFFF);
}

// [34] ns-char ::= nb-char - s-white
// [27] nb-char ::= c-printable - b-char - c-byte-order-mark
// [26] b-char  ::= b-line-feed | b-carriage-return
// Including s-white (for some reason, examples doesn't match specs in this aspect)
// ns-char ::= c-printable - b-line-feed - b-carriage-return - c-byte-order-mark
function isNsCharOrWhitespace(c) {
  return isPrintable(c)
    && c !== CHAR_BOM
    // - b-char
    && c !== CHAR_CARRIAGE_RETURN
    && c !== CHAR_LINE_FEED;
}

// [127]  ns-plain-safe(c) ::= c = flow-out  ⇒ ns-plain-safe-out
//                             c = flow-in   ⇒ ns-plain-safe-in
//                             c = block-key ⇒ ns-plain-safe-out
//                             c = flow-key  ⇒ ns-plain-safe-in
// [128] ns-plain-safe-out ::= ns-char
// [129]  ns-plain-safe-in ::= ns-char - c-flow-indicator
// [130]  ns-plain-char(c) ::=  ( ns-plain-safe(c) - “:” - “#” )
//                            | ( /* An ns-char preceding */ “#” )
//                            | ( “:” /* Followed by an ns-plain-safe(c) */ )
function isPlainSafe(c, prev, inblock) {
  var cIsNsCharOrWhitespace = isNsCharOrWhitespace(c);
  var cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c);
  return (
    // ns-plain-safe
    inblock ? // c = flow-in
      cIsNsCharOrWhitespace
      : cIsNsCharOrWhitespace
        // - c-flow-indicator
        && c !== CHAR_COMMA
        && c !== CHAR_LEFT_SQUARE_BRACKET
        && c !== CHAR_RIGHT_SQUARE_BRACKET
        && c !== CHAR_LEFT_CURLY_BRACKET
        && c !== CHAR_RIGHT_CURLY_BRACKET
  )
    // ns-plain-char
    && c !== CHAR_SHARP // false on '#'
    && !(prev === CHAR_COLON && !cIsNsChar) // false on ': '
    || (isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP) // change to true on '[^ ]#'
    || (prev === CHAR_COLON && cIsNsChar); // change to true on ':[^ ]'
}

// Simplified test for values allowed as the first character in plain style.
function isPlainSafeFirst(c) {
  // Uses a subset of ns-char - c-indicator
  // where ns-char = nb-char - s-white.
  // No support of ( ( “?” | “:” | “-” ) /* Followed by an ns-plain-safe(c)) */ ) part
  return isPrintable(c) && c !== CHAR_BOM
    && !isWhitespace(c) // - s-white
    // - (c-indicator ::=
    // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”
    && c !== CHAR_MINUS
    && c !== CHAR_QUESTION
    && c !== CHAR_COLON
    && c !== CHAR_COMMA
    && c !== CHAR_LEFT_SQUARE_BRACKET
    && c !== CHAR_RIGHT_SQUARE_BRACKET
    && c !== CHAR_LEFT_CURLY_BRACKET
    && c !== CHAR_RIGHT_CURLY_BRACKET
    // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “"”
    && c !== CHAR_SHARP
    && c !== CHAR_AMPERSAND
    && c !== CHAR_ASTERISK
    && c !== CHAR_EXCLAMATION
    && c !== CHAR_VERTICAL_LINE
    && c !== CHAR_EQUALS
    && c !== CHAR_GREATER_THAN
    && c !== CHAR_SINGLE_QUOTE
    && c !== CHAR_DOUBLE_QUOTE
    // | “%” | “@” | “`”)
    && c !== CHAR_PERCENT
    && c !== CHAR_COMMERCIAL_AT
    && c !== CHAR_GRAVE_ACCENT;
}

// Simplified test for values allowed as the last character in plain style.
function isPlainSafeLast(c) {
  // just not whitespace or colon, it will be checked to be plain character later
  return !isWhitespace(c) && c !== CHAR_COLON;
}

// Same as 'string'.codePointAt(pos), but works in older browsers.
function codePointAt(string, pos) {
  var first = string.charCodeAt(pos), second;
  if (first >= 0xD800 && first <= 0xDBFF && pos + 1 < string.length) {
    second = string.charCodeAt(pos + 1);
    if (second >= 0xDC00 && second <= 0xDFFF) {
      // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
      return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
    }
  }
  return first;
}

// Determines whether block indentation indicator is required.
function needIndentIndicator(string) {
  var leadingSpaceRe = /^\n* /;
  return leadingSpaceRe.test(string);
}

var STYLE_PLAIN   = 1,
    STYLE_SINGLE  = 2,
    STYLE_LITERAL = 3,
    STYLE_FOLDED  = 4,
    STYLE_DOUBLE  = 5;

// Determines which scalar styles are possible and returns the preferred style.
// lineWidth = -1 => no limit.
// Pre-conditions: str.length > 0.
// Post-conditions:
//    STYLE_PLAIN or STYLE_SINGLE => no \n are in the string.
//    STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).
//    STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).
function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth,
  testAmbiguousType, quotingType, forceQuotes, inblock) {

  var i;
  var char = 0;
  var prevChar = null;
  var hasLineBreak = false;
  var hasFoldableLine = false; // only checked if shouldTrackWidth
  var shouldTrackWidth = lineWidth !== -1;
  var previousLineBreak = -1; // count the first line correctly
  var plain = isPlainSafeFirst(codePointAt(string, 0))
          && isPlainSafeLast(codePointAt(string, string.length - 1));

  if (singleLineOnly || forceQuotes) {
    // Case: no block styles.
    // Check for disallowed characters to rule out plain and single.
    for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
      char = codePointAt(string, i);
      if (!isPrintable(char)) {
        return STYLE_DOUBLE;
      }
      plain = plain && isPlainSafe(char, prevChar, inblock);
      prevChar = char;
    }
  } else {
    // Case: block styles permitted.
    for (i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
      char = codePointAt(string, i);
      if (char === CHAR_LINE_FEED) {
        hasLineBreak = true;
        // Check if any line can be folded.
        if (shouldTrackWidth) {
          hasFoldableLine = hasFoldableLine ||
            // Foldable line = too long, and not more-indented.
            (i - previousLineBreak - 1 > lineWidth &&
             string[previousLineBreak + 1] !== ' ');
          previousLineBreak = i;
        }
      } else if (!isPrintable(char)) {
        return STYLE_DOUBLE;
      }
      plain = plain && isPlainSafe(char, prevChar, inblock);
      prevChar = char;
    }
    // in case the end is missing a \n
    hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&
      (i - previousLineBreak - 1 > lineWidth &&
       string[previousLineBreak + 1] !== ' '));
  }
  // Although every style can represent \n without escaping, prefer block styles
  // for multiline, since they're more readable and they don't add empty lines.
  // Also prefer folding a super-long line.
  if (!hasLineBreak && !hasFoldableLine) {
    // Strings interpretable as another type have to be quoted;
    // e.g. the string 'true' vs. the boolean true.
    if (plain && !forceQuotes && !testAmbiguousType(string)) {
      return STYLE_PLAIN;
    }
    return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
  }
  // Edge case: block indentation indicator can only have one digit.
  if (indentPerLevel > 9 && needIndentIndicator(string)) {
    return STYLE_DOUBLE;
  }
  // At this point we know block styles are valid.
  // Prefer literal style unless we want to fold.
  if (!forceQuotes) {
    return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
  }
  return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
}

// Note: line breaking/folding is implemented for only the folded style.
// NB. We drop the last trailing newline (if any) of a returned block scalar
//  since the dumper adds its own newline. This always works:
//    • No ending newline => unaffected; already using strip "-" chomping.
//    • Ending newline    => removed then restored.
//  Importantly, this keeps the "+" chomp indicator from gaining an extra line.
function writeScalar(state, string, level, iskey, inblock) {
  state.dump = (function () {
    if (string.length === 0) {
      return state.quotingType === QUOTING_TYPE_DOUBLE ? '""' : "''";
    }
    if (!state.noCompatMode) {
      if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) {
        return state.quotingType === QUOTING_TYPE_DOUBLE ? ('"' + string + '"') : ("'" + string + "'");
      }
    }

    var indent = state.indent * Math.max(1, level); // no 0-indent scalars
    // As indentation gets deeper, let the width decrease monotonically
    // to the lower bound min(state.lineWidth, 40).
    // Note that this implies
    //  state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.
    //  state.lineWidth > 40 + state.indent: width decreases until the lower bound.
    // This behaves better than a constant minimum width which disallows narrower options,
    // or an indent threshold which causes the width to suddenly increase.
    var lineWidth = state.lineWidth === -1
      ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);

    // Without knowing if keys are implicit/explicit, assume implicit for safety.
    var singleLineOnly = iskey
      // No block styles in flow mode.
      || (state.flowLevel > -1 && level >= state.flowLevel);
    function testAmbiguity(string) {
      return testImplicitResolving(state, string);
    }

    switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth,
      testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) {

      case STYLE_PLAIN:
        return string;
      case STYLE_SINGLE:
        return "'" + string.replace(/'/g, "''") + "'";
      case STYLE_LITERAL:
        return '|' + blockHeader(string, state.indent)
          + dropEndingNewline(indentString(string, indent));
      case STYLE_FOLDED:
        return '>' + blockHeader(string, state.indent)
          + dropEndingNewline(indentString(foldString(string, lineWidth), indent));
      case STYLE_DOUBLE:
        return '"' + escapeString(string, lineWidth) + '"';
      default:
        throw new YAMLException('impossible error: invalid scalar style');
    }
  }());
}

// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.
function blockHeader(string, indentPerLevel) {
  var indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : '';

  // note the special case: the string '\n' counts as a "trailing" empty line.
  var clip =          string[string.length - 1] === '\n';
  var keep = clip && (string[string.length - 2] === '\n' || string === '\n');
  var chomp = keep ? '+' : (clip ? '' : '-');

  return indentIndicator + chomp + '\n';
}

// (See the note for writeScalar.)
function dropEndingNewline(string) {
  return string[string.length - 1] === '\n' ? string.slice(0, -1) : string;
}

// Note: a long line without a suitable break point will exceed the width limit.
// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.
function foldString(string, width) {
  // In folded style, $k$ consecutive newlines output as $k+1$ newlines—
  // unless they're before or after a more-indented line, or at the very
  // beginning or end, in which case $k$ maps to $k$.
  // Therefore, parse each chunk as newline(s) followed by a content line.
  var lineRe = /(\n+)([^\n]*)/g;

  // first line (possibly an empty line)
  var result = (function () {
    var nextLF = string.indexOf('\n');
    nextLF = nextLF !== -1 ? nextLF : string.length;
    lineRe.lastIndex = nextLF;
    return foldLine(string.slice(0, nextLF), width);
  }());
  // If we haven't reached the first content line yet, don't add an extra \n.
  var prevMoreIndented = string[0] === '\n' || string[0] === ' ';
  var moreIndented;

  // rest of the lines
  var match;
  while ((match = lineRe.exec(string))) {
    var prefix = match[1], line = match[2];
    moreIndented = (line[0] === ' ');
    result += prefix
      + (!prevMoreIndented && !moreIndented && line !== ''
        ? '\n' : '')
      + foldLine(line, width);
    prevMoreIndented = moreIndented;
  }

  return result;
}

// Greedy line breaking.
// Picks the longest line under the limit each time,
// otherwise settles for the shortest line over the limit.
// NB. More-indented lines *cannot* be folded, as that would add an extra \n.
function foldLine(line, width) {
  if (line === '' || line[0] === ' ') return line;

  // Since a more-indented line adds a \n, breaks can't be followed by a space.
  var breakRe = / [^ ]/g; // note: the match index will always be <= length-2.
  var match;
  // start is an inclusive index. end, curr, and next are exclusive.
  var start = 0, end, curr = 0, next = 0;
  var result = '';

  // Invariants: 0 <= start <= length-1.
  //   0 <= curr <= next <= max(0, length-2). curr - start <= width.
  // Inside the loop:
  //   A match implies length >= 2, so curr and next are <= length-2.
  while ((match = breakRe.exec(line))) {
    next = match.index;
    // maintain invariant: curr - start <= width
    if (next - start > width) {
      end = (curr > start) ? curr : next; // derive end <= length-2
      result += '\n' + line.slice(start, end);
      // skip the space that was output as \n
      start = end + 1;                    // derive start <= length-1
    }
    curr = next;
  }

  // By the invariants, start <= length-1, so there is something left over.
  // It is either the whole string or a part starting from non-whitespace.
  result += '\n';
  // Insert a break if the remainder is too long and there is a break available.
  if (line.length - start > width && curr > start) {
    result += line.slice(start, curr) + '\n' + line.slice(curr + 1);
  } else {
    result += line.slice(start);
  }

  return result.slice(1); // drop extra \n joiner
}

// Escapes a double-quoted string.
function escapeString(string) {
  var result = '';
  var char = 0;
  var escapeSeq;

  for (var i = 0; i < string.length; char >= 0x10000 ? i += 2 : i++) {
    char = codePointAt(string, i);
    escapeSeq = ESCAPE_SEQUENCES[char];

    if (!escapeSeq && isPrintable(char)) {
      result += string[i];
      if (char >= 0x10000) result += string[i + 1];
    } else {
      result += escapeSeq || encodeHex(char);
    }
  }

  return result;
}

function writeFlowSequence(state, level, object) {
  var _result = '',
      _tag    = state.tag,
      index,
      length,
      value;

  for (index = 0, length = object.length; index < length; index += 1) {
    value = object[index];

    if (state.replacer) {
      value = state.replacer.call(object, String(index), value);
    }

    // Write only valid elements, put null instead of invalid elements.
    if (writeNode(state, level, value, false, false) ||
        (typeof value === 'undefined' &&
         writeNode(state, level, null, false, false))) {

      if (_result !== '') _result += ',' + (!state.condenseFlow ? ' ' : '');
      _result += state.dump;
    }
  }

  state.tag = _tag;
  state.dump = '[' + _result + ']';
}

function writeBlockSequence(state, level, object, compact) {
  var _result = '',
      _tag    = state.tag,
      index,
      length,
      value;

  for (index = 0, length = object.length; index < length; index += 1) {
    value = object[index];

    if (state.replacer) {
      value = state.replacer.call(object, String(index), value);
    }

    // Write only valid elements, put null instead of invalid elements.
    if (writeNode(state, level + 1, value, true, true, false, true) ||
        (typeof value === 'undefined' &&
         writeNode(state, level + 1, null, true, true, false, true))) {

      if (!compact || _result !== '') {
        _result += generateNextLine(state, level);
      }

      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
        _result += '-';
      } else {
        _result += '- ';
      }

      _result += state.dump;
    }
  }

  state.tag = _tag;
  state.dump = _result || '[]'; // Empty sequence if no valid values.
}

function writeFlowMapping(state, level, object) {
  var _result       = '',
      _tag          = state.tag,
      objectKeyList = Object.keys(object),
      index,
      length,
      objectKey,
      objectValue,
      pairBuffer;

  for (index = 0, length = objectKeyList.length; index < length; index += 1) {

    pairBuffer = '';
    if (_result !== '') pairBuffer += ', ';

    if (state.condenseFlow) pairBuffer += '"';

    objectKey = objectKeyList[index];
    objectValue = object[objectKey];

    if (state.replacer) {
      objectValue = state.replacer.call(object, objectKey, objectValue);
    }

    if (!writeNode(state, level, objectKey, false, false)) {
      continue; // Skip this pair because of invalid key;
    }

    if (state.dump.length > 1024) pairBuffer += '? ';

    pairBuffer += state.dump + (state.condenseFlow ? '"' : '') + ':' + (state.condenseFlow ? '' : ' ');

    if (!writeNode(state, level, objectValue, false, false)) {
      continue; // Skip this pair because of invalid value.
    }

    pairBuffer += state.dump;

    // Both key and value are valid.
    _result += pairBuffer;
  }

  state.tag = _tag;
  state.dump = '{' + _result + '}';
}

function writeBlockMapping(state, level, object, compact) {
  var _result       = '',
      _tag          = state.tag,
      objectKeyList = Object.keys(object),
      index,
      length,
      objectKey,
      objectValue,
      explicitPair,
      pairBuffer;

  // Allow sorting keys so that the output file is deterministic
  if (state.sortKeys === true) {
    // Default sorting
    objectKeyList.sort();
  } else if (typeof state.sortKeys === 'function') {
    // Custom sort function
    objectKeyList.sort(state.sortKeys);
  } else if (state.sortKeys) {
    // Something is wrong
    throw new YAMLException('sortKeys must be a boolean or a function');
  }

  for (index = 0, length = objectKeyList.length; index < length; index += 1) {
    pairBuffer = '';

    if (!compact || _result !== '') {
      pairBuffer += generateNextLine(state, level);
    }

    objectKey = objectKeyList[index];
    objectValue = object[objectKey];

    if (state.replacer) {
      objectValue = state.replacer.call(object, objectKey, objectValue);
    }

    if (!writeNode(state, level + 1, objectKey, true, true, true)) {
      continue; // Skip this pair because of invalid key.
    }

    explicitPair = (state.tag !== null && state.tag !== '?') ||
                   (state.dump && state.dump.length > 1024);

    if (explicitPair) {
      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
        pairBuffer += '?';
      } else {
        pairBuffer += '? ';
      }
    }

    pairBuffer += state.dump;

    if (explicitPair) {
      pairBuffer += generateNextLine(state, level);
    }

    if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
      continue; // Skip this pair because of invalid value.
    }

    if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
      pairBuffer += ':';
    } else {
      pairBuffer += ': ';
    }

    pairBuffer += state.dump;

    // Both key and value are valid.
    _result += pairBuffer;
  }

  state.tag = _tag;
  state.dump = _result || '{}'; // Empty mapping if no valid pairs.
}

function detectType(state, object, explicit) {
  var _result, typeList, index, length, type, style;

  typeList = explicit ? state.explicitTypes : state.implicitTypes;

  for (index = 0, length = typeList.length; index < length; index += 1) {
    type = typeList[index];

    if ((type.instanceOf  || type.predicate) &&
        (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&
        (!type.predicate  || type.predicate(object))) {

      if (explicit) {
        if (type.multi && type.representName) {
          state.tag = type.representName(object);
        } else {
          state.tag = type.tag;
        }
      } else {
        state.tag = '?';
      }

      if (type.represent) {
        style = state.styleMap[type.tag] || type.defaultStyle;

        if (_toString.call(type.represent) === '[object Function]') {
          _result = type.represent(object, style);
        } else if (_hasOwnProperty.call(type.represent, style)) {
          _result = type.represent[style](object, style);
        } else {
          throw new YAMLException('!<' + type.tag + '> tag resolver accepts not "' + style + '" style');
        }

        state.dump = _result;
      }

      return true;
    }
  }

  return false;
}

// Serializes `object` and writes it to global `result`.
// Returns true on success, or false on invalid object.
//
function writeNode(state, level, object, block, compact, iskey, isblockseq) {
  state.tag = null;
  state.dump = object;

  if (!detectType(state, object, false)) {
    detectType(state, object, true);
  }

  var type = _toString.call(state.dump);
  var inblock = block;
  var tagStr;

  if (block) {
    block = (state.flowLevel < 0 || state.flowLevel > level);
  }

  var objectOrArray = type === '[object Object]' || type === '[object Array]',
      duplicateIndex,
      duplicate;

  if (objectOrArray) {
    duplicateIndex = state.duplicates.indexOf(object);
    duplicate = duplicateIndex !== -1;
  }

  if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {
    compact = false;
  }

  if (duplicate && state.usedDuplicates[duplicateIndex]) {
    state.dump = '*ref_' + duplicateIndex;
  } else {
    if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
      state.usedDuplicates[duplicateIndex] = true;
    }
    if (type === '[object Object]') {
      if (block && (Object.keys(state.dump).length !== 0)) {
        writeBlockMapping(state, level, state.dump, compact);
        if (duplicate) {
          state.dump = '&ref_' + duplicateIndex + state.dump;
        }
      } else {
        writeFlowMapping(state, level, state.dump);
        if (duplicate) {
          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
        }
      }
    } else if (type === '[object Array]') {
      if (block && (state.dump.length !== 0)) {
        if (state.noArrayIndent && !isblockseq && level > 0) {
          writeBlockSequence(state, level - 1, state.dump, compact);
        } else {
          writeBlockSequence(state, level, state.dump, compact);
        }
        if (duplicate) {
          state.dump = '&ref_' + duplicateIndex + state.dump;
        }
      } else {
        writeFlowSequence(state, level, state.dump);
        if (duplicate) {
          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
        }
      }
    } else if (type === '[object String]') {
      if (state.tag !== '?') {
        writeScalar(state, state.dump, level, iskey, inblock);
      }
    } else if (type === '[object Undefined]') {
      return false;
    } else {
      if (state.skipInvalid) return false;
      throw new YAMLException('unacceptable kind of an object to dump ' + type);
    }

    if (state.tag !== null && state.tag !== '?') {
      // Need to encode all characters except those allowed by the spec:
      //
      // [35] ns-dec-digit    ::=  [#x30-#x39] /* 0-9 */
      // [36] ns-hex-digit    ::=  ns-dec-digit
      //                         | [#x41-#x46] /* A-F */ | [#x61-#x66] /* a-f */
      // [37] ns-ascii-letter ::=  [#x41-#x5A] /* A-Z */ | [#x61-#x7A] /* a-z */
      // [38] ns-word-char    ::=  ns-dec-digit | ns-ascii-letter | “-”
      // [39] ns-uri-char     ::=  “%” ns-hex-digit ns-hex-digit | ns-word-char | “#”
      //                         | “;” | “/” | “?” | “:” | “@” | “&” | “=” | “+” | “$” | “,”
      //                         | “_” | “.” | “!” | “~” | “*” | “'” | “(” | “)” | “[” | “]”
      //
      // Also need to encode '!' because it has special meaning (end of tag prefix).
      //
      tagStr = encodeURI(
        state.tag[0] === '!' ? state.tag.slice(1) : state.tag
      ).replace(/!/g, '%21');

      if (state.tag[0] === '!') {
        tagStr = '!' + tagStr;
      } else if (tagStr.slice(0, 18) === 'tag:yaml.org,2002:') {
        tagStr = '!!' + tagStr.slice(18);
      } else {
        tagStr = '!<' + tagStr + '>';
      }

      state.dump = tagStr + ' ' + state.dump;
    }
  }

  return true;
}

function getDuplicateReferences(object, state) {
  var objects = [],
      duplicatesIndexes = [],
      index,
      length;

  inspectNode(object, objects, duplicatesIndexes);

  for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) {
    state.duplicates.push(objects[duplicatesIndexes[index]]);
  }
  state.usedDuplicates = new Array(length);
}

function inspectNode(object, objects, duplicatesIndexes) {
  var objectKeyList,
      index,
      length;

  if (object !== null && typeof object === 'object') {
    index = objects.indexOf(object);
    if (index !== -1) {
      if (duplicatesIndexes.indexOf(index) === -1) {
        duplicatesIndexes.push(index);
      }
    } else {
      objects.push(object);

      if (Array.isArray(object)) {
        for (index = 0, length = object.length; index < length; index += 1) {
          inspectNode(object[index], objects, duplicatesIndexes);
        }
      } else {
        objectKeyList = Object.keys(object);

        for (index = 0, length = objectKeyList.length; index < length; index += 1) {
          inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes);
        }
      }
    }
  }
}

function dump(input, options) {
  options = options || {};

  var state = new State(options);

  if (!state.noRefs) getDuplicateReferences(input, state);

  var value = input;

  if (state.replacer) {
    value = state.replacer.call({ '': value }, '', value);
  }

  if (writeNode(state, 0, value, true, true)) return state.dump + '\n';

  return '';
}

module.exports.dump = dump;
// YAML error class. http://stackoverflow.com/questions/8458984
//
'use strict';


function formatError(exception, compact) {
  var where = '', message = exception.reason || '(unknown reason)';

  if (!exception.mark) return message;

  if (exception.mark.name) {
    where += 'in "' + exception.mark.name + '" ';
  }

  where += '(' + (exception.mark.line + 1) + ':' + (exception.mark.column + 1) + ')';

  if (!compact && exception.mark.snippet) {
    where += '\n\n' + exception.mark.snippet;
  }

  return message + ' ' + where;
}


function YAMLException(reason, mark) {
  // Super constructor
  Error.call(this);

  this.name = 'YAMLException';
  this.reason = reason;
  this.mark = mark;
  this.message = formatError(this, false);

  // Include stack trace in error object
  if (Error.captureStackTrace) {
    // Chrome and NodeJS
    Error.captureStackTrace(this, this.constructor);
  } else {
    // FF, IE 10+ and Safari 6+. Fallback for others
    this.stack = (new Error()).stack || '';
  }
}


// Inherit from Error
YAMLException.prototype = Object.create(Error.prototype);
YAMLException.prototype.constructor = YAMLException;


YAMLException.prototype.toString = function toString(compact) {
  return this.name + ': ' + formatError(this, compact);
};


module.exports = YAMLException;
'use strict';

/*eslint-disable max-len,no-use-before-define*/

var common              = require('./common');
var YAMLException       = require('./exception');
var makeSnippet         = require('./snippet');
var DEFAULT_SCHEMA      = require('./schema/default');


var _hasOwnProperty = Object.prototype.hasOwnProperty;


var CONTEXT_FLOW_IN   = 1;
var CONTEXT_FLOW_OUT  = 2;
var CONTEXT_BLOCK_IN  = 3;
var CONTEXT_BLOCK_OUT = 4;


var CHOMPING_CLIP  = 1;
var CHOMPING_STRIP = 2;
var CHOMPING_KEEP  = 3;


var PATTERN_NON_PRINTABLE         = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/;
var PATTERN_FLOW_INDICATORS       = /[,\[\]\{\}]/;
var PATTERN_TAG_HANDLE            = /^(?:!|!!|![a-z\-]+!)$/i;
var PATTERN_TAG_URI               = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;


function _class(obj) { return Object.prototype.toString.call(obj); }

function is_EOL(c) {
  return (c === 0x0A/* LF */) || (c === 0x0D/* CR */);
}

function is_WHITE_SPACE(c) {
  return (c === 0x09/* Tab */) || (c === 0x20/* Space */);
}

function is_WS_OR_EOL(c) {
  return (c === 0x09/* Tab */) ||
         (c === 0x20/* Space */) ||
         (c === 0x0A/* LF */) ||
         (c === 0x0D/* CR */);
}

function is_FLOW_INDICATOR(c) {
  return c === 0x2C/* , */ ||
         c === 0x5B/* [ */ ||
         c === 0x5D/* ] */ ||
         c === 0x7B/* { */ ||
         c === 0x7D/* } */;
}

function fromHexCode(c) {
  var lc;

  if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {
    return c - 0x30;
  }

  /*eslint-disable no-bitwise*/
  lc = c | 0x20;

  if ((0x61/* a */ <= lc) && (lc <= 0x66/* f */)) {
    return lc - 0x61 + 10;
  }

  return -1;
}

function escapedHexLen(c) {
  if (c === 0x78/* x */) { return 2; }
  if (c === 0x75/* u */) { return 4; }
  if (c === 0x55/* U */) { return 8; }
  return 0;
}

function fromDecimalCode(c) {
  if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {
    return c - 0x30;
  }

  return -1;
}

function simpleEscapeSequence(c) {
  /* eslint-disable indent */
  return (c === 0x30/* 0 */) ? '\x00' :
        (c === 0x61/* a */) ? '\x07' :
        (c === 0x62/* b */) ? '\x08' :
        (c === 0x74/* t */) ? '\x09' :
        (c === 0x09/* Tab */) ? '\x09' :
        (c === 0x6E/* n */) ? '\x0A' :
        (c === 0x76/* v */) ? '\x0B' :
        (c === 0x66/* f */) ? '\x0C' :
        (c === 0x72/* r */) ? '\x0D' :
        (c === 0x65/* e */) ? '\x1B' :
        (c === 0x20/* Space */) ? ' ' :
        (c === 0x22/* " */) ? '\x22' :
        (c === 0x2F/* / */) ? '/' :
        (c === 0x5C/* \ */) ? '\x5C' :
        (c === 0x4E/* N */) ? '\x85' :
        (c === 0x5F/* _ */) ? '\xA0' :
        (c === 0x4C/* L */) ? '\u2028' :
        (c === 0x50/* P */) ? '\u2029' : '';
}

function charFromCodepoint(c) {
  if (c <= 0xFFFF) {
    return String.fromCharCode(c);
  }
  // Encode UTF-16 surrogate pair
  // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF
  return String.fromCharCode(
    ((c - 0x010000) >> 10) + 0xD800,
    ((c - 0x010000) & 0x03FF) + 0xDC00
  );
}

var simpleEscapeCheck = new Array(256); // integer, for fast access
var simpleEscapeMap = new Array(256);
for (var i = 0; i < 256; i++) {
  simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0;
  simpleEscapeMap[i] = simpleEscapeSequence(i);
}


function State(input, options) {
  this.input = input;

  this.filename  = options['filename']  || null;
  this.schema    = options['schema']    || DEFAULT_SCHEMA;
  this.onWarning = options['onWarning'] || null;
  // (Hidden) Remove? makes the loader to expect YAML 1.1 documents
  // if such documents have no explicit %YAML directive
  this.legacy    = options['legacy']    || false;

  this.json      = options['json']      || false;
  this.listener  = options['listener']  || null;

  this.implicitTypes = this.schema.compiledImplicit;
  this.typeMap       = this.schema.compiledTypeMap;

  this.length     = input.length;
  this.position   = 0;
  this.line       = 0;
  this.lineStart  = 0;
  this.lineIndent = 0;

  // position of first leading tab in the current line,
  // used to make sure there are no tabs in the indentation
  this.firstTabInLine = -1;

  this.documents = [];

  /*
  this.version;
  this.checkLineBreaks;
  this.tagMap;
  this.anchorMap;
  this.tag;
  this.anchor;
  this.kind;
  this.result;*/

}


function generateError(state, message) {
  var mark = {
    name:     state.filename,
    buffer:   state.input.slice(0, -1), // omit trailing \0
    position: state.position,
    line:     state.line,
    column:   state.position - state.lineStart
  };

  mark.snippet = makeSnippet(mark);

  return new YAMLException(message, mark);
}

function throwError(state, message) {
  throw generateError(state, message);
}

function throwWarning(state, message) {
  if (state.onWarning) {
    state.onWarning.call(null, generateError(state, message));
  }
}


var directiveHandlers = {

  YAML: function handleYamlDirective(state, name, args) {

    var match, major, minor;

    if (state.version !== null) {
      throwError(state, 'duplication of %YAML directive');
    }

    if (args.length !== 1) {
      throwError(state, 'YAML directive accepts exactly one argument');
    }

    match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]);

    if (match === null) {
      throwError(state, 'ill-formed argument of the YAML directive');
    }

    major = parseInt(match[1], 10);
    minor = parseInt(match[2], 10);

    if (major !== 1) {
      throwError(state, 'unacceptable YAML version of the document');
    }

    state.version = args[0];
    state.checkLineBreaks = (minor < 2);

    if (minor !== 1 && minor !== 2) {
      throwWarning(state, 'unsupported YAML version of the document');
    }
  },

  TAG: function handleTagDirective(state, name, args) {

    var handle, prefix;

    if (args.length !== 2) {
      throwError(state, 'TAG directive accepts exactly two arguments');
    }

    handle = args[0];
    prefix = args[1];

    if (!PATTERN_TAG_HANDLE.test(handle)) {
      throwError(state, 'ill-formed tag handle (first argument) of the TAG directive');
    }

    if (_hasOwnProperty.call(state.tagMap, handle)) {
      throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle');
    }

    if (!PATTERN_TAG_URI.test(prefix)) {
      throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive');
    }

    try {
      prefix = decodeURIComponent(prefix);
    } catch (err) {
      throwError(state, 'tag prefix is malformed: ' + prefix);
    }

    state.tagMap[handle] = prefix;
  }
};


function captureSegment(state, start, end, checkJson) {
  var _position, _length, _character, _result;

  if (start < end) {
    _result = state.input.slice(start, end);

    if (checkJson) {
      for (_position = 0, _length = _result.length; _position < _length; _position += 1) {
        _character = _result.charCodeAt(_position);
        if (!(_character === 0x09 ||
              (0x20 <= _character && _character <= 0x10FFFF))) {
          throwError(state, 'expected valid JSON character');
        }
      }
    } else if (PATTERN_NON_PRINTABLE.test(_result)) {
      throwError(state, 'the stream contains non-printable characters');
    }

    state.result += _result;
  }
}

function mergeMappings(state, destination, source, overridableKeys) {
  var sourceKeys, key, index, quantity;

  if (!common.isObject(source)) {
    throwError(state, 'cannot merge mappings; the provided source object is unacceptable');
  }

  sourceKeys = Object.keys(source);

  for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
    key = sourceKeys[index];

    if (!_hasOwnProperty.call(destination, key)) {
      destination[key] = source[key];
      overridableKeys[key] = true;
    }
  }
}

function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode,
  startLine, startLineStart, startPos) {

  var index, quantity;

  // The output is a plain object here, so keys can only be strings.
  // We need to convert keyNode to a string, but doing so can hang the process
  // (deeply nested arrays that explode exponentially using aliases).
  if (Array.isArray(keyNode)) {
    keyNode = Array.prototype.slice.call(keyNode);

    for (index = 0, quantity = keyNode.length; index < quantity; index += 1) {
      if (Array.isArray(keyNode[index])) {
        throwError(state, 'nested arrays are not supported inside keys');
      }

      if (typeof keyNode === 'object' && _class(keyNode[index]) === '[object Object]') {
        keyNode[index] = '[object Object]';
      }
    }
  }

  // Avoid code execution in load() via toString property
  // (still use its own toString for arrays, timestamps,
  // and whatever user schema extensions happen to have @@toStringTag)
  if (typeof keyNode === 'object' && _class(keyNode) === '[object Object]') {
    keyNode = '[object Object]';
  }


  keyNode = String(keyNode);

  if (_result === null) {
    _result = {};
  }

  if (keyTag === 'tag:yaml.org,2002:merge') {
    if (Array.isArray(valueNode)) {
      for (index = 0, quantity = valueNode.length; index < quantity; index += 1) {
        mergeMappings(state, _result, valueNode[index], overridableKeys);
      }
    } else {
      mergeMappings(state, _result, valueNode, overridableKeys);
    }
  } else {
    if (!state.json &&
        !_hasOwnProperty.call(overridableKeys, keyNode) &&
        _hasOwnProperty.call(_result, keyNode)) {
      state.line = startLine || state.line;
      state.lineStart = startLineStart || state.lineStart;
      state.position = startPos || state.position;
      throwError(state, 'duplicated mapping key');
    }

    // used for this specific key only because Object.defineProperty is slow
    if (keyNode === '__proto__') {
      Object.defineProperty(_result, keyNode, {
        configurable: true,
        enumerable: true,
        writable: true,
        value: valueNode
      });
    } else {
      _result[keyNode] = valueNode;
    }
    delete overridableKeys[keyNode];
  }

  return _result;
}

function readLineBreak(state) {
  var ch;

  ch = state.input.charCodeAt(state.position);

  if (ch === 0x0A/* LF */) {
    state.position++;
  } else if (ch === 0x0D/* CR */) {
    state.position++;
    if (state.input.charCodeAt(state.position) === 0x0A/* LF */) {
      state.position++;
    }
  } else {
    throwError(state, 'a line break is expected');
  }

  state.line += 1;
  state.lineStart = state.position;
  state.firstTabInLine = -1;
}

function skipSeparationSpace(state, allowComments, checkIndent) {
  var lineBreaks = 0,
      ch = state.input.charCodeAt(state.position);

  while (ch !== 0) {
    while (is_WHITE_SPACE(ch)) {
      if (ch === 0x09/* Tab */ && state.firstTabInLine === -1) {
        state.firstTabInLine = state.position;
      }
      ch = state.input.charCodeAt(++state.position);
    }

    if (allowComments && ch === 0x23/* # */) {
      do {
        ch = state.input.charCodeAt(++state.position);
      } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0);
    }

    if (is_EOL(ch)) {
      readLineBreak(state);

      ch = state.input.charCodeAt(state.position);
      lineBreaks++;
      state.lineIndent = 0;

      while (ch === 0x20/* Space */) {
        state.lineIndent++;
        ch = state.input.charCodeAt(++state.position);
      }
    } else {
      break;
    }
  }

  if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {
    throwWarning(state, 'deficient indentation');
  }

  return lineBreaks;
}

function testDocumentSeparator(state) {
  var _position = state.position,
      ch;

  ch = state.input.charCodeAt(_position);

  // Condition state.position === state.lineStart is tested
  // in parent on each call, for efficiency. No needs to test here again.
  if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) &&
      ch === state.input.charCodeAt(_position + 1) &&
      ch === state.input.charCodeAt(_position + 2)) {

    _position += 3;

    ch = state.input.charCodeAt(_position);

    if (ch === 0 || is_WS_OR_EOL(ch)) {
      return true;
    }
  }

  return false;
}

function writeFoldedLines(state, count) {
  if (count === 1) {
    state.result += ' ';
  } else if (count > 1) {
    state.result += common.repeat('\n', count - 1);
  }
}


function readPlainScalar(state, nodeIndent, withinFlowCollection) {
  var preceding,
      following,
      captureStart,
      captureEnd,
      hasPendingContent,
      _line,
      _lineStart,
      _lineIndent,
      _kind = state.kind,
      _result = state.result,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (is_WS_OR_EOL(ch)      ||
      is_FLOW_INDICATOR(ch) ||
      ch === 0x23/* # */    ||
      ch === 0x26/* & */    ||
      ch === 0x2A/* * */    ||
      ch === 0x21/* ! */    ||
      ch === 0x7C/* | */    ||
      ch === 0x3E/* > */    ||
      ch === 0x27/* ' */    ||
      ch === 0x22/* " */    ||
      ch === 0x25/* % */    ||
      ch === 0x40/* @ */    ||
      ch === 0x60/* ` */) {
    return false;
  }

  if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) {
    following = state.input.charCodeAt(state.position + 1);

    if (is_WS_OR_EOL(following) ||
        withinFlowCollection && is_FLOW_INDICATOR(following)) {
      return false;
    }
  }

  state.kind = 'scalar';
  state.result = '';
  captureStart = captureEnd = state.position;
  hasPendingContent = false;

  while (ch !== 0) {
    if (ch === 0x3A/* : */) {
      following = state.input.charCodeAt(state.position + 1);

      if (is_WS_OR_EOL(following) ||
          withinFlowCollection && is_FLOW_INDICATOR(following)) {
        break;
      }

    } else if (ch === 0x23/* # */) {
      preceding = state.input.charCodeAt(state.position - 1);

      if (is_WS_OR_EOL(preceding)) {
        break;
      }

    } else if ((state.position === state.lineStart && testDocumentSeparator(state)) ||
               withinFlowCollection && is_FLOW_INDICATOR(ch)) {
      break;

    } else if (is_EOL(ch)) {
      _line = state.line;
      _lineStart = state.lineStart;
      _lineIndent = state.lineIndent;
      skipSeparationSpace(state, false, -1);

      if (state.lineIndent >= nodeIndent) {
        hasPendingContent = true;
        ch = state.input.charCodeAt(state.position);
        continue;
      } else {
        state.position = captureEnd;
        state.line = _line;
        state.lineStart = _lineStart;
        state.lineIndent = _lineIndent;
        break;
      }
    }

    if (hasPendingContent) {
      captureSegment(state, captureStart, captureEnd, false);
      writeFoldedLines(state, state.line - _line);
      captureStart = captureEnd = state.position;
      hasPendingContent = false;
    }

    if (!is_WHITE_SPACE(ch)) {
      captureEnd = state.position + 1;
    }

    ch = state.input.charCodeAt(++state.position);
  }

  captureSegment(state, captureStart, captureEnd, false);

  if (state.result) {
    return true;
  }

  state.kind = _kind;
  state.result = _result;
  return false;
}

function readSingleQuotedScalar(state, nodeIndent) {
  var ch,
      captureStart, captureEnd;

  ch = state.input.charCodeAt(state.position);

  if (ch !== 0x27/* ' */) {
    return false;
  }

  state.kind = 'scalar';
  state.result = '';
  state.position++;
  captureStart = captureEnd = state.position;

  while ((ch = state.input.charCodeAt(state.position)) !== 0) {
    if (ch === 0x27/* ' */) {
      captureSegment(state, captureStart, state.position, true);
      ch = state.input.charCodeAt(++state.position);

      if (ch === 0x27/* ' */) {
        captureStart = state.position;
        state.position++;
        captureEnd = state.position;
      } else {
        return true;
      }

    } else if (is_EOL(ch)) {
      captureSegment(state, captureStart, captureEnd, true);
      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
      captureStart = captureEnd = state.position;

    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
      throwError(state, 'unexpected end of the document within a single quoted scalar');

    } else {
      state.position++;
      captureEnd = state.position;
    }
  }

  throwError(state, 'unexpected end of the stream within a single quoted scalar');
}

function readDoubleQuotedScalar(state, nodeIndent) {
  var captureStart,
      captureEnd,
      hexLength,
      hexResult,
      tmp,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (ch !== 0x22/* " */) {
    return false;
  }

  state.kind = 'scalar';
  state.result = '';
  state.position++;
  captureStart = captureEnd = state.position;

  while ((ch = state.input.charCodeAt(state.position)) !== 0) {
    if (ch === 0x22/* " */) {
      captureSegment(state, captureStart, state.position, true);
      state.position++;
      return true;

    } else if (ch === 0x5C/* \ */) {
      captureSegment(state, captureStart, state.position, true);
      ch = state.input.charCodeAt(++state.position);

      if (is_EOL(ch)) {
        skipSeparationSpace(state, false, nodeIndent);

        // TODO: rework to inline fn with no type cast?
      } else if (ch < 256 && simpleEscapeCheck[ch]) {
        state.result += simpleEscapeMap[ch];
        state.position++;

      } else if ((tmp = escapedHexLen(ch)) > 0) {
        hexLength = tmp;
        hexResult = 0;

        for (; hexLength > 0; hexLength--) {
          ch = state.input.charCodeAt(++state.position);

          if ((tmp = fromHexCode(ch)) >= 0) {
            hexResult = (hexResult << 4) + tmp;

          } else {
            throwError(state, 'expected hexadecimal character');
          }
        }

        state.result += charFromCodepoint(hexResult);

        state.position++;

      } else {
        throwError(state, 'unknown escape sequence');
      }

      captureStart = captureEnd = state.position;

    } else if (is_EOL(ch)) {
      captureSegment(state, captureStart, captureEnd, true);
      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
      captureStart = captureEnd = state.position;

    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
      throwError(state, 'unexpected end of the document within a double quoted scalar');

    } else {
      state.position++;
      captureEnd = state.position;
    }
  }

  throwError(state, 'unexpected end of the stream within a double quoted scalar');
}

function readFlowCollection(state, nodeIndent) {
  var readNext = true,
      _line,
      _lineStart,
      _pos,
      _tag     = state.tag,
      _result,
      _anchor  = state.anchor,
      following,
      terminator,
      isPair,
      isExplicitPair,
      isMapping,
      overridableKeys = Object.create(null),
      keyNode,
      keyTag,
      valueNode,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (ch === 0x5B/* [ */) {
    terminator = 0x5D;/* ] */
    isMapping = false;
    _result = [];
  } else if (ch === 0x7B/* { */) {
    terminator = 0x7D;/* } */
    isMapping = true;
    _result = {};
  } else {
    return false;
  }

  if (state.anchor !== null) {
    state.anchorMap[state.anchor] = _result;
  }

  ch = state.input.charCodeAt(++state.position);

  while (ch !== 0) {
    skipSeparationSpace(state, true, nodeIndent);

    ch = state.input.charCodeAt(state.position);

    if (ch === terminator) {
      state.position++;
      state.tag = _tag;
      state.anchor = _anchor;
      state.kind = isMapping ? 'mapping' : 'sequence';
      state.result = _result;
      return true;
    } else if (!readNext) {
      throwError(state, 'missed comma between flow collection entries');
    } else if (ch === 0x2C/* , */) {
      // "flow collection entries can never be completely empty", as per YAML 1.2, section 7.4
      throwError(state, "expected the node content, but found ','");
    }

    keyTag = keyNode = valueNode = null;
    isPair = isExplicitPair = false;

    if (ch === 0x3F/* ? */) {
      following = state.input.charCodeAt(state.position + 1);

      if (is_WS_OR_EOL(following)) {
        isPair = isExplicitPair = true;
        state.position++;
        skipSeparationSpace(state, true, nodeIndent);
      }
    }

    _line = state.line; // Save the current line.
    _lineStart = state.lineStart;
    _pos = state.position;
    composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
    keyTag = state.tag;
    keyNode = state.result;
    skipSeparationSpace(state, true, nodeIndent);

    ch = state.input.charCodeAt(state.position);

    if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) {
      isPair = true;
      ch = state.input.charCodeAt(++state.position);
      skipSeparationSpace(state, true, nodeIndent);
      composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
      valueNode = state.result;
    }

    if (isMapping) {
      storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos);
    } else if (isPair) {
      _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos));
    } else {
      _result.push(keyNode);
    }

    skipSeparationSpace(state, true, nodeIndent);

    ch = state.input.charCodeAt(state.position);

    if (ch === 0x2C/* , */) {
      readNext = true;
      ch = state.input.charCodeAt(++state.position);
    } else {
      readNext = false;
    }
  }

  throwError(state, 'unexpected end of the stream within a flow collection');
}

function readBlockScalar(state, nodeIndent) {
  var captureStart,
      folding,
      chomping       = CHOMPING_CLIP,
      didReadContent = false,
      detectedIndent = false,
      textIndent     = nodeIndent,
      emptyLines     = 0,
      atMoreIndented = false,
      tmp,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (ch === 0x7C/* | */) {
    folding = false;
  } else if (ch === 0x3E/* > */) {
    folding = true;
  } else {
    return false;
  }

  state.kind = 'scalar';
  state.result = '';

  while (ch !== 0) {
    ch = state.input.charCodeAt(++state.position);

    if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {
      if (CHOMPING_CLIP === chomping) {
        chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP;
      } else {
        throwError(state, 'repeat of a chomping mode identifier');
      }

    } else if ((tmp = fromDecimalCode(ch)) >= 0) {
      if (tmp === 0) {
        throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one');
      } else if (!detectedIndent) {
        textIndent = nodeIndent + tmp - 1;
        detectedIndent = true;
      } else {
        throwError(state, 'repeat of an indentation width identifier');
      }

    } else {
      break;
    }
  }

  if (is_WHITE_SPACE(ch)) {
    do { ch = state.input.charCodeAt(++state.position); }
    while (is_WHITE_SPACE(ch));

    if (ch === 0x23/* # */) {
      do { ch = state.input.charCodeAt(++state.position); }
      while (!is_EOL(ch) && (ch !== 0));
    }
  }

  while (ch !== 0) {
    readLineBreak(state);
    state.lineIndent = 0;

    ch = state.input.charCodeAt(state.position);

    while ((!detectedIndent || state.lineIndent < textIndent) &&
           (ch === 0x20/* Space */)) {
      state.lineIndent++;
      ch = state.input.charCodeAt(++state.position);
    }

    if (!detectedIndent && state.lineIndent > textIndent) {
      textIndent = state.lineIndent;
    }

    if (is_EOL(ch)) {
      emptyLines++;
      continue;
    }

    // End of the scalar.
    if (state.lineIndent < textIndent) {

      // Perform the chomping.
      if (chomping === CHOMPING_KEEP) {
        state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
      } else if (chomping === CHOMPING_CLIP) {
        if (didReadContent) { // i.e. only if the scalar is not empty.
          state.result += '\n';
        }
      }

      // Break this `while` cycle and go to the funciton's epilogue.
      break;
    }

    // Folded style: use fancy rules to handle line breaks.
    if (folding) {

      // Lines starting with white space characters (more-indented lines) are not folded.
      if (is_WHITE_SPACE(ch)) {
        atMoreIndented = true;
        // except for the first content line (cf. Example 8.1)
        state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);

      // End of more-indented block.
      } else if (atMoreIndented) {
        atMoreIndented = false;
        state.result += common.repeat('\n', emptyLines + 1);

      // Just one line break - perceive as the same line.
      } else if (emptyLines === 0) {
        if (didReadContent) { // i.e. only if we have already read some scalar content.
          state.result += ' ';
        }

      // Several line breaks - perceive as different lines.
      } else {
        state.result += common.repeat('\n', emptyLines);
      }

    // Literal style: just add exact number of line breaks between content lines.
    } else {
      // Keep all line breaks except the header line break.
      state.result += common.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
    }

    didReadContent = true;
    detectedIndent = true;
    emptyLines = 0;
    captureStart = state.position;

    while (!is_EOL(ch) && (ch !== 0)) {
      ch = state.input.charCodeAt(++state.position);
    }

    captureSegment(state, captureStart, state.position, false);
  }

  return true;
}

function readBlockSequence(state, nodeIndent) {
  var _line,
      _tag      = state.tag,
      _anchor   = state.anchor,
      _result   = [],
      following,
      detected  = false,
      ch;

  // there is a leading tab before this token, so it can't be a block sequence/mapping;
  // it can still be flow sequence/mapping or a scalar
  if (state.firstTabInLine !== -1) return false;

  if (state.anchor !== null) {
    state.anchorMap[state.anchor] = _result;
  }

  ch = state.input.charCodeAt(state.position);

  while (ch !== 0) {
    if (state.firstTabInLine !== -1) {
      state.position = state.firstTabInLine;
      throwError(state, 'tab characters must not be used in indentation');
    }

    if (ch !== 0x2D/* - */) {
      break;
    }

    following = state.input.charCodeAt(state.position + 1);

    if (!is_WS_OR_EOL(following)) {
      break;
    }

    detected = true;
    state.position++;

    if (skipSeparationSpace(state, true, -1)) {
      if (state.lineIndent <= nodeIndent) {
        _result.push(null);
        ch = state.input.charCodeAt(state.position);
        continue;
      }
    }

    _line = state.line;
    composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true);
    _result.push(state.result);
    skipSeparationSpace(state, true, -1);

    ch = state.input.charCodeAt(state.position);

    if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {
      throwError(state, 'bad indentation of a sequence entry');
    } else if (state.lineIndent < nodeIndent) {
      break;
    }
  }

  if (detected) {
    state.tag = _tag;
    state.anchor = _anchor;
    state.kind = 'sequence';
    state.result = _result;
    return true;
  }
  return false;
}

function readBlockMapping(state, nodeIndent, flowIndent) {
  var following,
      allowCompact,
      _line,
      _keyLine,
      _keyLineStart,
      _keyPos,
      _tag          = state.tag,
      _anchor       = state.anchor,
      _result       = {},
      overridableKeys = Object.create(null),
      keyTag        = null,
      keyNode       = null,
      valueNode     = null,
      atExplicitKey = false,
      detected      = false,
      ch;

  // there is a leading tab before this token, so it can't be a block sequence/mapping;
  // it can still be flow sequence/mapping or a scalar
  if (state.firstTabInLine !== -1) return false;

  if (state.anchor !== null) {
    state.anchorMap[state.anchor] = _result;
  }

  ch = state.input.charCodeAt(state.position);

  while (ch !== 0) {
    if (!atExplicitKey && state.firstTabInLine !== -1) {
      state.position = state.firstTabInLine;
      throwError(state, 'tab characters must not be used in indentation');
    }

    following = state.input.charCodeAt(state.position + 1);
    _line = state.line; // Save the current line.

    //
    // Explicit notation case. There are two separate blocks:
    // first for the key (denoted by "?") and second for the value (denoted by ":")
    //
    if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && is_WS_OR_EOL(following)) {

      if (ch === 0x3F/* ? */) {
        if (atExplicitKey) {
          storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
          keyTag = keyNode = valueNode = null;
        }

        detected = true;
        atExplicitKey = true;
        allowCompact = true;

      } else if (atExplicitKey) {
        // i.e. 0x3A/* : */ === character after the explicit key.
        atExplicitKey = false;
        allowCompact = true;

      } else {
        throwError(state, 'incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line');
      }

      state.position += 1;
      ch = following;

    //
    // Implicit notation case. Flow-style node as the key first, then ":", and the value.
    //
    } else {
      _keyLine = state.line;
      _keyLineStart = state.lineStart;
      _keyPos = state.position;

      if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {
        // Neither implicit nor explicit notation.
        // Reading is done. Go to the epilogue.
        break;
      }

      if (state.line === _line) {
        ch = state.input.charCodeAt(state.position);

        while (is_WHITE_SPACE(ch)) {
          ch = state.input.charCodeAt(++state.position);
        }

        if (ch === 0x3A/* : */) {
          ch = state.input.charCodeAt(++state.position);

          if (!is_WS_OR_EOL(ch)) {
            throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping');
          }

          if (atExplicitKey) {
            storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
            keyTag = keyNode = valueNode = null;
          }

          detected = true;
          atExplicitKey = false;
          allowCompact = false;
          keyTag = state.tag;
          keyNode = state.result;

        } else if (detected) {
          throwError(state, 'can not read an implicit mapping pair; a colon is missed');

        } else {
          state.tag = _tag;
          state.anchor = _anchor;
          return true; // Keep the result of `composeNode`.
        }

      } else if (detected) {
        throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key');

      } else {
        state.tag = _tag;
        state.anchor = _anchor;
        return true; // Keep the result of `composeNode`.
      }
    }

    //
    // Common reading code for both explicit and implicit notations.
    //
    if (state.line === _line || state.lineIndent > nodeIndent) {
      if (atExplicitKey) {
        _keyLine = state.line;
        _keyLineStart = state.lineStart;
        _keyPos = state.position;
      }

      if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {
        if (atExplicitKey) {
          keyNode = state.result;
        } else {
          valueNode = state.result;
        }
      }

      if (!atExplicitKey) {
        storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos);
        keyTag = keyNode = valueNode = null;
      }

      skipSeparationSpace(state, true, -1);
      ch = state.input.charCodeAt(state.position);
    }

    if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {
      throwError(state, 'bad indentation of a mapping entry');
    } else if (state.lineIndent < nodeIndent) {
      break;
    }
  }

  //
  // Epilogue.
  //

  // Special case: last mapping's node contains only the key in explicit notation.
  if (atExplicitKey) {
    storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
  }

  // Expose the resulting mapping.
  if (detected) {
    state.tag = _tag;
    state.anchor = _anchor;
    state.kind = 'mapping';
    state.result = _result;
  }

  return detected;
}

function readTagProperty(state) {
  var _position,
      isVerbatim = false,
      isNamed    = false,
      tagHandle,
      tagName,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (ch !== 0x21/* ! */) return false;

  if (state.tag !== null) {
    throwError(state, 'duplication of a tag property');
  }

  ch = state.input.charCodeAt(++state.position);

  if (ch === 0x3C/* < */) {
    isVerbatim = true;
    ch = state.input.charCodeAt(++state.position);

  } else if (ch === 0x21/* ! */) {
    isNamed = true;
    tagHandle = '!!';
    ch = state.input.charCodeAt(++state.position);

  } else {
    tagHandle = '!';
  }

  _position = state.position;

  if (isVerbatim) {
    do { ch = state.input.charCodeAt(++state.position); }
    while (ch !== 0 && ch !== 0x3E/* > */);

    if (state.position < state.length) {
      tagName = state.input.slice(_position, state.position);
      ch = state.input.charCodeAt(++state.position);
    } else {
      throwError(state, 'unexpected end of the stream within a verbatim tag');
    }
  } else {
    while (ch !== 0 && !is_WS_OR_EOL(ch)) {

      if (ch === 0x21/* ! */) {
        if (!isNamed) {
          tagHandle = state.input.slice(_position - 1, state.position + 1);

          if (!PATTERN_TAG_HANDLE.test(tagHandle)) {
            throwError(state, 'named tag handle cannot contain such characters');
          }

          isNamed = true;
          _position = state.position + 1;
        } else {
          throwError(state, 'tag suffix cannot contain exclamation marks');
        }
      }

      ch = state.input.charCodeAt(++state.position);
    }

    tagName = state.input.slice(_position, state.position);

    if (PATTERN_FLOW_INDICATORS.test(tagName)) {
      throwError(state, 'tag suffix cannot contain flow indicator characters');
    }
  }

  if (tagName && !PATTERN_TAG_URI.test(tagName)) {
    throwError(state, 'tag name cannot contain such characters: ' + tagName);
  }

  try {
    tagName = decodeURIComponent(tagName);
  } catch (err) {
    throwError(state, 'tag name is malformed: ' + tagName);
  }

  if (isVerbatim) {
    state.tag = tagName;

  } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) {
    state.tag = state.tagMap[tagHandle] + tagName;

  } else if (tagHandle === '!') {
    state.tag = '!' + tagName;

  } else if (tagHandle === '!!') {
    state.tag = 'tag:yaml.org,2002:' + tagName;

  } else {
    throwError(state, 'undeclared tag handle "' + tagHandle + '"');
  }

  return true;
}

function readAnchorProperty(state) {
  var _position,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (ch !== 0x26/* & */) return false;

  if (state.anchor !== null) {
    throwError(state, 'duplication of an anchor property');
  }

  ch = state.input.charCodeAt(++state.position);
  _position = state.position;

  while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
    ch = state.input.charCodeAt(++state.position);
  }

  if (state.position === _position) {
    throwError(state, 'name of an anchor node must contain at least one character');
  }

  state.anchor = state.input.slice(_position, state.position);
  return true;
}

function readAlias(state) {
  var _position, alias,
      ch;

  ch = state.input.charCodeAt(state.position);

  if (ch !== 0x2A/* * */) return false;

  ch = state.input.charCodeAt(++state.position);
  _position = state.position;

  while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
    ch = state.input.charCodeAt(++state.position);
  }

  if (state.position === _position) {
    throwError(state, 'name of an alias node must contain at least one character');
  }

  alias = state.input.slice(_position, state.position);

  if (!_hasOwnProperty.call(state.anchorMap, alias)) {
    throwError(state, 'unidentified alias "' + alias + '"');
  }

  state.result = state.anchorMap[alias];
  skipSeparationSpace(state, true, -1);
  return true;
}

function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) {
  var allowBlockStyles,
      allowBlockScalars,
      allowBlockCollections,
      indentStatus = 1, // 1: this>parent, 0: this=parent, -1: this<parent
      atNewLine  = false,
      hasContent = false,
      typeIndex,
      typeQuantity,
      typeList,
      type,
      flowIndent,
      blockIndent;

  if (state.listener !== null) {
    state.listener('open', state);
  }

  state.tag    = null;
  state.anchor = null;
  state.kind   = null;
  state.result = null;

  allowBlockStyles = allowBlockScalars = allowBlockCollections =
    CONTEXT_BLOCK_OUT === nodeContext ||
    CONTEXT_BLOCK_IN  === nodeContext;

  if (allowToSeek) {
    if (skipSeparationSpace(state, true, -1)) {
      atNewLine = true;

      if (state.lineIndent > parentIndent) {
        indentStatus = 1;
      } else if (state.lineIndent === parentIndent) {
        indentStatus = 0;
      } else if (state.lineIndent < parentIndent) {
        indentStatus = -1;
      }
    }
  }

  if (indentStatus === 1) {
    while (readTagProperty(state) || readAnchorProperty(state)) {
      if (skipSeparationSpace(state, true, -1)) {
        atNewLine = true;
        allowBlockCollections = allowBlockStyles;

        if (state.lineIndent > parentIndent) {
          indentStatus = 1;
        } else if (state.lineIndent === parentIndent) {
          indentStatus = 0;
        } else if (state.lineIndent < parentIndent) {
          indentStatus = -1;
        }
      } else {
        allowBlockCollections = false;
      }
    }
  }

  if (allowBlockCollections) {
    allowBlockCollections = atNewLine || allowCompact;
  }

  if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {
    if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {
      flowIndent = parentIndent;
    } else {
      flowIndent = parentIndent + 1;
    }

    blockIndent = state.position - state.lineStart;

    if (indentStatus === 1) {
      if (allowBlockCollections &&
          (readBlockSequence(state, blockIndent) ||
           readBlockMapping(state, blockIndent, flowIndent)) ||
          readFlowCollection(state, flowIndent)) {
        hasContent = true;
      } else {
        if ((allowBlockScalars && readBlockScalar(state, flowIndent)) ||
            readSingleQuotedScalar(state, flowIndent) ||
            readDoubleQuotedScalar(state, flowIndent)) {
          hasContent = true;

        } else if (readAlias(state)) {
          hasContent = true;

          if (state.tag !== null || state.anchor !== null) {
            throwError(state, 'alias node should not have any properties');
          }

        } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {
          hasContent = true;

          if (state.tag === null) {
            state.tag = '?';
          }
        }

        if (state.anchor !== null) {
          state.anchorMap[state.anchor] = state.result;
        }
      }
    } else if (indentStatus === 0) {
      // Special case: block sequences are allowed to have same indentation level as the parent.
      // http://www.yaml.org/spec/1.2/spec.html#id2799784
      hasContent = allowBlockCollections && readBlockSequence(state, blockIndent);
    }
  }

  if (state.tag === null) {
    if (state.anchor !== null) {
      state.anchorMap[state.anchor] = state.result;
    }

  } else if (state.tag === '?') {
    // Implicit resolving is not allowed for non-scalar types, and '?'
    // non-specific tag is only automatically assigned to plain scalars.
    //
    // We only need to check kind conformity in case user explicitly assigns '?'
    // tag, for example like this: "!<?> [0]"
    //
    if (state.result !== null && state.kind !== 'scalar') {
      throwError(state, 'unacceptable node kind for !<?> tag; it should be "scalar", not "' + state.kind + '"');
    }

    for (typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {
      type = state.implicitTypes[typeIndex];

      if (type.resolve(state.result)) { // `state.result` updated in resolver if matched
        state.result = type.construct(state.result);
        state.tag = type.tag;
        if (state.anchor !== null) {
          state.anchorMap[state.anchor] = state.result;
        }
        break;
      }
    }
  } else if (state.tag !== '!') {
    if (_hasOwnProperty.call(state.typeMap[state.kind || 'fallback'], state.tag)) {
      type = state.typeMap[state.kind || 'fallback'][state.tag];
    } else {
      // looking for multi type
      type = null;
      typeList = state.typeMap.multi[state.kind || 'fallback'];

      for (typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) {
        if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) {
          type = typeList[typeIndex];
          break;
        }
      }
    }

    if (!type) {
      throwError(state, 'unknown tag !<' + state.tag + '>');
    }

    if (state.result !== null && type.kind !== state.kind) {
      throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be "' + type.kind + '", not "' + state.kind + '"');
    }

    if (!type.resolve(state.result, state.tag)) { // `state.result` updated in resolver if matched
      throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag');
    } else {
      state.result = type.construct(state.result, state.tag);
      if (state.anchor !== null) {
        state.anchorMap[state.anchor] = state.result;
      }
    }
  }

  if (state.listener !== null) {
    state.listener('close', state);
  }
  return state.tag !== null ||  state.anchor !== null || hasContent;
}

function readDocument(state) {
  var documentStart = state.position,
      _position,
      directiveName,
      directiveArgs,
      hasDirectives = false,
      ch;

  state.version = null;
  state.checkLineBreaks = state.legacy;
  state.tagMap = Object.create(null);
  state.anchorMap = Object.create(null);

  while ((ch = state.input.charCodeAt(state.position)) !== 0) {
    skipSeparationSpace(state, true, -1);

    ch = state.input.charCodeAt(state.position);

    if (state.lineIndent > 0 || ch !== 0x25/* % */) {
      break;
    }

    hasDirectives = true;
    ch = state.input.charCodeAt(++state.position);
    _position = state.position;

    while (ch !== 0 && !is_WS_OR_EOL(ch)) {
      ch = state.input.charCodeAt(++state.position);
    }

    directiveName = state.input.slice(_position, state.position);
    directiveArgs = [];

    if (directiveName.length < 1) {
      throwError(state, 'directive name must not be less than one character in length');
    }

    while (ch !== 0) {
      while (is_WHITE_SPACE(ch)) {
        ch = state.input.charCodeAt(++state.position);
      }

      if (ch === 0x23/* # */) {
        do { ch = state.input.charCodeAt(++state.position); }
        while (ch !== 0 && !is_EOL(ch));
        break;
      }

      if (is_EOL(ch)) break;

      _position = state.position;

      while (ch !== 0 && !is_WS_OR_EOL(ch)) {
        ch = state.input.charCodeAt(++state.position);
      }

      directiveArgs.push(state.input.slice(_position, state.position));
    }

    if (ch !== 0) readLineBreak(state);

    if (_hasOwnProperty.call(directiveHandlers, directiveName)) {
      directiveHandlers[directiveName](state, directiveName, directiveArgs);
    } else {
      throwWarning(state, 'unknown document directive "' + directiveName + '"');
    }
  }

  skipSeparationSpace(state, true, -1);

  if (state.lineIndent === 0 &&
      state.input.charCodeAt(state.position)     === 0x2D/* - */ &&
      state.input.charCodeAt(state.position + 1) === 0x2D/* - */ &&
      state.input.charCodeAt(state.position + 2) === 0x2D/* - */) {
    state.position += 3;
    skipSeparationSpace(state, true, -1);

  } else if (hasDirectives) {
    throwError(state, 'directives end mark is expected');
  }

  composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true);
  skipSeparationSpace(state, true, -1);

  if (state.checkLineBreaks &&
      PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {
    throwWarning(state, 'non-ASCII line breaks are interpreted as content');
  }

  state.documents.push(state.result);

  if (state.position === state.lineStart && testDocumentSeparator(state)) {

    if (state.input.charCodeAt(state.position) === 0x2E/* . */) {
      state.position += 3;
      skipSeparationSpace(state, true, -1);
    }
    return;
  }

  if (state.position < (state.length - 1)) {
    throwError(state, 'end of the stream or a document separator is expected');
  } else {
    return;
  }
}


function loadDocuments(input, options) {
  input = String(input);
  options = options || {};

  if (input.length !== 0) {

    // Add tailing `\n` if not exists
    if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ &&
        input.charCodeAt(input.length - 1) !== 0x0D/* CR */) {
      input += '\n';
    }

    // Strip BOM
    if (input.charCodeAt(0) === 0xFEFF) {
      input = input.slice(1);
    }
  }

  var state = new State(input, options);

  var nullpos = input.indexOf('\0');

  if (nullpos !== -1) {
    state.position = nullpos;
    throwError(state, 'null byte is not allowed in input');
  }

  // Use 0 as string terminator. That significantly simplifies bounds check.
  state.input += '\0';

  while (state.input.charCodeAt(state.position) === 0x20/* Space */) {
    state.lineIndent += 1;
    state.position += 1;
  }

  while (state.position < (state.length - 1)) {
    readDocument(state);
  }

  return state.documents;
}


function loadAll(input, iterator, options) {
  if (iterator !== null && typeof iterator === 'object' && typeof options === 'undefined') {
    options = iterator;
    iterator = null;
  }

  var documents = loadDocuments(input, options);

  if (typeof iterator !== 'function') {
    return documents;
  }

  for (var index = 0, length = documents.length; index < length; index += 1) {
    iterator(documents[index]);
  }
}


function load(input, options) {
  var documents = loadDocuments(input, options);

  if (documents.length === 0) {
    /*eslint-disable no-undefined*/
    return undefined;
  } else if (documents.length === 1) {
    return documents[0];
  }
  throw new YAMLException('expected a single document in the stream, but found more');
}


module.exports.loadAll = loadAll;
module.exports.load    = load;
'use strict';

/*eslint-disable max-len*/

var YAMLException = require('./exception');
var Type          = require('./type');


function compileList(schema, name) {
  var result = [];

  schema[name].forEach(function (currentType) {
    var newIndex = result.length;

    result.forEach(function (previousType, previousIndex) {
      if (previousType.tag === currentType.tag &&
          previousType.kind === currentType.kind &&
          previousType.multi === currentType.multi) {

        newIndex = previousIndex;
      }
    });

    result[newIndex] = currentType;
  });

  return result;
}


function compileMap(/* lists... */) {
  var result = {
        scalar: {},
        sequence: {},
        mapping: {},
        fallback: {},
        multi: {
          scalar: [],
          sequence: [],
          mapping: [],
          fallback: []
        }
      }, index, length;

  function collectType(type) {
    if (type.multi) {
      result.multi[type.kind].push(type);
      result.multi['fallback'].push(type);
    } else {
      result[type.kind][type.tag] = result['fallback'][type.tag] = type;
    }
  }

  for (index = 0, length = arguments.length; index < length; index += 1) {
    arguments[index].forEach(collectType);
  }
  return result;
}


function Schema(definition) {
  return this.extend(definition);
}


Schema.prototype.extend = function extend(definition) {
  var implicit = [];
  var explicit = [];

  if (definition instanceof Type) {
    // Schema.extend(type)
    explicit.push(definition);

  } else if (Array.isArray(definition)) {
    // Schema.extend([ type1, type2, ... ])
    explicit = explicit.concat(definition);

  } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) {
    // Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] })
    if (definition.implicit) implicit = implicit.concat(definition.implicit);
    if (definition.explicit) explicit = explicit.concat(definition.explicit);

  } else {
    throw new YAMLException('Schema.extend argument should be a Type, [ Type ], ' +
      'or a schema definition ({ implicit: [...], explicit: [...] })');
  }

  implicit.forEach(function (type) {
    if (!(type instanceof Type)) {
      throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.');
    }

    if (type.loadKind && type.loadKind !== 'scalar') {
      throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.');
    }

    if (type.multi) {
      throw new YAMLException('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.');
    }
  });

  explicit.forEach(function (type) {
    if (!(type instanceof Type)) {
      throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.');
    }
  });

  var result = Object.create(Schema.prototype);

  result.implicit = (this.implicit || []).concat(implicit);
  result.explicit = (this.explicit || []).concat(explicit);

  result.compiledImplicit = compileList(result, 'implicit');
  result.compiledExplicit = compileList(result, 'explicit');
  result.compiledTypeMap  = compileMap(result.compiledImplicit, result.compiledExplicit);

  return result;
};


module.exports = Schema;
// Standard YAML's Core schema.
// http://www.yaml.org/spec/1.2/spec.html#id2804923
//
// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.
// So, Core schema has no distinctions from JSON schema is JS-YAML.


'use strict';


module.exports = require('./json');
// JS-YAML's default schema for `safeLoad` function.
// It is not described in the YAML specification.
//
// This schema is based on standard YAML's Core schema and includes most of
// extra types described at YAML tag repository. (http://yaml.org/type/)


'use strict';


module.exports = require('./core').extend({
  implicit: [
    require('../type/timestamp'),
    require('../type/merge')
  ],
  explicit: [
    require('../type/binary'),
    require('../type/omap'),
    require('../type/pairs'),
    require('../type/set')
  ]
});
// Standard YAML's Failsafe schema.
// http://www.yaml.org/spec/1.2/spec.html#id2802346


'use strict';


var Schema = require('../schema');


module.exports = new Schema({
  explicit: [
    require('../type/str'),
    require('../type/seq'),
    require('../type/map')
  ]
});
// Standard YAML's JSON schema.
// http://www.yaml.org/spec/1.2/spec.html#id2803231
//
// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.
// So, this schema is not such strict as defined in the YAML specification.
// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc.


'use strict';


module.exports = require('./failsafe').extend({
  implicit: [
    require('../type/null'),
    require('../type/bool'),
    require('../type/int'),
    require('../type/float')
  ]
});
'use strict';


var common = require('./common');


// get snippet for a single line, respecting maxLength
function getLine(buffer, lineStart, lineEnd, position, maxLineLength) {
  var head = '';
  var tail = '';
  var maxHalfLength = Math.floor(maxLineLength / 2) - 1;

  if (position - lineStart > maxHalfLength) {
    head = ' ... ';
    lineStart = position - maxHalfLength + head.length;
  }

  if (lineEnd - position > maxHalfLength) {
    tail = ' ...';
    lineEnd = position + maxHalfLength - tail.length;
  }

  return {
    str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, '→') + tail,
    pos: position - lineStart + head.length // relative position
  };
}


function padStart(string, max) {
  return common.repeat(' ', max - string.length) + string;
}


function makeSnippet(mark, options) {
  options = Object.create(options || null);

  if (!mark.buffer) return null;

  if (!options.maxLength) options.maxLength = 79;
  if (typeof options.indent      !== 'number') options.indent      = 1;
  if (typeof options.linesBefore !== 'number') options.linesBefore = 3;
  if (typeof options.linesAfter  !== 'number') options.linesAfter  = 2;

  var re = /\r?\n|\r|\0/g;
  var lineStarts = [ 0 ];
  var lineEnds = [];
  var match;
  var foundLineNo = -1;

  while ((match = re.exec(mark.buffer))) {
    lineEnds.push(match.index);
    lineStarts.push(match.index + match[0].length);

    if (mark.position <= match.index && foundLineNo < 0) {
      foundLineNo = lineStarts.length - 2;
    }
  }

  if (foundLineNo < 0) foundLineNo = lineStarts.length - 1;

  var result = '', i, line;
  var lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length;
  var maxLineLength = options.maxLength - (options.indent + lineNoLength + 3);

  for (i = 1; i <= options.linesBefore; i++) {
    if (foundLineNo - i < 0) break;
    line = getLine(
      mark.buffer,
      lineStarts[foundLineNo - i],
      lineEnds[foundLineNo - i],
      mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),
      maxLineLength
    );
    result = common.repeat(' ', options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) +
      ' | ' + line.str + '\n' + result;
  }

  line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength);
  result += common.repeat(' ', options.indent) + padStart((mark.line + 1).toString(), lineNoLength) +
    ' | ' + line.str + '\n';
  result += common.repeat('-', options.indent + lineNoLength + 3 + line.pos) + '^' + '\n';

  for (i = 1; i <= options.linesAfter; i++) {
    if (foundLineNo + i >= lineEnds.length) break;
    line = getLine(
      mark.buffer,
      lineStarts[foundLineNo + i],
      lineEnds[foundLineNo + i],
      mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),
      maxLineLength
    );
    result += common.repeat(' ', options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) +
      ' | ' + line.str + '\n';
  }

  return result.replace(/\n$/, '');
}


module.exports = makeSnippet;
'use strict';

var YAMLException = require('./exception');

var TYPE_CONSTRUCTOR_OPTIONS = [
  'kind',
  'multi',
  'resolve',
  'construct',
  'instanceOf',
  'predicate',
  'represent',
  'representName',
  'defaultStyle',
  'styleAliases'
];

var YAML_NODE_KINDS = [
  'scalar',
  'sequence',
  'mapping'
];

function compileStyleAliases(map) {
  var result = {};

  if (map !== null) {
    Object.keys(map).forEach(function (style) {
      map[style].forEach(function (alias) {
        result[String(alias)] = style;
      });
    });
  }

  return result;
}

function Type(tag, options) {
  options = options || {};

  Object.keys(options).forEach(function (name) {
    if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {
      throw new YAMLException('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.');
    }
  });

  // TODO: Add tag format check.
  this.options       = options; // keep original options in case user wants to extend this type later
  this.tag           = tag;
  this.kind          = options['kind']          || null;
  this.resolve       = options['resolve']       || function () { return true; };
  this.construct     = options['construct']     || function (data) { return data; };
  this.instanceOf    = options['instanceOf']    || null;
  this.predicate     = options['predicate']     || null;
  this.represent     = options['represent']     || null;
  this.representName = options['representName'] || null;
  this.defaultStyle  = options['defaultStyle']  || null;
  this.multi         = options['multi']         || false;
  this.styleAliases  = compileStyleAliases(options['styleAliases'] || null);

  if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {
    throw new YAMLException('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.');
  }
}

module.exports = Type;
'use strict';

/*eslint-disable no-bitwise*/


var Type = require('../type');


// [ 64, 65, 66 ] -> [ padding, CR, LF ]
var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r';


function resolveYamlBinary(data) {
  if (data === null) return false;

  var code, idx, bitlen = 0, max = data.length, map = BASE64_MAP;

  // Convert one by one.
  for (idx = 0; idx < max; idx++) {
    code = map.indexOf(data.charAt(idx));

    // Skip CR/LF
    if (code > 64) continue;

    // Fail on illegal characters
    if (code < 0) return false;

    bitlen += 6;
  }

  // If there are any bits left, source was corrupted
  return (bitlen % 8) === 0;
}

function constructYamlBinary(data) {
  var idx, tailbits,
      input = data.replace(/[\r\n=]/g, ''), // remove CR/LF & padding to simplify scan
      max = input.length,
      map = BASE64_MAP,
      bits = 0,
      result = [];

  // Collect by 6*4 bits (3 bytes)

  for (idx = 0; idx < max; idx++) {
    if ((idx % 4 === 0) && idx) {
      result.push((bits >> 16) & 0xFF);
      result.push((bits >> 8) & 0xFF);
      result.push(bits & 0xFF);
    }

    bits = (bits << 6) | map.indexOf(input.charAt(idx));
  }

  // Dump tail

  tailbits = (max % 4) * 6;

  if (tailbits === 0) {
    result.push((bits >> 16) & 0xFF);
    result.push((bits >> 8) & 0xFF);
    result.push(bits & 0xFF);
  } else if (tailbits === 18) {
    result.push((bits >> 10) & 0xFF);
    result.push((bits >> 2) & 0xFF);
  } else if (tailbits === 12) {
    result.push((bits >> 4) & 0xFF);
  }

  return new Uint8Array(result);
}

function representYamlBinary(object /*, style*/) {
  var result = '', bits = 0, idx, tail,
      max = object.length,
      map = BASE64_MAP;

  // Convert every three bytes to 4 ASCII characters.

  for (idx = 0; idx < max; idx++) {
    if ((idx % 3 === 0) && idx) {
      result += map[(bits >> 18) & 0x3F];
      result += map[(bits >> 12) & 0x3F];
      result += map[(bits >> 6) & 0x3F];
      result += map[bits & 0x3F];
    }

    bits = (bits << 8) + object[idx];
  }

  // Dump tail

  tail = max % 3;

  if (tail === 0) {
    result += map[(bits >> 18) & 0x3F];
    result += map[(bits >> 12) & 0x3F];
    result += map[(bits >> 6) & 0x3F];
    result += map[bits & 0x3F];
  } else if (tail === 2) {
    result += map[(bits >> 10) & 0x3F];
    result += map[(bits >> 4) & 0x3F];
    result += map[(bits << 2) & 0x3F];
    result += map[64];
  } else if (tail === 1) {
    result += map[(bits >> 2) & 0x3F];
    result += map[(bits << 4) & 0x3F];
    result += map[64];
    result += map[64];
  }

  return result;
}

function isBinary(obj) {
  return Object.prototype.toString.call(obj) ===  '[object Uint8Array]';
}

module.exports = new Type('tag:yaml.org,2002:binary', {
  kind: 'scalar',
  resolve: resolveYamlBinary,
  construct: constructYamlBinary,
  predicate: isBinary,
  represent: representYamlBinary
});
'use strict';

var Type = require('../type');

function resolveYamlBoolean(data) {
  if (data === null) return false;

  var max = data.length;

  return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||
         (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'));
}

function constructYamlBoolean(data) {
  return data === 'true' ||
         data === 'True' ||
         data === 'TRUE';
}

function isBoolean(object) {
  return Object.prototype.toString.call(object) === '[object Boolean]';
}

module.exports = new Type('tag:yaml.org,2002:bool', {
  kind: 'scalar',
  resolve: resolveYamlBoolean,
  construct: constructYamlBoolean,
  predicate: isBoolean,
  represent: {
    lowercase: function (object) { return object ? 'true' : 'false'; },
    uppercase: function (object) { return object ? 'TRUE' : 'FALSE'; },
    camelcase: function (object) { return object ? 'True' : 'False'; }
  },
  defaultStyle: 'lowercase'
});
'use strict';

var common = require('../common');
var Type   = require('../type');

var YAML_FLOAT_PATTERN = new RegExp(
  // 2.5e4, 2.5 and integers
  '^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?' +
  // .2e4, .2
  // special case, seems not from spec
  '|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?' +
  // .inf
  '|[-+]?\\.(?:inf|Inf|INF)' +
  // .nan
  '|\\.(?:nan|NaN|NAN))$');

function resolveYamlFloat(data) {
  if (data === null) return false;

  if (!YAML_FLOAT_PATTERN.test(data) ||
      // Quick hack to not allow integers end with `_`
      // Probably should update regexp & check speed
      data[data.length - 1] === '_') {
    return false;
  }

  return true;
}

function constructYamlFloat(data) {
  var value, sign;

  value  = data.replace(/_/g, '').toLowerCase();
  sign   = value[0] === '-' ? -1 : 1;

  if ('+-'.indexOf(value[0]) >= 0) {
    value = value.slice(1);
  }

  if (value === '.inf') {
    return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;

  } else if (value === '.nan') {
    return NaN;
  }
  return sign * parseFloat(value, 10);
}


var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;

function representYamlFloat(object, style) {
  var res;

  if (isNaN(object)) {
    switch (style) {
      case 'lowercase': return '.nan';
      case 'uppercase': return '.NAN';
      case 'camelcase': return '.NaN';
    }
  } else if (Number.POSITIVE_INFINITY === object) {
    switch (style) {
      case 'lowercase': return '.inf';
      case 'uppercase': return '.INF';
      case 'camelcase': return '.Inf';
    }
  } else if (Number.NEGATIVE_INFINITY === object) {
    switch (style) {
      case 'lowercase': return '-.inf';
      case 'uppercase': return '-.INF';
      case 'camelcase': return '-.Inf';
    }
  } else if (common.isNegativeZero(object)) {
    return '-0.0';
  }

  res = object.toString(10);

  // JS stringifier can build scientific format without dots: 5e-100,
  // while YAML requres dot: 5.e-100. Fix it with simple hack

  return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res;
}

function isFloat(object) {
  return (Object.prototype.toString.call(object) === '[object Number]') &&
         (object % 1 !== 0 || common.isNegativeZero(object));
}

module.exports = new Type('tag:yaml.org,2002:float', {
  kind: 'scalar',
  resolve: resolveYamlFloat,
  construct: constructYamlFloat,
  predicate: isFloat,
  represent: representYamlFloat,
  defaultStyle: 'lowercase'
});
'use strict';

var common = require('../common');
var Type   = require('../type');

function isHexCode(c) {
  return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) ||
         ((0x41/* A */ <= c) && (c <= 0x46/* F */)) ||
         ((0x61/* a */ <= c) && (c <= 0x66/* f */));
}

function isOctCode(c) {
  return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */));
}

function isDecCode(c) {
  return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */));
}

function resolveYamlInteger(data) {
  if (data === null) return false;

  var max = data.length,
      index = 0,
      hasDigits = false,
      ch;

  if (!max) return false;

  ch = data[index];

  // sign
  if (ch === '-' || ch === '+') {
    ch = data[++index];
  }

  if (ch === '0') {
    // 0
    if (index + 1 === max) return true;
    ch = data[++index];

    // base 2, base 8, base 16

    if (ch === 'b') {
      // base 2
      index++;

      for (; index < max; index++) {
        ch = data[index];
        if (ch === '_') continue;
        if (ch !== '0' && ch !== '1') return false;
        hasDigits = true;
      }
      return hasDigits && ch !== '_';
    }


    if (ch === 'x') {
      // base 16
      index++;

      for (; index < max; index++) {
        ch = data[index];
        if (ch === '_') continue;
        if (!isHexCode(data.charCodeAt(index))) return false;
        hasDigits = true;
      }
      return hasDigits && ch !== '_';
    }


    if (ch === 'o') {
      // base 8
      index++;

      for (; index < max; index++) {
        ch = data[index];
        if (ch === '_') continue;
        if (!isOctCode(data.charCodeAt(index))) return false;
        hasDigits = true;
      }
      return hasDigits && ch !== '_';
    }
  }

  // base 10 (except 0)

  // value should not start with `_`;
  if (ch === '_') return false;

  for (; index < max; index++) {
    ch = data[index];
    if (ch === '_') continue;
    if (!isDecCode(data.charCodeAt(index))) {
      return false;
    }
    hasDigits = true;
  }

  // Should have digits and should not end with `_`
  if (!hasDigits || ch === '_') return false;

  return true;
}

function constructYamlInteger(data) {
  var value = data, sign = 1, ch;

  if (value.indexOf('_') !== -1) {
    value = value.replace(/_/g, '');
  }

  ch = value[0];

  if (ch === '-' || ch === '+') {
    if (ch === '-') sign = -1;
    value = value.slice(1);
    ch = value[0];
  }

  if (value === '0') return 0;

  if (ch === '0') {
    if (value[1] === 'b') return sign * parseInt(value.slice(2), 2);
    if (value[1] === 'x') return sign * parseInt(value.slice(2), 16);
    if (value[1] === 'o') return sign * parseInt(value.slice(2), 8);
  }

  return sign * parseInt(value, 10);
}

function isInteger(object) {
  return (Object.prototype.toString.call(object)) === '[object Number]' &&
         (object % 1 === 0 && !common.isNegativeZero(object));
}

module.exports = new Type('tag:yaml.org,2002:int', {
  kind: 'scalar',
  resolve: resolveYamlInteger,
  construct: constructYamlInteger,
  predicate: isInteger,
  represent: {
    binary:      function (obj) { return obj >= 0 ? '0b' + obj.toString(2) : '-0b' + obj.toString(2).slice(1); },
    octal:       function (obj) { return obj >= 0 ? '0o'  + obj.toString(8) : '-0o'  + obj.toString(8).slice(1); },
    decimal:     function (obj) { return obj.toString(10); },
    /* eslint-disable max-len */
    hexadecimal: function (obj) { return obj >= 0 ? '0x' + obj.toString(16).toUpperCase() :  '-0x' + obj.toString(16).toUpperCase().slice(1); }
  },
  defaultStyle: 'decimal',
  styleAliases: {
    binary:      [ 2,  'bin' ],
    octal:       [ 8,  'oct' ],
    decimal:     [ 10, 'dec' ],
    hexadecimal: [ 16, 'hex' ]
  }
});
'use strict';

var Type = require('../type');

module.exports = new Type('tag:yaml.org,2002:map', {
  kind: 'mapping',
  construct: function (data) { return data !== null ? data : {}; }
});
'use strict';

var Type = require('../type');

function resolveYamlMerge(data) {
  return data === '<<' || data === null;
}

module.exports = new Type('tag:yaml.org,2002:merge', {
  kind: 'scalar',
  resolve: resolveYamlMerge
});
'use strict';

var Type = require('../type');

function resolveYamlNull(data) {
  if (data === null) return true;

  var max = data.length;

  return (max === 1 && data === '~') ||
         (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'));
}

function constructYamlNull() {
  return null;
}

function isNull(object) {
  return object === null;
}

module.exports = new Type('tag:yaml.org,2002:null', {
  kind: 'scalar',
  resolve: resolveYamlNull,
  construct: constructYamlNull,
  predicate: isNull,
  represent: {
    canonical: function () { return '~';    },
    lowercase: function () { return 'null'; },
    uppercase: function () { return 'NULL'; },
    camelcase: function () { return 'Null'; },
    empty:     function () { return '';     }
  },
  defaultStyle: 'lowercase'
});
'use strict';

var Type = require('../type');

var _hasOwnProperty = Object.prototype.hasOwnProperty;
var _toString       = Object.prototype.toString;

function resolveYamlOmap(data) {
  if (data === null) return true;

  var objectKeys = [], index, length, pair, pairKey, pairHasKey,
      object = data;

  for (index = 0, length = object.length; index < length; index += 1) {
    pair = object[index];
    pairHasKey = false;

    if (_toString.call(pair) !== '[object Object]') return false;

    for (pairKey in pair) {
      if (_hasOwnProperty.call(pair, pairKey)) {
        if (!pairHasKey) pairHasKey = true;
        else return false;
      }
    }

    if (!pairHasKey) return false;

    if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey);
    else return false;
  }

  return true;
}

function constructYamlOmap(data) {
  return data !== null ? data : [];
}

module.exports = new Type('tag:yaml.org,2002:omap', {
  kind: 'sequence',
  resolve: resolveYamlOmap,
  construct: constructYamlOmap
});
'use strict';

var Type = require('../type');

var _toString = Object.prototype.toString;

function resolveYamlPairs(data) {
  if (data === null) return true;

  var index, length, pair, keys, result,
      object = data;

  result = new Array(object.length);

  for (index = 0, length = object.length; index < length; index += 1) {
    pair = object[index];

    if (_toString.call(pair) !== '[object Object]') return false;

    keys = Object.keys(pair);

    if (keys.length !== 1) return false;

    result[index] = [ keys[0], pair[keys[0]] ];
  }

  return true;
}

function constructYamlPairs(data) {
  if (data === null) return [];

  var index, length, pair, keys, result,
      object = data;

  result = new Array(object.length);

  for (index = 0, length = object.length; index < length; index += 1) {
    pair = object[index];

    keys = Object.keys(pair);

    result[index] = [ keys[0], pair[keys[0]] ];
  }

  return result;
}

module.exports = new Type('tag:yaml.org,2002:pairs', {
  kind: 'sequence',
  resolve: resolveYamlPairs,
  construct: constructYamlPairs
});
'use strict';

var Type = require('../type');

module.exports = new Type('tag:yaml.org,2002:seq', {
  kind: 'sequence',
  construct: function (data) { return data !== null ? data : []; }
});
'use strict';

var Type = require('../type');

var _hasOwnProperty = Object.prototype.hasOwnProperty;

function resolveYamlSet(data) {
  if (data === null) return true;

  var key, object = data;

  for (key in object) {
    if (_hasOwnProperty.call(object, key)) {
      if (object[key] !== null) return false;
    }
  }

  return true;
}

function constructYamlSet(data) {
  return data !== null ? data : {};
}

module.exports = new Type('tag:yaml.org,2002:set', {
  kind: 'mapping',
  resolve: resolveYamlSet,
  construct: constructYamlSet
});
'use strict';

var Type = require('../type');

module.exports = new Type('tag:yaml.org,2002:str', {
  kind: 'scalar',
  construct: function (data) { return data !== null ? data : ''; }
});
'use strict';

var Type = require('../type');

var YAML_DATE_REGEXP = new RegExp(
  '^([0-9][0-9][0-9][0-9])'          + // [1] year
  '-([0-9][0-9])'                    + // [2] month
  '-([0-9][0-9])$');                   // [3] day

var YAML_TIMESTAMP_REGEXP = new RegExp(
  '^([0-9][0-9][0-9][0-9])'          + // [1] year
  '-([0-9][0-9]?)'                   + // [2] month
  '-([0-9][0-9]?)'                   + // [3] day
  '(?:[Tt]|[ \\t]+)'                 + // ...
  '([0-9][0-9]?)'                    + // [4] hour
  ':([0-9][0-9])'                    + // [5] minute
  ':([0-9][0-9])'                    + // [6] second
  '(?:\\.([0-9]*))?'                 + // [7] fraction
  '(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tz_hour
  '(?::([0-9][0-9]))?))?$');           // [11] tz_minute

function resolveYamlTimestamp(data) {
  if (data === null) return false;
  if (YAML_DATE_REGEXP.exec(data) !== null) return true;
  if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;
  return false;
}

function constructYamlTimestamp(data) {
  var match, year, month, day, hour, minute, second, fraction = 0,
      delta = null, tz_hour, tz_minute, date;

  match = YAML_DATE_REGEXP.exec(data);
  if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);

  if (match === null) throw new Error('Date resolve error');

  // match: [1] year [2] month [3] day

  year = +(match[1]);
  month = +(match[2]) - 1; // JS month starts with 0
  day = +(match[3]);

  if (!match[4]) { // no hour
    return new Date(Date.UTC(year, month, day));
  }

  // match: [4] hour [5] minute [6] second [7] fraction

  hour = +(match[4]);
  minute = +(match[5]);
  second = +(match[6]);

  if (match[7]) {
    fraction = match[7].slice(0, 3);
    while (fraction.length < 3) { // milli-seconds
      fraction += '0';
    }
    fraction = +fraction;
  }

  // match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute

  if (match[9]) {
    tz_hour = +(match[10]);
    tz_minute = +(match[11] || 0);
    delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds
    if (match[9] === '-') delta = -delta;
  }

  date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction));

  if (delta) date.setTime(date.getTime() - delta);

  return date;
}

function representYamlTimestamp(object /*, style*/) {
  return object.toISOString();
}

module.exports = new Type('tag:yaml.org,2002:timestamp', {
  kind: 'scalar',
  resolve: resolveYamlTimestamp,
  construct: constructYamlTimestamp,
  instanceOf: Date,
  represent: representYamlTimestamp
});
{
  "name": "js-yaml",
  "version": "4.1.0",
  "description": "YAML 1.2 parser and serializer",
  "author": "Vladimir Zapparov <dervus.grim@gmail.com>",
  "license": "MIT",
  "repository": "nodeca/js-yaml",
  "files": [
    "index.js",
    "lib/",
    "bin/",
    "dist/"
  ],
  "bin": {
    "js-yaml": "bin/js-yaml.js"
  },
  "module": "./dist/js-yaml.mjs",
  "exports": {
    ".": {
      "import": "./dist/js-yaml.mjs",
      "require": "./index.js"
    },
    "./package.json": "./package.json"
  },
  "unpkg": "dist/js-yaml.min.js",
  "jsdelivr": "dist/js-yaml.min.js",
  "dependencies": {
    "argparse": "^2.0.1"
  },
  "devDependencies": {
    "@rollup/plugin-commonjs": "^17.0.0",
    "@rollup/plugin-node-resolve": "^11.0.0",
    "ansi": "^0.3.1",
    "benchmark": "^2.1.4",
    "codemirror": "^5.13.4",
    "eslint": "^7.0.0",
    "fast-check": "^2.8.0",
    "gh-pages": "^3.1.0",
    "mocha": "^8.2.1",
    "nyc": "^15.1.0",
    "rollup": "^2.34.1",
    "rollup-plugin-node-polyfills": "^0.2.1",
    "rollup-plugin-terser": "^7.0.2",
    "shelljs": "^0.8.4"
  }
}"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Lazy = void 0;
class Lazy {
    constructor(creator) {
        this._value = null;
        this.creator = creator;
    }
    get hasValue() {
        return this.creator == null;
    }
    get value() {
        if (this.creator == null) {
            return this._value;
        }
        const result = this.creator();
        this.value = result;
        return result;
    }
    set value(value) {
        this._value = value;
        this.creator = null;
    }
}
exports.Lazy = Lazy;
//# sourceMappingURL=main.js.map{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;;AAAA,MAAa,IAAI;IAIf,YAAY,OAAyB;QAH7B,WAAM,GAAsB,IAAI,CAAA;QAItC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAA;IAC7B,CAAC;IAED,IAAI,KAAK;QACP,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,EAAE;YACxB,OAAO,IAAI,CAAC,MAAQ,CAAA;SACrB;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAA;QAC7B,IAAI,CAAC,KAAK,GAAG,MAAM,CAAA;QACnB,OAAO,MAAM,CAAA;IACf,CAAC;IAED,IAAI,KAAK,CAAC,KAAiB;QACzB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;IACrB,CAAC;CACF;AA1BD,oBA0BC","sourcesContent":["export class Lazy<T> {\n  private _value: Promise<T> | null = null\n  private creator: (() => Promise<T>) | null\n\n  constructor(creator: () => Promise<T>) {\n    this.creator = creator\n  }\n\n  get hasValue() {\n    return this.creator == null\n  }\n\n  get value(): Promise<T> {\n    if (this.creator == null) {\n      return this._value!!\n    }\n\n    const result = this.creator()\n    this.value = result\n    return result\n  }\n\n  set value(value: Promise<T>) {\n    this._value = value\n    this.creator = null\n  }\n}"]}{
  "name": "lazy-val",
  "version": "1.0.5",
  "main": "out/main.js",
  "author": "Vladimir Krivosheev",
  "license": "MIT",
  "repository": "develar/lazy-val",
  "homepage": "https://github.com/develar/lazy-val",
  "files": [
    "out"
  ],
  "devDependencies": {
    "typescript": "^4.2.4"
  },
  "typings": "./out/main.d.ts"
}Copyright jQuery Foundation and other contributors <https://jquery.org/>

Based on Underscore.js, copyright Jeremy Ashkenas,
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>

This software consists of voluntary contributions made by many
individuals. For exact contribution history, see the revision history
available at https://github.com/lodash/lodash

The following license applies to all parts of this software except as
documented below:

====

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

====

Copyright and related rights for sample code are waived via CC0. Sample
code is defined as all source code displayed within the prose of the
documentation.

CC0: http://creativecommons.org/publicdomain/zero/1.0/

====

Files located in the node_modules and vendor directories are externally
maintained libraries used by this software which have their own
licenses; we recommend you read them, as their terms may differ from the
terms above.
/**
 * lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright jQuery Foundation and other contributors <https://jquery.org/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as references for various `Number` constants. */
var INFINITY = 1 / 0;

/** `Object#toString` result references. */
var symbolTag = '[object Symbol]';

/**
 * Used to match `RegExp`
 * [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns).
 */
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
    reHasRegExpChar = RegExp(reRegExpChar.source);

/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();

/** Used for built-in method references. */
var objectProto = Object.prototype;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
 * of values.
 */
var objectToString = objectProto.toString;

/** Built-in value references. */
var Symbol = root.Symbol;

/** Used to convert symbols to primitives and strings. */
var symbolProto = Symbol ? Symbol.prototype : undefined,
    symbolToString = symbolProto ? symbolProto.toString : undefined;

/**
 * The base implementation of `_.toString` which doesn't convert nullish
 * values to empty strings.
 *
 * @private
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 */
function baseToString(value) {
  // Exit early for strings to avoid a performance hit in some environments.
  if (typeof value == 'string') {
    return value;
  }
  if (isSymbol(value)) {
    return symbolToString ? symbolToString.call(value) : '';
  }
  var result = (value + '');
  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return !!value && typeof value == 'object';
}

/**
 * Checks if `value` is classified as a `Symbol` primitive or object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
 * @example
 *
 * _.isSymbol(Symbol.iterator);
 * // => true
 *
 * _.isSymbol('abc');
 * // => false
 */
function isSymbol(value) {
  return typeof value == 'symbol' ||
    (isObjectLike(value) && objectToString.call(value) == symbolTag);
}

/**
 * Converts `value` to a string. An empty string is returned for `null`
 * and `undefined` values. The sign of `-0` is preserved.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 * @example
 *
 * _.toString(null);
 * // => ''
 *
 * _.toString(-0);
 * // => '-0'
 *
 * _.toString([1, 2, 3]);
 * // => '1,2,3'
 */
function toString(value) {
  return value == null ? '' : baseToString(value);
}

/**
 * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
 * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category String
 * @param {string} [string=''] The string to escape.
 * @returns {string} Returns the escaped string.
 * @example
 *
 * _.escapeRegExp('[lodash](https://lodash.com/)');
 * // => '\[lodash\]\(https://lodash\.com/\)'
 */
function escapeRegExp(string) {
  string = toString(string);
  return (string && reHasRegExpChar.test(string))
    ? string.replace(reRegExpChar, '\\$&')
    : string;
}

module.exports = escapeRegExp;
{
  "name": "lodash.escaperegexp",
  "version": "4.1.2",
  "description": "The lodash method `_.escapeRegExp` exported as a module.",
  "homepage": "https://lodash.com/",
  "icon": "https://lodash.com/icon.svg",
  "license": "MIT",
  "author": "John-David Dalton <john.david.dalton@gmail.com> (http://allyoucanleet.com/)",
  "repository": "lodash/lodash"
}Copyright JS Foundation and other contributors <https://js.foundation/>

Based on Underscore.js, copyright Jeremy Ashkenas,
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>

This software consists of voluntary contributions made by many
individuals. For exact contribution history, see the revision history
available at https://github.com/lodash/lodash

The following license applies to all parts of this software except as
documented below:

====

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

====

Copyright and related rights for sample code are waived via CC0. Sample
code is defined as all source code displayed within the prose of the
documentation.

CC0: http://creativecommons.org/publicdomain/zero/1.0/

====

Files located in the node_modules and vendor directories are externally
maintained libraries used by this software which have their own
licenses; we recommend you read them, as their terms may differ from the
terms above.
/**
 * Lodash (Custom Build) <https://lodash.com/>
 * Build: `lodash modularize exports="npm" -o ./`
 * Copyright JS Foundation and other contributors <https://js.foundation/>
 * Released under MIT license <https://lodash.com/license>
 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 */

/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;

/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/** Used to compose bitmasks for value comparisons. */
var COMPARE_PARTIAL_FLAG = 1,
    COMPARE_UNORDERED_FLAG = 2;

/** Used as references for various `Number` constants. */
var MAX_SAFE_INTEGER = 9007199254740991;

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    arrayTag = '[object Array]',
    asyncTag = '[object AsyncFunction]',
    boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    errorTag = '[object Error]',
    funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]',
    mapTag = '[object Map]',
    numberTag = '[object Number]',
    nullTag = '[object Null]',
    objectTag = '[object Object]',
    promiseTag = '[object Promise]',
    proxyTag = '[object Proxy]',
    regexpTag = '[object RegExp]',
    setTag = '[object Set]',
    stringTag = '[object String]',
    symbolTag = '[object Symbol]',
    undefinedTag = '[object Undefined]',
    weakMapTag = '[object WeakMap]';

var arrayBufferTag = '[object ArrayBuffer]',
    dataViewTag = '[object DataView]',
    float32Tag = '[object Float32Array]',
    float64Tag = '[object Float64Array]',
    int8Tag = '[object Int8Array]',
    int16Tag = '[object Int16Array]',
    int32Tag = '[object Int32Array]',
    uint8Tag = '[object Uint8Array]',
    uint8ClampedTag = '[object Uint8ClampedArray]',
    uint16Tag = '[object Uint16Array]',
    uint32Tag = '[object Uint32Array]';

/**
 * Used to match `RegExp`
 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
 */
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;

/** Used to detect host constructors (Safari). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;

/** Used to detect unsigned integer values. */
var reIsUint = /^(?:0|[1-9]\d*)$/;

/** Used to identify `toStringTag` values of typed arrays. */
var typedArrayTags = {};
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
typedArrayTags[uint32Tag] = true;
typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
typedArrayTags[errorTag] = typedArrayTags[funcTag] =
typedArrayTags[mapTag] = typedArrayTags[numberTag] =
typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
typedArrayTags[setTag] = typedArrayTags[stringTag] =
typedArrayTags[weakMapTag] = false;

/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();

/** Detect free variable `exports`. */
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

/** Detect free variable `module`. */
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;

/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;

/** Detect free variable `process` from Node.js. */
var freeProcess = moduleExports && freeGlobal.process;

/** Used to access faster Node.js helpers. */
var nodeUtil = (function() {
  try {
    return freeProcess && freeProcess.binding && freeProcess.binding('util');
  } catch (e) {}
}());

/* Node.js helper references. */
var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;

/**
 * A specialized version of `_.filter` for arrays without support for
 * iteratee shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {Array} Returns the new filtered array.
 */
function arrayFilter(array, predicate) {
  var index = -1,
      length = array == null ? 0 : array.length,
      resIndex = 0,
      result = [];

  while (++index < length) {
    var value = array[index];
    if (predicate(value, index, array)) {
      result[resIndex++] = value;
    }
  }
  return result;
}

/**
 * Appends the elements of `values` to `array`.
 *
 * @private
 * @param {Array} array The array to modify.
 * @param {Array} values The values to append.
 * @returns {Array} Returns `array`.
 */
function arrayPush(array, values) {
  var index = -1,
      length = values.length,
      offset = array.length;

  while (++index < length) {
    array[offset + index] = values[index];
  }
  return array;
}

/**
 * A specialized version of `_.some` for arrays without support for iteratee
 * shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {boolean} Returns `true` if any element passes the predicate check,
 *  else `false`.
 */
function arraySome(array, predicate) {
  var index = -1,
      length = array == null ? 0 : array.length;

  while (++index < length) {
    if (predicate(array[index], index, array)) {
      return true;
    }
  }
  return false;
}

/**
 * The base implementation of `_.times` without support for iteratee shorthands
 * or max array length checks.
 *
 * @private
 * @param {number} n The number of times to invoke `iteratee`.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the array of results.
 */
function baseTimes(n, iteratee) {
  var index = -1,
      result = Array(n);

  while (++index < n) {
    result[index] = iteratee(index);
  }
  return result;
}

/**
 * The base implementation of `_.unary` without support for storing metadata.
 *
 * @private
 * @param {Function} func The function to cap arguments for.
 * @returns {Function} Returns the new capped function.
 */
function baseUnary(func) {
  return function(value) {
    return func(value);
  };
}

/**
 * Checks if a `cache` value for `key` exists.
 *
 * @private
 * @param {Object} cache The cache to query.
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function cacheHas(cache, key) {
  return cache.has(key);
}

/**
 * Gets the value at `key` of `object`.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {string} key The key of the property to get.
 * @returns {*} Returns the property value.
 */
function getValue(object, key) {
  return object == null ? undefined : object[key];
}

/**
 * Converts `map` to its key-value pairs.
 *
 * @private
 * @param {Object} map The map to convert.
 * @returns {Array} Returns the key-value pairs.
 */
function mapToArray(map) {
  var index = -1,
      result = Array(map.size);

  map.forEach(function(value, key) {
    result[++index] = [key, value];
  });
  return result;
}

/**
 * Creates a unary function that invokes `func` with its argument transformed.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {Function} transform The argument transform.
 * @returns {Function} Returns the new function.
 */
function overArg(func, transform) {
  return function(arg) {
    return func(transform(arg));
  };
}

/**
 * Converts `set` to an array of its values.
 *
 * @private
 * @param {Object} set The set to convert.
 * @returns {Array} Returns the values.
 */
function setToArray(set) {
  var index = -1,
      result = Array(set.size);

  set.forEach(function(value) {
    result[++index] = value;
  });
  return result;
}

/** Used for built-in method references. */
var arrayProto = Array.prototype,
    funcProto = Function.prototype,
    objectProto = Object.prototype;

/** Used to detect overreaching core-js shims. */
var coreJsData = root['__core-js_shared__'];

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/** Used to detect methods masquerading as native. */
var maskSrcKey = (function() {
  var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
  return uid ? ('Symbol(src)_1.' + uid) : '';
}());

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var nativeObjectToString = objectProto.toString;

/** Used to detect if a method is native. */
var reIsNative = RegExp('^' +
  funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);

/** Built-in value references. */
var Buffer = moduleExports ? root.Buffer : undefined,
    Symbol = root.Symbol,
    Uint8Array = root.Uint8Array,
    propertyIsEnumerable = objectProto.propertyIsEnumerable,
    splice = arrayProto.splice,
    symToStringTag = Symbol ? Symbol.toStringTag : undefined;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeGetSymbols = Object.getOwnPropertySymbols,
    nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
    nativeKeys = overArg(Object.keys, Object);

/* Built-in method references that are verified to be native. */
var DataView = getNative(root, 'DataView'),
    Map = getNative(root, 'Map'),
    Promise = getNative(root, 'Promise'),
    Set = getNative(root, 'Set'),
    WeakMap = getNative(root, 'WeakMap'),
    nativeCreate = getNative(Object, 'create');

/** Used to detect maps, sets, and weakmaps. */
var dataViewCtorString = toSource(DataView),
    mapCtorString = toSource(Map),
    promiseCtorString = toSource(Promise),
    setCtorString = toSource(Set),
    weakMapCtorString = toSource(WeakMap);

/** Used to convert symbols to primitives and strings. */
var symbolProto = Symbol ? Symbol.prototype : undefined,
    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;

/**
 * Creates a hash object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Hash(entries) {
  var index = -1,
      length = entries == null ? 0 : entries.length;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the hash.
 *
 * @private
 * @name clear
 * @memberOf Hash
 */
function hashClear() {
  this.__data__ = nativeCreate ? nativeCreate(null) : {};
  this.size = 0;
}

/**
 * Removes `key` and its value from the hash.
 *
 * @private
 * @name delete
 * @memberOf Hash
 * @param {Object} hash The hash to modify.
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function hashDelete(key) {
  var result = this.has(key) && delete this.__data__[key];
  this.size -= result ? 1 : 0;
  return result;
}

/**
 * Gets the hash value for `key`.
 *
 * @private
 * @name get
 * @memberOf Hash
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function hashGet(key) {
  var data = this.__data__;
  if (nativeCreate) {
    var result = data[key];
    return result === HASH_UNDEFINED ? undefined : result;
  }
  return hasOwnProperty.call(data, key) ? data[key] : undefined;
}

/**
 * Checks if a hash value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Hash
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function hashHas(key) {
  var data = this.__data__;
  return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
}

/**
 * Sets the hash `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Hash
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the hash instance.
 */
function hashSet(key, value) {
  var data = this.__data__;
  this.size += this.has(key) ? 0 : 1;
  data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
  return this;
}

// Add methods to `Hash`.
Hash.prototype.clear = hashClear;
Hash.prototype['delete'] = hashDelete;
Hash.prototype.get = hashGet;
Hash.prototype.has = hashHas;
Hash.prototype.set = hashSet;

/**
 * Creates an list cache object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function ListCache(entries) {
  var index = -1,
      length = entries == null ? 0 : entries.length;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the list cache.
 *
 * @private
 * @name clear
 * @memberOf ListCache
 */
function listCacheClear() {
  this.__data__ = [];
  this.size = 0;
}

/**
 * Removes `key` and its value from the list cache.
 *
 * @private
 * @name delete
 * @memberOf ListCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function listCacheDelete(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    return false;
  }
  var lastIndex = data.length - 1;
  if (index == lastIndex) {
    data.pop();
  } else {
    splice.call(data, index, 1);
  }
  --this.size;
  return true;
}

/**
 * Gets the list cache value for `key`.
 *
 * @private
 * @name get
 * @memberOf ListCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function listCacheGet(key) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  return index < 0 ? undefined : data[index][1];
}

/**
 * Checks if a list cache value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf ListCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function listCacheHas(key) {
  return assocIndexOf(this.__data__, key) > -1;
}

/**
 * Sets the list cache `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf ListCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the list cache instance.
 */
function listCacheSet(key, value) {
  var data = this.__data__,
      index = assocIndexOf(data, key);

  if (index < 0) {
    ++this.size;
    data.push([key, value]);
  } else {
    data[index][1] = value;
  }
  return this;
}

// Add methods to `ListCache`.
ListCache.prototype.clear = listCacheClear;
ListCache.prototype['delete'] = listCacheDelete;
ListCache.prototype.get = listCacheGet;
ListCache.prototype.has = listCacheHas;
ListCache.prototype.set = listCacheSet;

/**
 * Creates a map cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function MapCache(entries) {
  var index = -1,
      length = entries == null ? 0 : entries.length;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

/**
 * Removes all key-value entries from the map.
 *
 * @private
 * @name clear
 * @memberOf MapCache
 */
function mapCacheClear() {
  this.size = 0;
  this.__data__ = {
    'hash': new Hash,
    'map': new (Map || ListCache),
    'string': new Hash
  };
}

/**
 * Removes `key` and its value from the map.
 *
 * @private
 * @name delete
 * @memberOf MapCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function mapCacheDelete(key) {
  var result = getMapData(this, key)['delete'](key);
  this.size -= result ? 1 : 0;
  return result;
}

/**
 * Gets the map value for `key`.
 *
 * @private
 * @name get
 * @memberOf MapCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function mapCacheGet(key) {
  return getMapData(this, key).get(key);
}

/**
 * Checks if a map value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf MapCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function mapCacheHas(key) {
  return getMapData(this, key).has(key);
}

/**
 * Sets the map `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf MapCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the map cache instance.
 */
function mapCacheSet(key, value) {
  var data = getMapData(this, key),
      size = data.size;

  data.set(key, value);
  this.size += data.size == size ? 0 : 1;
  return this;
}

// Add methods to `MapCache`.
MapCache.prototype.clear = mapCacheClear;
MapCache.prototype['delete'] = mapCacheDelete;
MapCache.prototype.get = mapCacheGet;
MapCache.prototype.has = mapCacheHas;
MapCache.prototype.set = mapCacheSet;

/**
 *
 * Creates an array cache object to store unique values.
 *
 * @private
 * @constructor
 * @param {Array} [values] The values to cache.
 */
function SetCache(values) {
  var index = -1,
      length = values == null ? 0 : values.length;

  this.__data__ = new MapCache;
  while (++index < length) {
    this.add(values[index]);
  }
}

/**
 * Adds `value` to the array cache.
 *
 * @private
 * @name add
 * @memberOf SetCache
 * @alias push
 * @param {*} value The value to cache.
 * @returns {Object} Returns the cache instance.
 */
function setCacheAdd(value) {
  this.__data__.set(value, HASH_UNDEFINED);
  return this;
}

/**
 * Checks if `value` is in the array cache.
 *
 * @private
 * @name has
 * @memberOf SetCache
 * @param {*} value The value to search for.
 * @returns {number} Returns `true` if `value` is found, else `false`.
 */
function setCacheHas(value) {
  return this.__data__.has(value);
}

// Add methods to `SetCache`.
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
SetCache.prototype.has = setCacheHas;

/**
 * Creates a stack cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Stack(entries) {
  var data = this.__data__ = new ListCache(entries);
  this.size = data.size;
}

/**
 * Removes all key-value entries from the stack.
 *
 * @private
 * @name clear
 * @memberOf Stack
 */
function stackClear() {
  this.__data__ = new ListCache;
  this.size = 0;
}

/**
 * Removes `key` and its value from the stack.
 *
 * @private
 * @name delete
 * @memberOf Stack
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function stackDelete(key) {
  var data = this.__data__,
      result = data['delete'](key);

  this.size = data.size;
  return result;
}

/**
 * Gets the stack value for `key`.
 *
 * @private
 * @name get
 * @memberOf Stack
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function stackGet(key) {
  return this.__data__.get(key);
}

/**
 * Checks if a stack value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Stack
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function stackHas(key) {
  return this.__data__.has(key);
}

/**
 * Sets the stack `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Stack
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the stack cache instance.
 */
function stackSet(key, value) {
  var data = this.__data__;
  if (data instanceof ListCache) {
    var pairs = data.__data__;
    if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
      pairs.push([key, value]);
      this.size = ++data.size;
      return this;
    }
    data = this.__data__ = new MapCache(pairs);
  }
  data.set(key, value);
  this.size = data.size;
  return this;
}

// Add methods to `Stack`.
Stack.prototype.clear = stackClear;
Stack.prototype['delete'] = stackDelete;
Stack.prototype.get = stackGet;
Stack.prototype.has = stackHas;
Stack.prototype.set = stackSet;

/**
 * Creates an array of the enumerable property names of the array-like `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @param {boolean} inherited Specify returning inherited property names.
 * @returns {Array} Returns the array of property names.
 */
function arrayLikeKeys(value, inherited) {
  var isArr = isArray(value),
      isArg = !isArr && isArguments(value),
      isBuff = !isArr && !isArg && isBuffer(value),
      isType = !isArr && !isArg && !isBuff && isTypedArray(value),
      skipIndexes = isArr || isArg || isBuff || isType,
      result = skipIndexes ? baseTimes(value.length, String) : [],
      length = result.length;

  for (var key in value) {
    if ((inherited || hasOwnProperty.call(value, key)) &&
        !(skipIndexes && (
           // Safari 9 has enumerable `arguments.length` in strict mode.
           key == 'length' ||
           // Node.js 0.10 has enumerable non-index properties on buffers.
           (isBuff && (key == 'offset' || key == 'parent')) ||
           // PhantomJS 2 has enumerable non-index properties on typed arrays.
           (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
           // Skip index properties.
           isIndex(key, length)
        ))) {
      result.push(key);
    }
  }
  return result;
}

/**
 * Gets the index at which the `key` is found in `array` of key-value pairs.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} key The key to search for.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function assocIndexOf(array, key) {
  var length = array.length;
  while (length--) {
    if (eq(array[length][0], key)) {
      return length;
    }
  }
  return -1;
}

/**
 * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
 * `keysFunc` and `symbolsFunc` to get the enumerable property names and
 * symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Function} keysFunc The function to get the keys of `object`.
 * @param {Function} symbolsFunc The function to get the symbols of `object`.
 * @returns {Array} Returns the array of property names and symbols.
 */
function baseGetAllKeys(object, keysFunc, symbolsFunc) {
  var result = keysFunc(object);
  return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
}

/**
 * The base implementation of `getTag` without fallbacks for buggy environments.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
function baseGetTag(value) {
  if (value == null) {
    return value === undefined ? undefinedTag : nullTag;
  }
  return (symToStringTag && symToStringTag in Object(value))
    ? getRawTag(value)
    : objectToString(value);
}

/**
 * The base implementation of `_.isArguments`.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 */
function baseIsArguments(value) {
  return isObjectLike(value) && baseGetTag(value) == argsTag;
}

/**
 * The base implementation of `_.isEqual` which supports partial comparisons
 * and tracks traversed objects.
 *
 * @private
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @param {boolean} bitmask The bitmask flags.
 *  1 - Unordered comparison
 *  2 - Partial comparison
 * @param {Function} [customizer] The function to customize comparisons.
 * @param {Object} [stack] Tracks traversed `value` and `other` objects.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 */
function baseIsEqual(value, other, bitmask, customizer, stack) {
  if (value === other) {
    return true;
  }
  if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
    return value !== value && other !== other;
  }
  return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
}

/**
 * A specialized version of `baseIsEqual` for arrays and objects which performs
 * deep comparisons and tracks traversed objects enabling objects with circular
 * references to be compared.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} [stack] Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
  var objIsArr = isArray(object),
      othIsArr = isArray(other),
      objTag = objIsArr ? arrayTag : getTag(object),
      othTag = othIsArr ? arrayTag : getTag(other);

  objTag = objTag == argsTag ? objectTag : objTag;
  othTag = othTag == argsTag ? objectTag : othTag;

  var objIsObj = objTag == objectTag,
      othIsObj = othTag == objectTag,
      isSameTag = objTag == othTag;

  if (isSameTag && isBuffer(object)) {
    if (!isBuffer(other)) {
      return false;
    }
    objIsArr = true;
    objIsObj = false;
  }
  if (isSameTag && !objIsObj) {
    stack || (stack = new Stack);
    return (objIsArr || isTypedArray(object))
      ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
      : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
  }
  if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
    var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
        othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');

    if (objIsWrapped || othIsWrapped) {
      var objUnwrapped = objIsWrapped ? object.value() : object,
          othUnwrapped = othIsWrapped ? other.value() : other;

      stack || (stack = new Stack);
      return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
    }
  }
  if (!isSameTag) {
    return false;
  }
  stack || (stack = new Stack);
  return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
}

/**
 * The base implementation of `_.isNative` without bad shim checks.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a native function,
 *  else `false`.
 */
function baseIsNative(value) {
  if (!isObject(value) || isMasked(value)) {
    return false;
  }
  var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
  return pattern.test(toSource(value));
}

/**
 * The base implementation of `_.isTypedArray` without Node.js optimizations.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 */
function baseIsTypedArray(value) {
  return isObjectLike(value) &&
    isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
}

/**
 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function baseKeys(object) {
  if (!isPrototype(object)) {
    return nativeKeys(object);
  }
  var result = [];
  for (var key in Object(object)) {
    if (hasOwnProperty.call(object, key) && key != 'constructor') {
      result.push(key);
    }
  }
  return result;
}

/**
 * A specialized version of `baseIsEqualDeep` for arrays with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Array} array The array to compare.
 * @param {Array} other The other array to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `array` and `other` objects.
 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
 */
function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
      arrLength = array.length,
      othLength = other.length;

  if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
    return false;
  }
  // Assume cyclic values are equal.
  var stacked = stack.get(array);
  if (stacked && stack.get(other)) {
    return stacked == other;
  }
  var index = -1,
      result = true,
      seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;

  stack.set(array, other);
  stack.set(other, array);

  // Ignore non-index properties.
  while (++index < arrLength) {
    var arrValue = array[index],
        othValue = other[index];

    if (customizer) {
      var compared = isPartial
        ? customizer(othValue, arrValue, index, other, array, stack)
        : customizer(arrValue, othValue, index, array, other, stack);
    }
    if (compared !== undefined) {
      if (compared) {
        continue;
      }
      result = false;
      break;
    }
    // Recursively compare arrays (susceptible to call stack limits).
    if (seen) {
      if (!arraySome(other, function(othValue, othIndex) {
            if (!cacheHas(seen, othIndex) &&
                (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
              return seen.push(othIndex);
            }
          })) {
        result = false;
        break;
      }
    } else if (!(
          arrValue === othValue ||
            equalFunc(arrValue, othValue, bitmask, customizer, stack)
        )) {
      result = false;
      break;
    }
  }
  stack['delete'](array);
  stack['delete'](other);
  return result;
}

/**
 * A specialized version of `baseIsEqualDeep` for comparing objects of
 * the same `toStringTag`.
 *
 * **Note:** This function only supports comparing values with tags of
 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {string} tag The `toStringTag` of the objects to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
  switch (tag) {
    case dataViewTag:
      if ((object.byteLength != other.byteLength) ||
          (object.byteOffset != other.byteOffset)) {
        return false;
      }
      object = object.buffer;
      other = other.buffer;

    case arrayBufferTag:
      if ((object.byteLength != other.byteLength) ||
          !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
        return false;
      }
      return true;

    case boolTag:
    case dateTag:
    case numberTag:
      // Coerce booleans to `1` or `0` and dates to milliseconds.
      // Invalid dates are coerced to `NaN`.
      return eq(+object, +other);

    case errorTag:
      return object.name == other.name && object.message == other.message;

    case regexpTag:
    case stringTag:
      // Coerce regexes to strings and treat strings, primitives and objects,
      // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
      // for more details.
      return object == (other + '');

    case mapTag:
      var convert = mapToArray;

    case setTag:
      var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
      convert || (convert = setToArray);

      if (object.size != other.size && !isPartial) {
        return false;
      }
      // Assume cyclic values are equal.
      var stacked = stack.get(object);
      if (stacked) {
        return stacked == other;
      }
      bitmask |= COMPARE_UNORDERED_FLAG;

      // Recursively compare objects (susceptible to call stack limits).
      stack.set(object, other);
      var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
      stack['delete'](object);
      return result;

    case symbolTag:
      if (symbolValueOf) {
        return symbolValueOf.call(object) == symbolValueOf.call(other);
      }
  }
  return false;
}

/**
 * A specialized version of `baseIsEqualDeep` for objects with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
      objProps = getAllKeys(object),
      objLength = objProps.length,
      othProps = getAllKeys(other),
      othLength = othProps.length;

  if (objLength != othLength && !isPartial) {
    return false;
  }
  var index = objLength;
  while (index--) {
    var key = objProps[index];
    if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
      return false;
    }
  }
  // Assume cyclic values are equal.
  var stacked = stack.get(object);
  if (stacked && stack.get(other)) {
    return stacked == other;
  }
  var result = true;
  stack.set(object, other);
  stack.set(other, object);

  var skipCtor = isPartial;
  while (++index < objLength) {
    key = objProps[index];
    var objValue = object[key],
        othValue = other[key];

    if (customizer) {
      var compared = isPartial
        ? customizer(othValue, objValue, key, other, object, stack)
        : customizer(objValue, othValue, key, object, other, stack);
    }
    // Recursively compare objects (susceptible to call stack limits).
    if (!(compared === undefined
          ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
          : compared
        )) {
      result = false;
      break;
    }
    skipCtor || (skipCtor = key == 'constructor');
  }
  if (result && !skipCtor) {
    var objCtor = object.constructor,
        othCtor = other.constructor;

    // Non `Object` object instances with different constructors are not equal.
    if (objCtor != othCtor &&
        ('constructor' in object && 'constructor' in other) &&
        !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
          typeof othCtor == 'function' && othCtor instanceof othCtor)) {
      result = false;
    }
  }
  stack['delete'](object);
  stack['delete'](other);
  return result;
}

/**
 * Creates an array of own enumerable property names and symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names and symbols.
 */
function getAllKeys(object) {
  return baseGetAllKeys(object, keys, getSymbols);
}

/**
 * Gets the data for `map`.
 *
 * @private
 * @param {Object} map The map to query.
 * @param {string} key The reference key.
 * @returns {*} Returns the map data.
 */
function getMapData(map, key) {
  var data = map.__data__;
  return isKeyable(key)
    ? data[typeof key == 'string' ? 'string' : 'hash']
    : data.map;
}

/**
 * Gets the native function at `key` of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the method to get.
 * @returns {*} Returns the function if it's native, else `undefined`.
 */
function getNative(object, key) {
  var value = getValue(object, key);
  return baseIsNative(value) ? value : undefined;
}

/**
 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the raw `toStringTag`.
 */
function getRawTag(value) {
  var isOwn = hasOwnProperty.call(value, symToStringTag),
      tag = value[symToStringTag];

  try {
    value[symToStringTag] = undefined;
    var unmasked = true;
  } catch (e) {}

  var result = nativeObjectToString.call(value);
  if (unmasked) {
    if (isOwn) {
      value[symToStringTag] = tag;
    } else {
      delete value[symToStringTag];
    }
  }
  return result;
}

/**
 * Creates an array of the own enumerable symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of symbols.
 */
var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
  if (object == null) {
    return [];
  }
  object = Object(object);
  return arrayFilter(nativeGetSymbols(object), function(symbol) {
    return propertyIsEnumerable.call(object, symbol);
  });
};

/**
 * Gets the `toStringTag` of `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
var getTag = baseGetTag;

// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
    (Map && getTag(new Map) != mapTag) ||
    (Promise && getTag(Promise.resolve()) != promiseTag) ||
    (Set && getTag(new Set) != setTag) ||
    (WeakMap && getTag(new WeakMap) != weakMapTag)) {
  getTag = function(value) {
    var result = baseGetTag(value),
        Ctor = result == objectTag ? value.constructor : undefined,
        ctorString = Ctor ? toSource(Ctor) : '';

    if (ctorString) {
      switch (ctorString) {
        case dataViewCtorString: return dataViewTag;
        case mapCtorString: return mapTag;
        case promiseCtorString: return promiseTag;
        case setCtorString: return setTag;
        case weakMapCtorString: return weakMapTag;
      }
    }
    return result;
  };
}

/**
 * Checks if `value` is a valid array-like index.
 *
 * @private
 * @param {*} value The value to check.
 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
 */
function isIndex(value, length) {
  length = length == null ? MAX_SAFE_INTEGER : length;
  return !!length &&
    (typeof value == 'number' || reIsUint.test(value)) &&
    (value > -1 && value % 1 == 0 && value < length);
}

/**
 * Checks if `value` is suitable for use as unique object key.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
 */
function isKeyable(value) {
  var type = typeof value;
  return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
    ? (value !== '__proto__')
    : (value === null);
}

/**
 * Checks if `func` has its source masked.
 *
 * @private
 * @param {Function} func The function to check.
 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
 */
function isMasked(func) {
  return !!maskSrcKey && (maskSrcKey in func);
}

/**
 * Checks if `value` is likely a prototype object.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
 */
function isPrototype(value) {
  var Ctor = value && value.constructor,
      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;

  return value === proto;
}

/**
 * Converts `value` to a string using `Object.prototype.toString`.
 *
 * @private
 * @param {*} value The value to convert.
 * @returns {string} Returns the converted string.
 */
function objectToString(value) {
  return nativeObjectToString.call(value);
}

/**
 * Converts `func` to its source code.
 *
 * @private
 * @param {Function} func The function to convert.
 * @returns {string} Returns the source code.
 */
function toSource(func) {
  if (func != null) {
    try {
      return funcToString.call(func);
    } catch (e) {}
    try {
      return (func + '');
    } catch (e) {}
  }
  return '';
}

/**
 * Performs a
 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * comparison between two values to determine if they are equivalent.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.eq(object, object);
 * // => true
 *
 * _.eq(object, other);
 * // => false
 *
 * _.eq('a', 'a');
 * // => true
 *
 * _.eq('a', Object('a'));
 * // => false
 *
 * _.eq(NaN, NaN);
 * // => true
 */
function eq(value, other) {
  return value === other || (value !== value && other !== other);
}

/**
 * Checks if `value` is likely an `arguments` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 *  else `false`.
 * @example
 *
 * _.isArguments(function() { return arguments; }());
 * // => true
 *
 * _.isArguments([1, 2, 3]);
 * // => false
 */
var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
  return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
    !propertyIsEnumerable.call(value, 'callee');
};

/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && isLength(value.length) && !isFunction(value);
}

/**
 * Checks if `value` is a buffer.
 *
 * @static
 * @memberOf _
 * @since 4.3.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
 * @example
 *
 * _.isBuffer(new Buffer(2));
 * // => true
 *
 * _.isBuffer(new Uint8Array(2));
 * // => false
 */
var isBuffer = nativeIsBuffer || stubFalse;

/**
 * Performs a deep comparison between two values to determine if they are
 * equivalent.
 *
 * **Note:** This method supports comparing arrays, array buffers, booleans,
 * date objects, error objects, maps, numbers, `Object` objects, regexes,
 * sets, strings, symbols, and typed arrays. `Object` objects are compared
 * by their own, not inherited, enumerable properties. Functions and DOM
 * nodes are compared by strict equality, i.e. `===`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.isEqual(object, other);
 * // => true
 *
 * object === other;
 * // => false
 */
function isEqual(value, other) {
  return baseIsEqual(value, other);
}

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  if (!isObject(value)) {
    return false;
  }
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 9 which returns 'object' for typed arrays and other constructors.
  var tag = baseGetTag(value);
  return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
}

/**
 * Checks if `value` is a valid array-like length.
 *
 * **Note:** This method is loosely based on
 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 * @example
 *
 * _.isLength(3);
 * // => true
 *
 * _.isLength(Number.MIN_VALUE);
 * // => false
 *
 * _.isLength(Infinity);
 * // => false
 *
 * _.isLength('3');
 * // => false
 */
function isLength(value) {
  return typeof value == 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value;
  return value != null && (type == 'object' || type == 'function');
}

/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return value != null && typeof value == 'object';
}

/**
 * Checks if `value` is classified as a typed array.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 * @example
 *
 * _.isTypedArray(new Uint8Array);
 * // => true
 *
 * _.isTypedArray([]);
 * // => false
 */
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;

/**
 * Creates an array of the own enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects. See the
 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
 * for more details.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keys(new Foo);
 * // => ['a', 'b'] (iteration order is not guaranteed)
 *
 * _.keys('hi');
 * // => ['0', '1']
 */
function keys(object) {
  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
}

/**
 * This method returns a new empty array.
 *
 * @static
 * @memberOf _
 * @since 4.13.0
 * @category Util
 * @returns {Array} Returns the new empty array.
 * @example
 *
 * var arrays = _.times(2, _.stubArray);
 *
 * console.log(arrays);
 * // => [[], []]
 *
 * console.log(arrays[0] === arrays[1]);
 * // => false
 */
function stubArray() {
  return [];
}

/**
 * This method returns `false`.
 *
 * @static
 * @memberOf _
 * @since 4.13.0
 * @category Util
 * @returns {boolean} Returns `false`.
 * @example
 *
 * _.times(2, _.stubFalse);
 * // => [false, false]
 */
function stubFalse() {
  return false;
}

module.exports = isEqual;
{
  "name": "lodash.isequal",
  "version": "4.5.0",
  "description": "The Lodash method `_.isEqual` exported as a module.",
  "homepage": "https://lodash.com/",
  "icon": "https://lodash.com/icon.svg",
  "license": "MIT",
  "author": "John-David Dalton <john.david.dalton@gmail.com> (http://allyoucanleet.com/)",
  "repository": "lodash/lodash"
}/**
 * Helpers.
 */

var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var w = d * 7;
var y = d * 365.25;

/**
 * Parse or format the given `val`.
 *
 * Options:
 *
 *  - `long` verbose formatting [false]
 *
 * @param {String|Number} val
 * @param {Object} [options]
 * @throws {Error} throw an error if val is not a non-empty string or a number
 * @return {String|Number}
 * @api public
 */

module.exports = function (val, options) {
  options = options || {};
  var type = typeof val;
  if (type === 'string' && val.length > 0) {
    return parse(val);
  } else if (type === 'number' && isFinite(val)) {
    return options.long ? fmtLong(val) : fmtShort(val);
  }
  throw new Error(
    'val is not a non-empty string or a valid number. val=' +
      JSON.stringify(val)
  );
};

/**
 * Parse the given `str` and return milliseconds.
 *
 * @param {String} str
 * @return {Number}
 * @api private
 */

function parse(str) {
  str = String(str);
  if (str.length > 100) {
    return;
  }
  var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
    str
  );
  if (!match) {
    return;
  }
  var n = parseFloat(match[1]);
  var type = (match[2] || 'ms').toLowerCase();
  switch (type) {
    case 'years':
    case 'year':
    case 'yrs':
    case 'yr':
    case 'y':
      return n * y;
    case 'weeks':
    case 'week':
    case 'w':
      return n * w;
    case 'days':
    case 'day':
    case 'd':
      return n * d;
    case 'hours':
    case 'hour':
    case 'hrs':
    case 'hr':
    case 'h':
      return n * h;
    case 'minutes':
    case 'minute':
    case 'mins':
    case 'min':
    case 'm':
      return n * m;
    case 'seconds':
    case 'second':
    case 'secs':
    case 'sec':
    case 's':
      return n * s;
    case 'milliseconds':
    case 'millisecond':
    case 'msecs':
    case 'msec':
    case 'ms':
      return n;
    default:
      return undefined;
  }
}

/**
 * Short format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function fmtShort(ms) {
  var msAbs = Math.abs(ms);
  if (msAbs >= d) {
    return Math.round(ms / d) + 'd';
  }
  if (msAbs >= h) {
    return Math.round(ms / h) + 'h';
  }
  if (msAbs >= m) {
    return Math.round(ms / m) + 'm';
  }
  if (msAbs >= s) {
    return Math.round(ms / s) + 's';
  }
  return ms + 'ms';
}

/**
 * Long format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function fmtLong(ms) {
  var msAbs = Math.abs(ms);
  if (msAbs >= d) {
    return plural(ms, msAbs, d, 'day');
  }
  if (msAbs >= h) {
    return plural(ms, msAbs, h, 'hour');
  }
  if (msAbs >= m) {
    return plural(ms, msAbs, m, 'minute');
  }
  if (msAbs >= s) {
    return plural(ms, msAbs, s, 'second');
  }
  return ms + ' ms';
}

/**
 * Pluralization helper.
 */

function plural(ms, msAbs, n, name) {
  var isPlural = msAbs >= n * 1.5;
  return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
}
The MIT License (MIT)

Copyright (c) 2020 Vercel, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
{
  "name": "ms",
  "version": "2.1.3",
  "description": "Tiny millisecond conversion utility",
  "repository": "vercel/ms",
  "main": "./index",
  "files": [
    "index.js"
  ],
  "lint-staged": {
    "*.js": [
      "npm run lint",
      "prettier --single-quote --write",
      "git add"
    ]
  },
  "license": "MIT",
  "devDependencies": {
    "eslint": "4.18.2",
    "expect.js": "0.3.1",
    "husky": "0.14.3",
    "lint-staged": "5.0.0",
    "mocha": "4.0.1",
    "prettier": "2.0.5"
  }
}The ISC License

Copyright (c) 2010-2024 Isaac Z. Schlueter and Contributors

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

====

`String.fromCodePoint` by Mathias Bynens used according to terms of MIT
License, as follows:

Copyright (c) 2010-2024 Mathias Bynens <https://mathiasbynens.be/>

    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    "Software"), to deal in the Software without restriction, including
    without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to
    the following conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
;(function (sax) { // wrapper for non-node envs
  sax.parser = function (strict, opt) { return new SAXParser(strict, opt) }
  sax.SAXParser = SAXParser
  sax.SAXStream = SAXStream
  sax.createStream = createStream

  // When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns.
  // When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)),
  // since that's the earliest that a buffer overrun could occur.  This way, checks are
  // as rare as required, but as often as necessary to ensure never crossing this bound.
  // Furthermore, buffers are only tested at most once per write(), so passing a very
  // large string into write() might have undesirable effects, but this is manageable by
  // the caller, so it is assumed to be safe.  Thus, a call to write() may, in the extreme
  // edge case, result in creating at most one complete copy of the string passed in.
  // Set to Infinity to have unlimited buffers.
  sax.MAX_BUFFER_LENGTH = 64 * 1024

  var buffers = [
    'comment', 'sgmlDecl', 'textNode', 'tagName', 'doctype',
    'procInstName', 'procInstBody', 'entity', 'attribName',
    'attribValue', 'cdata', 'script'
  ]

  sax.EVENTS = [
    'text',
    'processinginstruction',
    'sgmldeclaration',
    'doctype',
    'comment',
    'opentagstart',
    'attribute',
    'opentag',
    'closetag',
    'opencdata',
    'cdata',
    'closecdata',
    'error',
    'end',
    'ready',
    'script',
    'opennamespace',
    'closenamespace'
  ]

  function SAXParser (strict, opt) {
    if (!(this instanceof SAXParser)) {
      return new SAXParser(strict, opt)
    }

    var parser = this
    clearBuffers(parser)
    parser.q = parser.c = ''
    parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH
    parser.opt = opt || {}
    parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags
    parser.looseCase = parser.opt.lowercase ? 'toLowerCase' : 'toUpperCase'
    parser.tags = []
    parser.closed = parser.closedRoot = parser.sawRoot = false
    parser.tag = parser.error = null
    parser.strict = !!strict
    parser.noscript = !!(strict || parser.opt.noscript)
    parser.state = S.BEGIN
    parser.strictEntities = parser.opt.strictEntities
    parser.ENTITIES = parser.strictEntities ? Object.create(sax.XML_ENTITIES) : Object.create(sax.ENTITIES)
    parser.attribList = []

    // namespaces form a prototype chain.
    // it always points at the current tag,
    // which protos to its parent tag.
    if (parser.opt.xmlns) {
      parser.ns = Object.create(rootNS)
    }

    // disallow unquoted attribute values if not otherwise configured
    // and strict mode is true
    if (parser.opt.unquotedAttributeValues === undefined) {
      parser.opt.unquotedAttributeValues = !strict;
    }

    // mostly just for error reporting
    parser.trackPosition = parser.opt.position !== false
    if (parser.trackPosition) {
      parser.position = parser.line = parser.column = 0
    }
    emit(parser, 'onready')
  }

  if (!Object.create) {
    Object.create = function (o) {
      function F () {}
      F.prototype = o
      var newf = new F()
      return newf
    }
  }

  if (!Object.keys) {
    Object.keys = function (o) {
      var a = []
      for (var i in o) if (o.hasOwnProperty(i)) a.push(i)
      return a
    }
  }

  function checkBufferLength (parser) {
    var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10)
    var maxActual = 0
    for (var i = 0, l = buffers.length; i < l; i++) {
      var len = parser[buffers[i]].length
      if (len > maxAllowed) {
        // Text/cdata nodes can get big, and since they're buffered,
        // we can get here under normal conditions.
        // Avoid issues by emitting the text node now,
        // so at least it won't get any bigger.
        switch (buffers[i]) {
          case 'textNode':
            closeText(parser)
            break

          case 'cdata':
            emitNode(parser, 'oncdata', parser.cdata)
            parser.cdata = ''
            break

          case 'script':
            emitNode(parser, 'onscript', parser.script)
            parser.script = ''
            break

          default:
            error(parser, 'Max buffer length exceeded: ' + buffers[i])
        }
      }
      maxActual = Math.max(maxActual, len)
    }
    // schedule the next check for the earliest possible buffer overrun.
    var m = sax.MAX_BUFFER_LENGTH - maxActual
    parser.bufferCheckPosition = m + parser.position
  }

  function clearBuffers (parser) {
    for (var i = 0, l = buffers.length; i < l; i++) {
      parser[buffers[i]] = ''
    }
  }

  function flushBuffers (parser) {
    closeText(parser)
    if (parser.cdata !== '') {
      emitNode(parser, 'oncdata', parser.cdata)
      parser.cdata = ''
    }
    if (parser.script !== '') {
      emitNode(parser, 'onscript', parser.script)
      parser.script = ''
    }
  }

  SAXParser.prototype = {
    end: function () { end(this) },
    write: write,
    resume: function () { this.error = null; return this },
    close: function () { return this.write(null) },
    flush: function () { flushBuffers(this) }
  }

  var Stream
  try {
    Stream = require('stream').Stream
  } catch (ex) {
    Stream = function () {}
  }
  if (!Stream) Stream = function () {}

  var streamWraps = sax.EVENTS.filter(function (ev) {
    return ev !== 'error' && ev !== 'end'
  })

  function createStream (strict, opt) {
    return new SAXStream(strict, opt)
  }

  function SAXStream (strict, opt) {
    if (!(this instanceof SAXStream)) {
      return new SAXStream(strict, opt)
    }

    Stream.apply(this)

    this._parser = new SAXParser(strict, opt)
    this.writable = true
    this.readable = true

    var me = this

    this._parser.onend = function () {
      me.emit('end')
    }

    this._parser.onerror = function (er) {
      me.emit('error', er)

      // if didn't throw, then means error was handled.
      // go ahead and clear error, so we can write again.
      me._parser.error = null
    }

    this._decoder = null

    streamWraps.forEach(function (ev) {
      Object.defineProperty(me, 'on' + ev, {
        get: function () {
          return me._parser['on' + ev]
        },
        set: function (h) {
          if (!h) {
            me.removeAllListeners(ev)
            me._parser['on' + ev] = h
            return h
          }
          me.on(ev, h)
        },
        enumerable: true,
        configurable: false
      })
    })
  }

  SAXStream.prototype = Object.create(Stream.prototype, {
    constructor: {
      value: SAXStream
    }
  })

  SAXStream.prototype.write = function (data) {
    if (typeof Buffer === 'function' &&
      typeof Buffer.isBuffer === 'function' &&
      Buffer.isBuffer(data)) {
      if (!this._decoder) {
        var SD = require('string_decoder').StringDecoder
        this._decoder = new SD('utf8')
      }
      data = this._decoder.write(data)
    }

    this._parser.write(data.toString())
    this.emit('data', data)
    return true
  }

  SAXStream.prototype.end = function (chunk) {
    if (chunk && chunk.length) {
      this.write(chunk)
    }
    this._parser.end()
    return true
  }

  SAXStream.prototype.on = function (ev, handler) {
    var me = this
    if (!me._parser['on' + ev] && streamWraps.indexOf(ev) !== -1) {
      me._parser['on' + ev] = function () {
        var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments)
        args.splice(0, 0, ev)
        me.emit.apply(me, args)
      }
    }

    return Stream.prototype.on.call(me, ev, handler)
  }

  // this really needs to be replaced with character classes.
  // XML allows all manner of ridiculous numbers and digits.
  var CDATA = '[CDATA['
  var DOCTYPE = 'DOCTYPE'
  var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace'
  var XMLNS_NAMESPACE = 'http://www.w3.org/2000/xmlns/'
  var rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE }

  // http://www.w3.org/TR/REC-xml/#NT-NameStartChar
  // This implementation works on strings, a single character at a time
  // as such, it cannot ever support astral-plane characters (10000-EFFFF)
  // without a significant breaking change to either this  parser, or the
  // JavaScript language.  Implementation of an emoji-capable xml parser
  // is left as an exercise for the reader.
  var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/

  var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/

  var entityStart = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/
  var entityBody = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/

  function isWhitespace (c) {
    return c === ' ' || c === '\n' || c === '\r' || c === '\t'
  }

  function isQuote (c) {
    return c === '"' || c === '\''
  }

  function isAttribEnd (c) {
    return c === '>' || isWhitespace(c)
  }

  function isMatch (regex, c) {
    return regex.test(c)
  }

  function notMatch (regex, c) {
    return !isMatch(regex, c)
  }

  var S = 0
  sax.STATE = {
    BEGIN: S++, // leading byte order mark or whitespace
    BEGIN_WHITESPACE: S++, // leading whitespace
    TEXT: S++, // general stuff
    TEXT_ENTITY: S++, // &amp and such.
    OPEN_WAKA: S++, // <
    SGML_DECL: S++, // <!BLARG
    SGML_DECL_QUOTED: S++, // <!BLARG foo "bar
    DOCTYPE: S++, // <!DOCTYPE
    DOCTYPE_QUOTED: S++, // <!DOCTYPE "//blah
    DOCTYPE_DTD: S++, // <!DOCTYPE "//blah" [ ...
    DOCTYPE_DTD_QUOTED: S++, // <!DOCTYPE "//blah" [ "foo
    COMMENT_STARTING: S++, // <!-
    COMMENT: S++, // <!--
    COMMENT_ENDING: S++, // <!-- blah -
    COMMENT_ENDED: S++, // <!-- blah --
    CDATA: S++, // <![CDATA[ something
    CDATA_ENDING: S++, // ]
    CDATA_ENDING_2: S++, // ]]
    PROC_INST: S++, // <?hi
    PROC_INST_BODY: S++, // <?hi there
    PROC_INST_ENDING: S++, // <?hi "there" ?
    OPEN_TAG: S++, // <strong
    OPEN_TAG_SLASH: S++, // <strong /
    ATTRIB: S++, // <a
    ATTRIB_NAME: S++, // <a foo
    ATTRIB_NAME_SAW_WHITE: S++, // <a foo _
    ATTRIB_VALUE: S++, // <a foo=
    ATTRIB_VALUE_QUOTED: S++, // <a foo="bar
    ATTRIB_VALUE_CLOSED: S++, // <a foo="bar"
    ATTRIB_VALUE_UNQUOTED: S++, // <a foo=bar
    ATTRIB_VALUE_ENTITY_Q: S++, // <foo bar="&quot;"
    ATTRIB_VALUE_ENTITY_U: S++, // <foo bar=&quot
    CLOSE_TAG: S++, // </a
    CLOSE_TAG_SAW_WHITE: S++, // </a   >
    SCRIPT: S++, // <script> ...
    SCRIPT_ENDING: S++ // <script> ... <
  }

  sax.XML_ENTITIES = {
    'amp': '&',
    'gt': '>',
    'lt': '<',
    'quot': '"',
    'apos': "'"
  }

  sax.ENTITIES = {
    'amp': '&',
    'gt': '>',
    'lt': '<',
    'quot': '"',
    'apos': "'",
    'AElig': 198,
    'Aacute': 193,
    'Acirc': 194,
    'Agrave': 192,
    'Aring': 197,
    'Atilde': 195,
    'Auml': 196,
    'Ccedil': 199,
    'ETH': 208,
    'Eacute': 201,
    'Ecirc': 202,
    'Egrave': 200,
    'Euml': 203,
    'Iacute': 205,
    'Icirc': 206,
    'Igrave': 204,
    'Iuml': 207,
    'Ntilde': 209,
    'Oacute': 211,
    'Ocirc': 212,
    'Ograve': 210,
    'Oslash': 216,
    'Otilde': 213,
    'Ouml': 214,
    'THORN': 222,
    'Uacute': 218,
    'Ucirc': 219,
    'Ugrave': 217,
    'Uuml': 220,
    'Yacute': 221,
    'aacute': 225,
    'acirc': 226,
    'aelig': 230,
    'agrave': 224,
    'aring': 229,
    'atilde': 227,
    'auml': 228,
    'ccedil': 231,
    'eacute': 233,
    'ecirc': 234,
    'egrave': 232,
    'eth': 240,
    'euml': 235,
    'iacute': 237,
    'icirc': 238,
    'igrave': 236,
    'iuml': 239,
    'ntilde': 241,
    'oacute': 243,
    'ocirc': 244,
    'ograve': 242,
    'oslash': 248,
    'otilde': 245,
    'ouml': 246,
    'szlig': 223,
    'thorn': 254,
    'uacute': 250,
    'ucirc': 251,
    'ugrave': 249,
    'uuml': 252,
    'yacute': 253,
    'yuml': 255,
    'copy': 169,
    'reg': 174,
    'nbsp': 160,
    'iexcl': 161,
    'cent': 162,
    'pound': 163,
    'curren': 164,
    'yen': 165,
    'brvbar': 166,
    'sect': 167,
    'uml': 168,
    'ordf': 170,
    'laquo': 171,
    'not': 172,
    'shy': 173,
    'macr': 175,
    'deg': 176,
    'plusmn': 177,
    'sup1': 185,
    'sup2': 178,
    'sup3': 179,
    'acute': 180,
    'micro': 181,
    'para': 182,
    'middot': 183,
    'cedil': 184,
    'ordm': 186,
    'raquo': 187,
    'frac14': 188,
    'frac12': 189,
    'frac34': 190,
    'iquest': 191,
    'times': 215,
    'divide': 247,
    'OElig': 338,
    'oelig': 339,
    'Scaron': 352,
    'scaron': 353,
    'Yuml': 376,
    'fnof': 402,
    'circ': 710,
    'tilde': 732,
    'Alpha': 913,
    'Beta': 914,
    'Gamma': 915,
    'Delta': 916,
    'Epsilon': 917,
    'Zeta': 918,
    'Eta': 919,
    'Theta': 920,
    'Iota': 921,
    'Kappa': 922,
    'Lambda': 923,
    'Mu': 924,
    'Nu': 925,
    'Xi': 926,
    'Omicron': 927,
    'Pi': 928,
    'Rho': 929,
    'Sigma': 931,
    'Tau': 932,
    'Upsilon': 933,
    'Phi': 934,
    'Chi': 935,
    'Psi': 936,
    'Omega': 937,
    'alpha': 945,
    'beta': 946,
    'gamma': 947,
    'delta': 948,
    'epsilon': 949,
    'zeta': 950,
    'eta': 951,
    'theta': 952,
    'iota': 953,
    'kappa': 954,
    'lambda': 955,
    'mu': 956,
    'nu': 957,
    'xi': 958,
    'omicron': 959,
    'pi': 960,
    'rho': 961,
    'sigmaf': 962,
    'sigma': 963,
    'tau': 964,
    'upsilon': 965,
    'phi': 966,
    'chi': 967,
    'psi': 968,
    'omega': 969,
    'thetasym': 977,
    'upsih': 978,
    'piv': 982,
    'ensp': 8194,
    'emsp': 8195,
    'thinsp': 8201,
    'zwnj': 8204,
    'zwj': 8205,
    'lrm': 8206,
    'rlm': 8207,
    'ndash': 8211,
    'mdash': 8212,
    'lsquo': 8216,
    'rsquo': 8217,
    'sbquo': 8218,
    'ldquo': 8220,
    'rdquo': 8221,
    'bdquo': 8222,
    'dagger': 8224,
    'Dagger': 8225,
    'bull': 8226,
    'hellip': 8230,
    'permil': 8240,
    'prime': 8242,
    'Prime': 8243,
    'lsaquo': 8249,
    'rsaquo': 8250,
    'oline': 8254,
    'frasl': 8260,
    'euro': 8364,
    'image': 8465,
    'weierp': 8472,
    'real': 8476,
    'trade': 8482,
    'alefsym': 8501,
    'larr': 8592,
    'uarr': 8593,
    'rarr': 8594,
    'darr': 8595,
    'harr': 8596,
    'crarr': 8629,
    'lArr': 8656,
    'uArr': 8657,
    'rArr': 8658,
    'dArr': 8659,
    'hArr': 8660,
    'forall': 8704,
    'part': 8706,
    'exist': 8707,
    'empty': 8709,
    'nabla': 8711,
    'isin': 8712,
    'notin': 8713,
    'ni': 8715,
    'prod': 8719,
    'sum': 8721,
    'minus': 8722,
    'lowast': 8727,
    'radic': 8730,
    'prop': 8733,
    'infin': 8734,
    'ang': 8736,
    'and': 8743,
    'or': 8744,
    'cap': 8745,
    'cup': 8746,
    'int': 8747,
    'there4': 8756,
    'sim': 8764,
    'cong': 8773,
    'asymp': 8776,
    'ne': 8800,
    'equiv': 8801,
    'le': 8804,
    'ge': 8805,
    'sub': 8834,
    'sup': 8835,
    'nsub': 8836,
    'sube': 8838,
    'supe': 8839,
    'oplus': 8853,
    'otimes': 8855,
    'perp': 8869,
    'sdot': 8901,
    'lceil': 8968,
    'rceil': 8969,
    'lfloor': 8970,
    'rfloor': 8971,
    'lang': 9001,
    'rang': 9002,
    'loz': 9674,
    'spades': 9824,
    'clubs': 9827,
    'hearts': 9829,
    'diams': 9830
  }

  Object.keys(sax.ENTITIES).forEach(function (key) {
    var e = sax.ENTITIES[key]
    var s = typeof e === 'number' ? String.fromCharCode(e) : e
    sax.ENTITIES[key] = s
  })

  for (var s in sax.STATE) {
    sax.STATE[sax.STATE[s]] = s
  }

  // shorthand
  S = sax.STATE

  function emit (parser, event, data) {
    parser[event] && parser[event](data)
  }

  function emitNode (parser, nodeType, data) {
    if (parser.textNode) closeText(parser)
    emit(parser, nodeType, data)
  }

  function closeText (parser) {
    parser.textNode = textopts(parser.opt, parser.textNode)
    if (parser.textNode) emit(parser, 'ontext', parser.textNode)
    parser.textNode = ''
  }

  function textopts (opt, text) {
    if (opt.trim) text = text.trim()
    if (opt.normalize) text = text.replace(/\s+/g, ' ')
    return text
  }

  function error (parser, er) {
    closeText(parser)
    if (parser.trackPosition) {
      er += '\nLine: ' + parser.line +
        '\nColumn: ' + parser.column +
        '\nChar: ' + parser.c
    }
    er = new Error(er)
    parser.error = er
    emit(parser, 'onerror', er)
    return parser
  }

  function end (parser) {
    if (parser.sawRoot && !parser.closedRoot) strictFail(parser, 'Unclosed root tag')
    if ((parser.state !== S.BEGIN) &&
      (parser.state !== S.BEGIN_WHITESPACE) &&
      (parser.state !== S.TEXT)) {
      error(parser, 'Unexpected end')
    }
    closeText(parser)
    parser.c = ''
    parser.closed = true
    emit(parser, 'onend')
    SAXParser.call(parser, parser.strict, parser.opt)
    return parser
  }

  function strictFail (parser, message) {
    if (typeof parser !== 'object' || !(parser instanceof SAXParser)) {
      throw new Error('bad call to strictFail')
    }
    if (parser.strict) {
      error(parser, message)
    }
  }

  function newTag (parser) {
    if (!parser.strict) parser.tagName = parser.tagName[parser.looseCase]()
    var parent = parser.tags[parser.tags.length - 1] || parser
    var tag = parser.tag = { name: parser.tagName, attributes: {} }

    // will be overridden if tag contails an xmlns="foo" or xmlns:foo="bar"
    if (parser.opt.xmlns) {
      tag.ns = parent.ns
    }
    parser.attribList.length = 0
    emitNode(parser, 'onopentagstart', tag)
  }

  function qname (name, attribute) {
    var i = name.indexOf(':')
    var qualName = i < 0 ? [ '', name ] : name.split(':')
    var prefix = qualName[0]
    var local = qualName[1]

    // <x "xmlns"="http://foo">
    if (attribute && name === 'xmlns') {
      prefix = 'xmlns'
      local = ''
    }

    return { prefix: prefix, local: local }
  }

  function attrib (parser) {
    if (!parser.strict) {
      parser.attribName = parser.attribName[parser.looseCase]()
    }

    if (parser.attribList.indexOf(parser.attribName) !== -1 ||
      parser.tag.attributes.hasOwnProperty(parser.attribName)) {
      parser.attribName = parser.attribValue = ''
      return
    }

    if (parser.opt.xmlns) {
      var qn = qname(parser.attribName, true)
      var prefix = qn.prefix
      var local = qn.local

      if (prefix === 'xmlns') {
        // namespace binding attribute. push the binding into scope
        if (local === 'xml' && parser.attribValue !== XML_NAMESPACE) {
          strictFail(parser,
            'xml: prefix must be bound to ' + XML_NAMESPACE + '\n' +
            'Actual: ' + parser.attribValue)
        } else if (local === 'xmlns' && parser.attribValue !== XMLNS_NAMESPACE) {
          strictFail(parser,
            'xmlns: prefix must be bound to ' + XMLNS_NAMESPACE + '\n' +
            'Actual: ' + parser.attribValue)
        } else {
          var tag = parser.tag
          var parent = parser.tags[parser.tags.length - 1] || parser
          if (tag.ns === parent.ns) {
            tag.ns = Object.create(parent.ns)
          }
          tag.ns[local] = parser.attribValue
        }
      }

      // defer onattribute events until all attributes have been seen
      // so any new bindings can take effect. preserve attribute order
      // so deferred events can be emitted in document order
      parser.attribList.push([parser.attribName, parser.attribValue])
    } else {
      // in non-xmlns mode, we can emit the event right away
      parser.tag.attributes[parser.attribName] = parser.attribValue
      emitNode(parser, 'onattribute', {
        name: parser.attribName,
        value: parser.attribValue
      })
    }

    parser.attribName = parser.attribValue = ''
  }

  function openTag (parser, selfClosing) {
    if (parser.opt.xmlns) {
      // emit namespace binding events
      var tag = parser.tag

      // add namespace info to tag
      var qn = qname(parser.tagName)
      tag.prefix = qn.prefix
      tag.local = qn.local
      tag.uri = tag.ns[qn.prefix] || ''

      if (tag.prefix && !tag.uri) {
        strictFail(parser, 'Unbound namespace prefix: ' +
          JSON.stringify(parser.tagName))
        tag.uri = qn.prefix
      }

      var parent = parser.tags[parser.tags.length - 1] || parser
      if (tag.ns && parent.ns !== tag.ns) {
        Object.keys(tag.ns).forEach(function (p) {
          emitNode(parser, 'onopennamespace', {
            prefix: p,
            uri: tag.ns[p]
          })
        })
      }

      // handle deferred onattribute events
      // Note: do not apply default ns to attributes:
      //   http://www.w3.org/TR/REC-xml-names/#defaulting
      for (var i = 0, l = parser.attribList.length; i < l; i++) {
        var nv = parser.attribList[i]
        var name = nv[0]
        var value = nv[1]
        var qualName = qname(name, true)
        var prefix = qualName.prefix
        var local = qualName.local
        var uri = prefix === '' ? '' : (tag.ns[prefix] || '')
        var a = {
          name: name,
          value: value,
          prefix: prefix,
          local: local,
          uri: uri
        }

        // if there's any attributes with an undefined namespace,
        // then fail on them now.
        if (prefix && prefix !== 'xmlns' && !uri) {
          strictFail(parser, 'Unbound namespace prefix: ' +
            JSON.stringify(prefix))
          a.uri = prefix
        }
        parser.tag.attributes[name] = a
        emitNode(parser, 'onattribute', a)
      }
      parser.attribList.length = 0
    }

    parser.tag.isSelfClosing = !!selfClosing

    // process the tag
    parser.sawRoot = true
    parser.tags.push(parser.tag)
    emitNode(parser, 'onopentag', parser.tag)
    if (!selfClosing) {
      // special case for <script> in non-strict mode.
      if (!parser.noscript && parser.tagName.toLowerCase() === 'script') {
        parser.state = S.SCRIPT
      } else {
        parser.state = S.TEXT
      }
      parser.tag = null
      parser.tagName = ''
    }
    parser.attribName = parser.attribValue = ''
    parser.attribList.length = 0
  }

  function closeTag (parser) {
    if (!parser.tagName) {
      strictFail(parser, 'Weird empty close tag.')
      parser.textNode += '</>'
      parser.state = S.TEXT
      return
    }

    if (parser.script) {
      if (parser.tagName !== 'script') {
        parser.script += '</' + parser.tagName + '>'
        parser.tagName = ''
        parser.state = S.SCRIPT
        return
      }
      emitNode(parser, 'onscript', parser.script)
      parser.script = ''
    }

    // first make sure that the closing tag actually exists.
    // <a><b></c></b></a> will close everything, otherwise.
    var t = parser.tags.length
    var tagName = parser.tagName
    if (!parser.strict) {
      tagName = tagName[parser.looseCase]()
    }
    var closeTo = tagName
    while (t--) {
      var close = parser.tags[t]
      if (close.name !== closeTo) {
        // fail the first time in strict mode
        strictFail(parser, 'Unexpected close tag')
      } else {
        break
      }
    }

    // didn't find it.  we already failed for strict, so just abort.
    if (t < 0) {
      strictFail(parser, 'Unmatched closing tag: ' + parser.tagName)
      parser.textNode += '</' + parser.tagName + '>'
      parser.state = S.TEXT
      return
    }
    parser.tagName = tagName
    var s = parser.tags.length
    while (s-- > t) {
      var tag = parser.tag = parser.tags.pop()
      parser.tagName = parser.tag.name
      emitNode(parser, 'onclosetag', parser.tagName)

      var x = {}
      for (var i in tag.ns) {
        x[i] = tag.ns[i]
      }

      var parent = parser.tags[parser.tags.length - 1] || parser
      if (parser.opt.xmlns && tag.ns !== parent.ns) {
        // remove namespace bindings introduced by tag
        Object.keys(tag.ns).forEach(function (p) {
          var n = tag.ns[p]
          emitNode(parser, 'onclosenamespace', { prefix: p, uri: n })
        })
      }
    }
    if (t === 0) parser.closedRoot = true
    parser.tagName = parser.attribValue = parser.attribName = ''
    parser.attribList.length = 0
    parser.state = S.TEXT
  }

  function parseEntity (parser) {
    var entity = parser.entity
    var entityLC = entity.toLowerCase()
    var num
    var numStr = ''

    if (parser.ENTITIES[entity]) {
      return parser.ENTITIES[entity]
    }
    if (parser.ENTITIES[entityLC]) {
      return parser.ENTITIES[entityLC]
    }
    entity = entityLC
    if (entity.charAt(0) === '#') {
      if (entity.charAt(1) === 'x') {
        entity = entity.slice(2)
        num = parseInt(entity, 16)
        numStr = num.toString(16)
      } else {
        entity = entity.slice(1)
        num = parseInt(entity, 10)
        numStr = num.toString(10)
      }
    }
    entity = entity.replace(/^0+/, '')
    if (isNaN(num) || numStr.toLowerCase() !== entity) {
      strictFail(parser, 'Invalid character entity')
      return '&' + parser.entity + ';'
    }

    return String.fromCodePoint(num)
  }

  function beginWhiteSpace (parser, c) {
    if (c === '<') {
      parser.state = S.OPEN_WAKA
      parser.startTagPosition = parser.position
    } else if (!isWhitespace(c)) {
      // have to process this as a text node.
      // weird, but happens.
      strictFail(parser, 'Non-whitespace before first tag.')
      parser.textNode = c
      parser.state = S.TEXT
    }
  }

  function charAt (chunk, i) {
    var result = ''
    if (i < chunk.length) {
      result = chunk.charAt(i)
    }
    return result
  }

  function write (chunk) {
    var parser = this
    if (this.error) {
      throw this.error
    }
    if (parser.closed) {
      return error(parser,
        'Cannot write after close. Assign an onready handler.')
    }
    if (chunk === null) {
      return end(parser)
    }
    if (typeof chunk === 'object') {
      chunk = chunk.toString()
    }
    var i = 0
    var c = ''
    while (true) {
      c = charAt(chunk, i++)
      parser.c = c

      if (!c) {
        break
      }

      if (parser.trackPosition) {
        parser.position++
        if (c === '\n') {
          parser.line++
          parser.column = 0
        } else {
          parser.column++
        }
      }

      switch (parser.state) {
        case S.BEGIN:
          parser.state = S.BEGIN_WHITESPACE
          if (c === '\uFEFF') {
            continue
          }
          beginWhiteSpace(parser, c)
          continue

        case S.BEGIN_WHITESPACE:
          beginWhiteSpace(parser, c)
          continue

        case S.TEXT:
          if (parser.sawRoot && !parser.closedRoot) {
            var starti = i - 1
            while (c && c !== '<' && c !== '&') {
              c = charAt(chunk, i++)
              if (c && parser.trackPosition) {
                parser.position++
                if (c === '\n') {
                  parser.line++
                  parser.column = 0
                } else {
                  parser.column++
                }
              }
            }
            parser.textNode += chunk.substring(starti, i - 1)
          }
          if (c === '<' && !(parser.sawRoot && parser.closedRoot && !parser.strict)) {
            parser.state = S.OPEN_WAKA
            parser.startTagPosition = parser.position
          } else {
            if (!isWhitespace(c) && (!parser.sawRoot || parser.closedRoot)) {
              strictFail(parser, 'Text data outside of root node.')
            }
            if (c === '&') {
              parser.state = S.TEXT_ENTITY
            } else {
              parser.textNode += c
            }
          }
          continue

        case S.SCRIPT:
          // only non-strict
          if (c === '<') {
            parser.state = S.SCRIPT_ENDING
          } else {
            parser.script += c
          }
          continue

        case S.SCRIPT_ENDING:
          if (c === '/') {
            parser.state = S.CLOSE_TAG
          } else {
            parser.script += '<' + c
            parser.state = S.SCRIPT
          }
          continue

        case S.OPEN_WAKA:
          // either a /, ?, !, or text is coming next.
          if (c === '!') {
            parser.state = S.SGML_DECL
            parser.sgmlDecl = ''
          } else if (isWhitespace(c)) {
            // wait for it...
          } else if (isMatch(nameStart, c)) {
            parser.state = S.OPEN_TAG
            parser.tagName = c
          } else if (c === '/') {
            parser.state = S.CLOSE_TAG
            parser.tagName = ''
          } else if (c === '?') {
            parser.state = S.PROC_INST
            parser.procInstName = parser.procInstBody = ''
          } else {
            strictFail(parser, 'Unencoded <')
            // if there was some whitespace, then add that in.
            if (parser.startTagPosition + 1 < parser.position) {
              var pad = parser.position - parser.startTagPosition
              c = new Array(pad).join(' ') + c
            }
            parser.textNode += '<' + c
            parser.state = S.TEXT
          }
          continue

        case S.SGML_DECL:
          if (parser.sgmlDecl + c === '--') {
            parser.state = S.COMMENT
            parser.comment = ''
            parser.sgmlDecl = ''
            continue;
          }

          if (parser.doctype && parser.doctype !== true && parser.sgmlDecl) {
            parser.state = S.DOCTYPE_DTD
            parser.doctype += '<!' + parser.sgmlDecl + c
            parser.sgmlDecl = ''
          } else if ((parser.sgmlDecl + c).toUpperCase() === CDATA) {
            emitNode(parser, 'onopencdata')
            parser.state = S.CDATA
            parser.sgmlDecl = ''
            parser.cdata = ''
          } else if ((parser.sgmlDecl + c).toUpperCase() === DOCTYPE) {
            parser.state = S.DOCTYPE
            if (parser.doctype || parser.sawRoot) {
              strictFail(parser,
                'Inappropriately located doctype declaration')
            }
            parser.doctype = ''
            parser.sgmlDecl = ''
          } else if (c === '>') {
            emitNode(parser, 'onsgmldeclaration', parser.sgmlDecl)
            parser.sgmlDecl = ''
            parser.state = S.TEXT
          } else if (isQuote(c)) {
            parser.state = S.SGML_DECL_QUOTED
            parser.sgmlDecl += c
          } else {
            parser.sgmlDecl += c
          }
          continue

        case S.SGML_DECL_QUOTED:
          if (c === parser.q) {
            parser.state = S.SGML_DECL
            parser.q = ''
          }
          parser.sgmlDecl += c
          continue

        case S.DOCTYPE:
          if (c === '>') {
            parser.state = S.TEXT
            emitNode(parser, 'ondoctype', parser.doctype)
            parser.doctype = true // just remember that we saw it.
          } else {
            parser.doctype += c
            if (c === '[') {
              parser.state = S.DOCTYPE_DTD
            } else if (isQuote(c)) {
              parser.state = S.DOCTYPE_QUOTED
              parser.q = c
            }
          }
          continue

        case S.DOCTYPE_QUOTED:
          parser.doctype += c
          if (c === parser.q) {
            parser.q = ''
            parser.state = S.DOCTYPE
          }
          continue

        case S.DOCTYPE_DTD:
          if (c === ']') {
            parser.doctype += c
            parser.state = S.DOCTYPE
          } else if (c === '<') {
            parser.state = S.OPEN_WAKA
            parser.startTagPosition = parser.position
          } else if (isQuote(c)) {
            parser.doctype += c
            parser.state = S.DOCTYPE_DTD_QUOTED
            parser.q = c
          } else {
            parser.doctype += c
          }
          continue

        case S.DOCTYPE_DTD_QUOTED:
          parser.doctype += c
          if (c === parser.q) {
            parser.state = S.DOCTYPE_DTD
            parser.q = ''
          }
          continue

        case S.COMMENT:
          if (c === '-') {
            parser.state = S.COMMENT_ENDING
          } else {
            parser.comment += c
          }
          continue

        case S.COMMENT_ENDING:
          if (c === '-') {
            parser.state = S.COMMENT_ENDED
            parser.comment = textopts(parser.opt, parser.comment)
            if (parser.comment) {
              emitNode(parser, 'oncomment', parser.comment)
            }
            parser.comment = ''
          } else {
            parser.comment += '-' + c
            parser.state = S.COMMENT
          }
          continue

        case S.COMMENT_ENDED:
          if (c !== '>') {
            strictFail(parser, 'Malformed comment')
            // allow <!-- blah -- bloo --> in non-strict mode,
            // which is a comment of " blah -- bloo "
            parser.comment += '--' + c
            parser.state = S.COMMENT
          } else if (parser.doctype && parser.doctype !== true) {
            parser.state = S.DOCTYPE_DTD
          } else {
            parser.state = S.TEXT
          }
          continue

        case S.CDATA:
          if (c === ']') {
            parser.state = S.CDATA_ENDING
          } else {
            parser.cdata += c
          }
          continue

        case S.CDATA_ENDING:
          if (c === ']') {
            parser.state = S.CDATA_ENDING_2
          } else {
            parser.cdata += ']' + c
            parser.state = S.CDATA
          }
          continue

        case S.CDATA_ENDING_2:
          if (c === '>') {
            if (parser.cdata) {
              emitNode(parser, 'oncdata', parser.cdata)
            }
            emitNode(parser, 'onclosecdata')
            parser.cdata = ''
            parser.state = S.TEXT
          } else if (c === ']') {
            parser.cdata += ']'
          } else {
            parser.cdata += ']]' + c
            parser.state = S.CDATA
          }
          continue

        case S.PROC_INST:
          if (c === '?') {
            parser.state = S.PROC_INST_ENDING
          } else if (isWhitespace(c)) {
            parser.state = S.PROC_INST_BODY
          } else {
            parser.procInstName += c
          }
          continue

        case S.PROC_INST_BODY:
          if (!parser.procInstBody && isWhitespace(c)) {
            continue
          } else if (c === '?') {
            parser.state = S.PROC_INST_ENDING
          } else {
            parser.procInstBody += c
          }
          continue

        case S.PROC_INST_ENDING:
          if (c === '>') {
            emitNode(parser, 'onprocessinginstruction', {
              name: parser.procInstName,
              body: parser.procInstBody
            })
            parser.procInstName = parser.procInstBody = ''
            parser.state = S.TEXT
          } else {
            parser.procInstBody += '?' + c
            parser.state = S.PROC_INST_BODY
          }
          continue

        case S.OPEN_TAG:
          if (isMatch(nameBody, c)) {
            parser.tagName += c
          } else {
            newTag(parser)
            if (c === '>') {
              openTag(parser)
            } else if (c === '/') {
              parser.state = S.OPEN_TAG_SLASH
            } else {
              if (!isWhitespace(c)) {
                strictFail(parser, 'Invalid character in tag name')
              }
              parser.state = S.ATTRIB
            }
          }
          continue

        case S.OPEN_TAG_SLASH:
          if (c === '>') {
            openTag(parser, true)
            closeTag(parser)
          } else {
            strictFail(parser, 'Forward-slash in opening tag not followed by >')
            parser.state = S.ATTRIB
          }
          continue

        case S.ATTRIB:
          // haven't read the attribute name yet.
          if (isWhitespace(c)) {
            continue
          } else if (c === '>') {
            openTag(parser)
          } else if (c === '/') {
            parser.state = S.OPEN_TAG_SLASH
          } else if (isMatch(nameStart, c)) {
            parser.attribName = c
            parser.attribValue = ''
            parser.state = S.ATTRIB_NAME
          } else {
            strictFail(parser, 'Invalid attribute name')
          }
          continue

        case S.ATTRIB_NAME:
          if (c === '=') {
            parser.state = S.ATTRIB_VALUE
          } else if (c === '>') {
            strictFail(parser, 'Attribute without value')
            parser.attribValue = parser.attribName
            attrib(parser)
            openTag(parser)
          } else if (isWhitespace(c)) {
            parser.state = S.ATTRIB_NAME_SAW_WHITE
          } else if (isMatch(nameBody, c)) {
            parser.attribName += c
          } else {
            strictFail(parser, 'Invalid attribute name')
          }
          continue

        case S.ATTRIB_NAME_SAW_WHITE:
          if (c === '=') {
            parser.state = S.ATTRIB_VALUE
          } else if (isWhitespace(c)) {
            continue
          } else {
            strictFail(parser, 'Attribute without value')
            parser.tag.attributes[parser.attribName] = ''
            parser.attribValue = ''
            emitNode(parser, 'onattribute', {
              name: parser.attribName,
              value: ''
            })
            parser.attribName = ''
            if (c === '>') {
              openTag(parser)
            } else if (isMatch(nameStart, c)) {
              parser.attribName = c
              parser.state = S.ATTRIB_NAME
            } else {
              strictFail(parser, 'Invalid attribute name')
              parser.state = S.ATTRIB
            }
          }
          continue

        case S.ATTRIB_VALUE:
          if (isWhitespace(c)) {
            continue
          } else if (isQuote(c)) {
            parser.q = c
            parser.state = S.ATTRIB_VALUE_QUOTED
          } else {
            if (!parser.opt.unquotedAttributeValues) {
              error(parser, 'Unquoted attribute value')
            }
            parser.state = S.ATTRIB_VALUE_UNQUOTED
            parser.attribValue = c
          }
          continue

        case S.ATTRIB_VALUE_QUOTED:
          if (c !== parser.q) {
            if (c === '&') {
              parser.state = S.ATTRIB_VALUE_ENTITY_Q
            } else {
              parser.attribValue += c
            }
            continue
          }
          attrib(parser)
          parser.q = ''
          parser.state = S.ATTRIB_VALUE_CLOSED
          continue

        case S.ATTRIB_VALUE_CLOSED:
          if (isWhitespace(c)) {
            parser.state = S.ATTRIB
          } else if (c === '>') {
            openTag(parser)
          } else if (c === '/') {
            parser.state = S.OPEN_TAG_SLASH
          } else if (isMatch(nameStart, c)) {
            strictFail(parser, 'No whitespace between attributes')
            parser.attribName = c
            parser.attribValue = ''
            parser.state = S.ATTRIB_NAME
          } else {
            strictFail(parser, 'Invalid attribute name')
          }
          continue

        case S.ATTRIB_VALUE_UNQUOTED:
          if (!isAttribEnd(c)) {
            if (c === '&') {
              parser.state = S.ATTRIB_VALUE_ENTITY_U
            } else {
              parser.attribValue += c
            }
            continue
          }
          attrib(parser)
          if (c === '>') {
            openTag(parser)
          } else {
            parser.state = S.ATTRIB
          }
          continue

        case S.CLOSE_TAG:
          if (!parser.tagName) {
            if (isWhitespace(c)) {
              continue
            } else if (notMatch(nameStart, c)) {
              if (parser.script) {
                parser.script += '</' + c
                parser.state = S.SCRIPT
              } else {
                strictFail(parser, 'Invalid tagname in closing tag.')
              }
            } else {
              parser.tagName = c
            }
          } else if (c === '>') {
            closeTag(parser)
          } else if (isMatch(nameBody, c)) {
            parser.tagName += c
          } else if (parser.script) {
            parser.script += '</' + parser.tagName
            parser.tagName = ''
            parser.state = S.SCRIPT
          } else {
            if (!isWhitespace(c)) {
              strictFail(parser, 'Invalid tagname in closing tag')
            }
            parser.state = S.CLOSE_TAG_SAW_WHITE
          }
          continue

        case S.CLOSE_TAG_SAW_WHITE:
          if (isWhitespace(c)) {
            continue
          }
          if (c === '>') {
            closeTag(parser)
          } else {
            strictFail(parser, 'Invalid characters in closing tag')
          }
          continue

        case S.TEXT_ENTITY:
        case S.ATTRIB_VALUE_ENTITY_Q:
        case S.ATTRIB_VALUE_ENTITY_U:
          var returnState
          var buffer
          switch (parser.state) {
            case S.TEXT_ENTITY:
              returnState = S.TEXT
              buffer = 'textNode'
              break

            case S.ATTRIB_VALUE_ENTITY_Q:
              returnState = S.ATTRIB_VALUE_QUOTED
              buffer = 'attribValue'
              break

            case S.ATTRIB_VALUE_ENTITY_U:
              returnState = S.ATTRIB_VALUE_UNQUOTED
              buffer = 'attribValue'
              break
          }

          if (c === ';') {
            var parsedEntity = parseEntity(parser)
            if (parser.opt.unparsedEntities && !Object.values(sax.XML_ENTITIES).includes(parsedEntity)) {
              parser.entity = ''
              parser.state = returnState
              parser.write(parsedEntity)
            } else {
              parser[buffer] += parsedEntity
              parser.entity = ''
              parser.state = returnState
            }
          } else if (isMatch(parser.entity.length ? entityBody : entityStart, c)) {
            parser.entity += c
          } else {
            strictFail(parser, 'Invalid character in entity name')
            parser[buffer] += '&' + parser.entity + c
            parser.entity = ''
            parser.state = returnState
          }

          continue

        default: /* istanbul ignore next */ {
          throw new Error(parser, 'Unknown state: ' + parser.state)
        }
      }
    } // while

    if (parser.position >= parser.bufferCheckPosition) {
      checkBufferLength(parser)
    }
    return parser
  }

  /*! http://mths.be/fromcodepoint v0.1.0 by @mathias */
  /* istanbul ignore next */
  if (!String.fromCodePoint) {
    (function () {
      var stringFromCharCode = String.fromCharCode
      var floor = Math.floor
      var fromCodePoint = function () {
        var MAX_SIZE = 0x4000
        var codeUnits = []
        var highSurrogate
        var lowSurrogate
        var index = -1
        var length = arguments.length
        if (!length) {
          return ''
        }
        var result = ''
        while (++index < length) {
          var codePoint = Number(arguments[index])
          if (
            !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
            codePoint < 0 || // not a valid Unicode code point
            codePoint > 0x10FFFF || // not a valid Unicode code point
            floor(codePoint) !== codePoint // not an integer
          ) {
            throw RangeError('Invalid code point: ' + codePoint)
          }
          if (codePoint <= 0xFFFF) { // BMP code point
            codeUnits.push(codePoint)
          } else { // Astral code point; split in surrogate halves
            // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
            codePoint -= 0x10000
            highSurrogate = (codePoint >> 10) + 0xD800
            lowSurrogate = (codePoint % 0x400) + 0xDC00
            codeUnits.push(highSurrogate, lowSurrogate)
          }
          if (index + 1 === length || codeUnits.length > MAX_SIZE) {
            result += stringFromCharCode.apply(null, codeUnits)
            codeUnits.length = 0
          }
        }
        return result
      }
      /* istanbul ignore next */
      if (Object.defineProperty) {
        Object.defineProperty(String, 'fromCodePoint', {
          value: fromCodePoint,
          configurable: true,
          writable: true
        })
      } else {
        String.fromCodePoint = fromCodePoint
      }
    }())
  }
})(typeof exports === 'undefined' ? this.sax = {} : exports)
{
  "name": "sax",
  "description": "An evented streaming XML parser in JavaScript",
  "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
  "version": "1.4.1",
  "main": "lib/sax.js",
  "license": "ISC",
  "repository": "git://github.com/isaacs/sax-js.git",
  "files": [
    "lib/sax.js",
    "LICENSE",
    "README.md"
  ],
  "devDependencies": {
    "tap": "^15.1.6"
  },
  "tap": {
    "statements": 79,
    "branches": 75,
    "functions": 80,
    "lines": 79
  }
}MIT License

Copyright (c) 2020 Zurab Benashvili (binier) <zura.bena@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypedEmitter = require("events").EventEmitter;
{
  "name": "tiny-typed-emitter",
  "version": "2.1.0",
  "description": "Fully type-checked EventEmitter",
  "main": "lib/index",
  "repository": "https://github.com/binier/tiny-typed-emitter.git",
  "author": "Zurab Benashvili <zura.benashvili@gmail.com>",
  "license": "MIT",
  "files": [
    "lib/*"
  ],
  "devDependencies": {
    "@types/node": "^13.13.4",
    "typescript": "^3.8.3"
  }
}FROM electronuserland/builder:wine AS build

RUN pwd
RUN ls

WORKDIR /app/

# RUN npm config set //registry.npmjs.org/:_authToken $NPM_TOKEN
RUN git clone https://x-token-auth:$GIT_TOKEN_ELECTRON@bitbucket.org/digital-rally/altmann-viper-electron.git

WORKDIR /app/altmann-viper-electron
#RUN git checkout $GIT_BRANCH
RUN npm ci --production=false
RUN npm run postinstall
RUN npm run build:win

#WORKDIR /app/digital-planner-fe/dist/pwa
#RUN ls


FROM nginx:alpine
WORKDIR /usr/share/nginx/html
RUN rm -rf ./*
COPY --from=build /app/altmann-viper-electron/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/altmann-viper-electron/dist .
ENTRYPOINT ["nginx", "-g", "daemon off;"]
# Define additional MIME types, important for the Electron updater.
types {
    application/x-yaml                      yml yaml;
    application/octet-stream                exe;
}

server {
    listen 80;
    listen [::]:80;

    server_name localhost;

    # The root directory where Nginx looks for files.
    # This must match the WORKDIR and COPY destination in your Dockerfile.
    root /usr/share/nginx/html;

    # Default index files (not strictly necessary for this use case, but good practice).
    index index.html index.htm;

    location / {
        # Try to serve the requested file directly, otherwise return a 404 error.
        try_files $uri $uri/ =404;

        # Enables automatic listing of directory contents.
        # This is useful for debugging to see if your files are present.

        autoindex on;
    }

    # Add headers to prevent caching issues.
    # This ensures the Electron client always receives the latest 'latest.yml'
    # and not a stale version from the cache.
    location = /latest.yml {
        add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
        expires off;
        etag off;
        if_modified_since off;
    }

    # Logging-settings
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
}
"use strict";
const utils = require("@electron-toolkit/utils");
const electron = require("electron");
const path = require("path");
const log = require("electron-log/main.js");
const electronUpdater = require("electron-updater");
const log$1 = require("electron-log");
const url = require("url");
const http = require("http");
const https = require("https");
const windowsIcon = path.join(__dirname, "../../resources/icon.ico");
const linuxIcon = path.join(__dirname, "../../resources/icon.png");
function getAutoUpdater() {
  const { autoUpdater } = electronUpdater;
  return autoUpdater;
}
class AppUpdaterClass {
  constructor() {
    log.initialize();
    log.transports.file.level = "debug";
    const autoUpdater = getAutoUpdater();
    autoUpdater.logger = log;
    autoUpdater.on("error", (err) => {
      log.error("Fehler beim Auto-Update:", err.message);
    });
    autoUpdater.on("update-available", (info) => {
      log.info("An update has been found. The download will start automatically.", info);
    });
    autoUpdater.on("update-not-available", (info) => {
      log.info("No updates found.", info.version);
    });
    autoUpdater.on("update-downloaded", (info) => {
      log.info("Update downloaded, show dialog.");
      electron.dialog.showMessageBox({
        type: "info",
        title: "Update bereit zur Installation",
        message: `Die neue Version ${info.version} wurde heruntergeladen. Starten Sie die Anwendung neu, um das Update zu installieren.`,
        buttons: ["Jetzt neu starten", "Später"]
      }).then((result) => {
        if (result.response === 0) {
          autoUpdater.quitAndInstall();
        }
      });
    });
    autoUpdater.checkForUpdates();
  }
}
class Logger {
  static initialized = false;
  static logPath = path.join(electron.app.getPath("userData"), "logs");
  static logger = log$1;
  /**
   * Initializes the logger once, sets level & path
   */
  static init() {
    if (this.initialized) return;
    this.logger.transports.file.resolvePathFn = () => path.join(this.logPath, "main.log");
    this.logger.transports.file.level = "info";
    this.logger.transports.console.level = "info";
    this.initialized = true;
  }
  static getLogger() {
    this.init();
    return this.logger;
  }
  static setDebugLog() {
    this.logger.transports.file.resolvePathFn = () => path.join(this.logPath, "debug.log");
  }
  static setMainLog() {
    this.logger.transports.file.resolvePathFn = () => path.join(this.logPath, "main.log");
  }
  // Convenience methods
  static info(...args) {
    this.init();
    this.logger.info(...args);
  }
  static error(...args) {
    this.init();
    this.logger.error(...args);
  }
  static debug(...args) {
    this.init();
    this.logger.debug(...args);
  }
  static warn(...args) {
    this.init();
    this.logger.warn(...args);
  }
}
class Reachable {
  static serverUrl = "https://viper.digital-rally.de";
  static timeout = 3e3;
  /**
   * Checks whether the configured server is reachable via a lightweight HTTP(S) `HEAD` request.
   *
   * This method attempts to open a connection to the provided URL (defined in `this.serverUrl`)
   * using either the HTTP or HTTPS protocol, depending on the URL scheme.
   *
   * The request uses the `HEAD` method to avoid downloading any response body and to minimize bandwidth usage.
   * It resolves with `true` if the server responds with status code 200 (OK) or 404 (Not Found),
   * indicating that the server is reachable and processing requests.
   *
   * In case of any connection error, timeout, or malformed URL, the method resolves with `false`.
   * It does **not** throw errors, making it safe for use in connectivity checks without requiring try/catch externally.
   *
   * @returns {Promise<boolean>} A promise that resolves to `true` if the server is reachable, or `false` otherwise.
   */
  static checkServerReachable() {
    return new Promise((resolve) => {
      try {
        const urlObj = new url.URL(this.serverUrl);
        const lib = urlObj.protocol === "https" ? https : http;
        const req = lib.request(
          {
            method: "HEAD",
            host: urlObj.hostname,
            port: urlObj.port,
            path: urlObj.pathname,
            timeout: this.timeout
          },
          (res) => {
            if (!res?.statusCode) resolve(false);
            else resolve(res.statusCode >= 200 && res.statusCode < 400);
          }
        );
        req.on("error", () => resolve(false));
        req.on("timeout", () => {
          req.destroy();
          resolve(false);
        });
        req.end();
      } catch (error) {
        console.error("Error", error);
        resolve(false);
      }
    });
  }
}
const logger$1 = Logger.getLogger();
async function loadFailedServicePage(mainWindow2) {
  logger$1.debug("Site is not Reachable. Show fallback HTML");
  const currentDir = url.fileURLToPath(new URL(".", require("url").pathToFileURL(__filename).href));
  const fallbackPath = path.join(currentDir, "../renderer/index.html");
  logger$1.debug(`fallBackPath: ${fallbackPath}`);
  await mainWindow2.loadFile(fallbackPath);
}
async function loadApp(mainWindow2) {
  const serverUrl = "https://viper.digital-rally.de";
  Logger.setDebugLog();
  logger$1.debug(`ServerUrl is ${serverUrl}`);
  logger$1.error("test error");
  const isReachable = await Reachable.checkServerReachable();
  let serverStatus;
  if (isReachable) {
    logger$1.debug("Site is Reachable");
    await mainWindow2.loadURL(serverUrl);
    serverStatus = "up";
  } else {
    await loadFailedServicePage(mainWindow2);
    serverStatus = "down";
  }
  setInterval(async () => {
    const isServerReachable = await Reachable.checkServerReachable();
    if (!isServerReachable && serverStatus === "up") {
      serverStatus = "down";
      await loadFailedServicePage(mainWindow2);
    }
    if (isServerReachable && serverStatus === "down") {
      serverStatus = "up";
      await mainWindow2.loadFile(serverUrl);
    }
  }, 5e3);
}
const ipcMainHandler = {
  /**
   * Registers an IPC handler to open a given folder in the system's file explorer.
   *
   * This bridge is typically called from the renderer process when the user requests
   * to open a specific directory (e.g., logs, exported files, etc.) via the UI.
   *
   * @example
   * window.myApi.openFolderInExplorer('/path/to/folder');
   */
  openFolderInExplorer: () => {
    electron.ipcMain.handle("open-folder-in-explorer", async (_event, folderPath) => {
      try {
        const result = await electron.shell.openPath(folderPath);
        return result;
      } catch (error) {
        console.error("Failed open the Explorer:", error);
        return String(error);
      }
    });
  },
  /**
   * Registers an IPC bridge that allows the fallback page to trigger a full reload of the Electron app.
   *
   * This is typically used when the frontend is offline and the fallback page offers
   * a "Reload" button. It re-initializes the main window by calling `loadApp(...)`.
   *
   * @param mainWindow - The main Electron browser window instance to reload.
   */
  fullReloadElectronApp: (mainWindow2) => {
    electron.ipcMain.handle("full-reload-electron-app", async () => {
      if (!mainWindow2) return;
      try {
        await loadApp(mainWindow2);
      } catch (err) {
        console.error("Reload failed:", err);
      }
    });
  }
};
let mainWindow;
const logger = Logger.getLogger();
const __filename$1 = url.fileURLToPath(require("url").pathToFileURL(__filename).href);
const __dirname$1 = path.dirname(__filename$1);
const IOT_PORT = 3e3;
const server = http.createServer((req, res) => {
  let body = "";
  req.on("data", (chunk) => body += chunk);
  req.on("end", () => {
    logger.log(`${req.method} ${req.url}`);
    if (body) {
      try {
        const data = JSON.parse(body);
        for (const tag of data) {
          if (tag?.data?.idHex && mainWindow) {
            logger.log("found data: ", tag);
            mainWindow.webContents.send("tag-read", tag.data.idHex);
          } else {
            mainWindow?.webContents.send("debug-notify", "could not convert hex to text");
          }
        }
      } catch (error) {
        logger.error(error);
        logger.error(body);
        mainWindow?.webContents.send("debug-notify", "error parsing json data");
      }
    } else {
      mainWindow?.webContents.send("debug-notify", "request without body");
    }
    res.writeHead(200);
    res.end();
  });
});
server.listen(IOT_PORT, () => logger.log("Listening on http://localhost:3000"));
function createWindow() {
  logger.log("Start App");
  mainWindow = new electron.BrowserWindow({
    width: 2e3,
    height: 1e3,
    minHeight: 1e3,
    minWidth: 1e3,
    show: false,
    // autoHideMenuBar: is.dev ? false : true,
    ...process.platform === "linux" ? { linuxIcon } : { windowsIcon },
    webPreferences: {
      // devTools: is.dev ? false : true,
      preload: path.join(__dirname$1, "../preload/index.js"),
      sandbox: true,
      nodeIntegration: false,
      contextIsolation: true
    }
  });
  try {
    loadApp(mainWindow);
    mainWindow.on("ready-to-show", () => {
      mainWindow.show();
    });
    mainWindow.webContents.openDevTools();
    mainWindow.webContents.setWindowOpenHandler((details) => {
      electron.shell.openExternal(details.url);
      return { action: "deny" };
    });
    ipcMainHandler.openFolderInExplorer();
    ipcMainHandler.fullReloadElectronApp(mainWindow);
    mainWindow.webContents.on("did-fail-load", () => {
      Logger.setDebugLog();
      logger.debug("The connection to the web server has been interrupted. Loading fallback page.");
      loadApp(mainWindow);
    });
    mainWindow.webContents.on("unresponsive", () => {
      logger.log("onUnresponsive");
    });
    mainWindow.webContents.on("responsive", () => {
      logger.log("onResponsive");
    });
  } catch (err) {
    logger.error("Error on start electron app", err);
  }
}
electron.app.whenReady().then(() => {
  utils.electronApp.setAppUserModelId("com.altmann.viper");
  electron.app.on("browser-window-created", (_, window) => {
    utils.optimizer.watchWindowShortcuts(window);
  });
  electron.ipcMain.on("ping", () => logger.info("pong"));
  new AppUpdaterClass();
  createWindow();
  electron.app.on("activate", function() {
    if (mainWindow === void 0) {
      void createWindow();
    }
  });
});
electron.app.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    electron.app.quit();
  }
});
"use strict";
const electron = require("electron");
try {
  electron.contextBridge.exposeInMainWorld("myApi", {
    openFolderInExplorer: (folderPath) => {
      return electron.ipcRenderer.invoke("open-folder-in-explorer", folderPath);
    },
    fullReloadElectronApp: () => {
      return electron.ipcRenderer.invoke("full-reload-electron-app");
    }
  });
  electron.contextBridge.exposeInMainWorld("scanner", {
    onTag: (callback) => {
      electron.ipcRenderer.on("tag-read", (_event, epc) => callback(epc));
    },
    removeTagListeners: () => {
      electron.ipcRenderer.removeAllListeners("tag-read");
    },
    onNotify: (callback) => {
      electron.ipcRenderer.on("debug-notify", (_event, message) => callback(message));
    }
  });
} catch (error) {
  console.error("Failed to expose preload API:", error);
}
<!doctype html>
<html lang="de">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Altmann viper [offline]</title>
    <style>
      :root {
        --primary: #004fa2;
        --secondary: #144579;
        --accent: #e96a22;
        --bg: #f4f6f9;
        --text: #1e1e1e;
      }

      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }

      html,
      body {
        width: 100%;
        height: 100%;
        font-family:
          -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
        background-color: var(--bg);
        color: var(--text);
        display: flex;
        align-items: center;
        justify-content: center;
      }

      .container {
        text-align: center;
        padding: 2rem;
        background: white;
        border-radius: 12px;
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        max-width: 400px;
      }

      .title {
        font-size: 1.5rem;
        font-weight: 600;
        color: var(--primary);
        margin-bottom: 1rem;
      }

      .message {
        font-size: 1rem;
        margin-bottom: 2rem;
        color: var(--secondary);
      }

      .reload-btn {
        background-color: var(--accent);
        color: white;
        border: none;
        padding: 0.75rem 1.5rem;
        border-radius: 6px;
        font-size: 1rem;
        cursor: pointer;
        transition: background-color 0.3s ease;
      }

      .reload-btn:hover {
        background-color: #d15a17;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="title">Altmann Viper</div>
      <div class="message">
        Die Anwendung ist derzeit offline.<br />Bitte überprüfen Sie Ihre Verbindung oder versuchen
        Sie es später erneut.
      </div>
      <button class="reload-btn" onclick="manageReloadApp()">Seite neu laden</button>
    </div>
  </body>
</html>
<script>
  /**
   * Triggers a full reload of the Electron application via the preload bridge (`window.electronAPI`).
   *
   * This function ensures that the reload is safely routed through the Electron main process,
   * allowing centralized logic (e.g., connection checks, fallback handling) to be executed.
   * Requires a properly exposed `reloadApp` handler in the preload context.
   */
  function manageReloadApp() {
    if (window.myApi) {
      window.myApi.fullReloadElectronApp()
    }
  }
</script>
{
  "name": "viper-electron",
  "version": "1.0.2",
  "description": "A minimal Electron application with TypeScript",
  "homepage": "https://viper-electron.staging.digital-rally.cloud",
  "main": "./out/main/index.js",
  "author": "info@digital-rally.de",
  "dependencies": {
    "@electron-toolkit/preload": "^3.0.2",
    "@electron-toolkit/utils": "^4.0.0",
    "electron-log": "5.4.3",
    "electron-updater": "^6.3.9"
  }
}