leafrelay 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../node_modules/.pnpm/diff-match-patch@1.0.5/node_modules/diff-match-patch/index.js","../../daemon/src/codec.ts","../../daemon/src/paths.ts","../../core/src/api/base.ts","../../core/src/api/overleafRealtimeSocket.ts","../../core/src/core/logger.ts","../../core/src/api/requestScheduler.ts","../../core/src/api/extendedBase.ts","../../core/src/api/socketio.ts","../../core/src/core/projectTypes.ts","../../core/src/node/config.ts","../../core/src/node/localFileSystem.ts","../../core/src/node/projectSettings.ts","../../core/src/node/serve.ts","../../core/src/sync/ignore.ts","../../core/src/sync/remoteProject.ts","../../core/src/sync/syncEngine.ts","../../core/src/sync/checkpoint.ts","../../core/src/sync/threeWayMerge.ts","../../core/src/node/syncStateStore.ts","../../../node_modules/.pnpm/mime@4.1.0/node_modules/mime/dist/types/other.js","../../../node_modules/.pnpm/mime@4.1.0/node_modules/mime/dist/types/standard.js","../../../node_modules/.pnpm/mime@4.1.0/node_modules/mime/dist/src/Mime.js","../../../node_modules/.pnpm/mime@4.1.0/node_modules/mime/dist/src/index.js","../../../node_modules/.pnpm/uuid@14.0.1/node_modules/uuid/dist-node/stringify.js","../../../node_modules/.pnpm/uuid@14.0.1/node_modules/uuid/dist-node/rng.js","../../../node_modules/.pnpm/uuid@14.0.1/node_modules/uuid/dist-node/v4.js","../../../node_modules/.pnpm/chokidar@5.0.0/node_modules/chokidar/index.js","../../../node_modules/.pnpm/readdirp@5.1.1/node_modules/readdirp/index.js","../../../node_modules/.pnpm/chokidar@5.0.0/node_modules/chokidar/handler.js","../../../node_modules/.pnpm/balanced-match@4.0.4/node_modules/balanced-match/src/index.ts","../../../node_modules/.pnpm/brace-expansion@5.0.9/node_modules/brace-expansion/src/index.ts","../../../node_modules/.pnpm/minimatch@10.2.6/node_modules/minimatch/src/assert-valid-pattern.ts","../../../node_modules/.pnpm/minimatch@10.2.6/node_modules/minimatch/src/brace-expressions.ts","../../../node_modules/.pnpm/minimatch@10.2.6/node_modules/minimatch/src/unescape.ts","../../../node_modules/.pnpm/minimatch@10.2.6/node_modules/minimatch/src/ast.ts","../../../node_modules/.pnpm/minimatch@10.2.6/node_modules/minimatch/src/escape.ts","../../../node_modules/.pnpm/minimatch@10.2.6/node_modules/minimatch/src/index.ts","../../../node_modules/.pnpm/node-diff3@3.2.1/node_modules/node-diff3/src/diff3.mjs","../../daemon/src/networkRuntime.ts","../../daemon/src/replicaRegistry.ts","../../daemon/src/server.ts","../../protocol/src/index.ts","../../daemon/src/transport.ts","../../daemon/src/client.ts","../src/daemonClient.ts","../src/serve.ts"],"sourcesContent":["/**\n * Diff Match and Patch\n * Copyright 2018 The diff-match-patch Authors.\n * https://github.com/google/diff-match-patch\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Computes the difference between two texts to create a patch.\n * Applies the patch onto another text, allowing for errors.\n * @author fraser@google.com (Neil Fraser)\n */\n\n/**\n * Class containing the diff, match and patch methods.\n * @constructor\n */\nvar diff_match_patch = function() {\n\n // Defaults.\n // Redefine these in your program to override the defaults.\n\n // Number of seconds to map a diff before giving up (0 for infinity).\n this.Diff_Timeout = 1.0;\n // Cost of an empty edit operation in terms of edit characters.\n this.Diff_EditCost = 4;\n // At what point is no match declared (0.0 = perfection, 1.0 = very loose).\n this.Match_Threshold = 0.5;\n // How far to search for a match (0 = exact location, 1000+ = broad match).\n // A match this many characters away from the expected location will add\n // 1.0 to the score (0.0 is a perfect match).\n this.Match_Distance = 1000;\n // When deleting a large block of text (over ~64 characters), how close do\n // the contents have to be to match the expected contents. (0.0 = perfection,\n // 1.0 = very loose). Note that Match_Threshold controls how closely the\n // end points of a delete need to match.\n this.Patch_DeleteThreshold = 0.5;\n // Chunk size for context length.\n this.Patch_Margin = 4;\n\n // The number of bits in an int.\n this.Match_MaxBits = 32;\n};\n\n\n// DIFF FUNCTIONS\n\n\n/**\n * The data structure representing a diff is an array of tuples:\n * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]\n * which means: delete 'Hello', add 'Goodbye' and keep ' world.'\n */\nvar DIFF_DELETE = -1;\nvar DIFF_INSERT = 1;\nvar DIFF_EQUAL = 0;\n\n/**\n * Class representing one diff tuple.\n * ~Attempts to look like a two-element array (which is what this used to be).~\n * Constructor returns an actual two-element array, to allow destructing @JackuB\n * See https://github.com/JackuB/diff-match-patch/issues/14 for details\n * @param {number} op Operation, one of: DIFF_DELETE, DIFF_INSERT, DIFF_EQUAL.\n * @param {string} text Text to be deleted, inserted, or retained.\n * @constructor\n */\ndiff_match_patch.Diff = function(op, text) {\n return [op, text];\n};\n\n/**\n * Find the differences between two texts. Simplifies the problem by stripping\n * any common prefix or suffix off the texts before diffing.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {boolean=} opt_checklines Optional speedup flag. If present and false,\n * then don't run a line-level diff first to identify the changed areas.\n * Defaults to true, which does a faster, slightly less optimal diff.\n * @param {number=} opt_deadline Optional time when the diff should be complete\n * by. Used internally for recursive calls. Users should set DiffTimeout\n * instead.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_main = function(text1, text2, opt_checklines,\n opt_deadline) {\n // Set a deadline by which time the diff must be complete.\n if (typeof opt_deadline == 'undefined') {\n if (this.Diff_Timeout <= 0) {\n opt_deadline = Number.MAX_VALUE;\n } else {\n opt_deadline = (new Date).getTime() + this.Diff_Timeout * 1000;\n }\n }\n var deadline = opt_deadline;\n\n // Check for null inputs.\n if (text1 == null || text2 == null) {\n throw new Error('Null input. (diff_main)');\n }\n\n // Check for equality (speedup).\n if (text1 == text2) {\n if (text1) {\n return [new diff_match_patch.Diff(DIFF_EQUAL, text1)];\n }\n return [];\n }\n\n if (typeof opt_checklines == 'undefined') {\n opt_checklines = true;\n }\n var checklines = opt_checklines;\n\n // Trim off common prefix (speedup).\n var commonlength = this.diff_commonPrefix(text1, text2);\n var commonprefix = text1.substring(0, commonlength);\n text1 = text1.substring(commonlength);\n text2 = text2.substring(commonlength);\n\n // Trim off common suffix (speedup).\n commonlength = this.diff_commonSuffix(text1, text2);\n var commonsuffix = text1.substring(text1.length - commonlength);\n text1 = text1.substring(0, text1.length - commonlength);\n text2 = text2.substring(0, text2.length - commonlength);\n\n // Compute the diff on the middle block.\n var diffs = this.diff_compute_(text1, text2, checklines, deadline);\n\n // Restore the prefix and suffix.\n if (commonprefix) {\n diffs.unshift(new diff_match_patch.Diff(DIFF_EQUAL, commonprefix));\n }\n if (commonsuffix) {\n diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, commonsuffix));\n }\n this.diff_cleanupMerge(diffs);\n return diffs;\n};\n\n\n/**\n * Find the differences between two texts. Assumes that the texts do not\n * have any common prefix or suffix.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {boolean} checklines Speedup flag. If false, then don't run a\n * line-level diff first to identify the changed areas.\n * If true, then run a faster, slightly less optimal diff.\n * @param {number} deadline Time when the diff should be complete by.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @private\n */\ndiff_match_patch.prototype.diff_compute_ = function(text1, text2, checklines,\n deadline) {\n var diffs;\n\n if (!text1) {\n // Just add some text (speedup).\n return [new diff_match_patch.Diff(DIFF_INSERT, text2)];\n }\n\n if (!text2) {\n // Just delete some text (speedup).\n return [new diff_match_patch.Diff(DIFF_DELETE, text1)];\n }\n\n var longtext = text1.length > text2.length ? text1 : text2;\n var shorttext = text1.length > text2.length ? text2 : text1;\n var i = longtext.indexOf(shorttext);\n if (i != -1) {\n // Shorter text is inside the longer text (speedup).\n diffs = [new diff_match_patch.Diff(DIFF_INSERT, longtext.substring(0, i)),\n new diff_match_patch.Diff(DIFF_EQUAL, shorttext),\n new diff_match_patch.Diff(DIFF_INSERT,\n longtext.substring(i + shorttext.length))];\n // Swap insertions for deletions if diff is reversed.\n if (text1.length > text2.length) {\n diffs[0][0] = diffs[2][0] = DIFF_DELETE;\n }\n return diffs;\n }\n\n if (shorttext.length == 1) {\n // Single character string.\n // After the previous speedup, the character can't be an equality.\n return [new diff_match_patch.Diff(DIFF_DELETE, text1),\n new diff_match_patch.Diff(DIFF_INSERT, text2)];\n }\n\n // Check to see if the problem can be split in two.\n var hm = this.diff_halfMatch_(text1, text2);\n if (hm) {\n // A half-match was found, sort out the return data.\n var text1_a = hm[0];\n var text1_b = hm[1];\n var text2_a = hm[2];\n var text2_b = hm[3];\n var mid_common = hm[4];\n // Send both pairs off for separate processing.\n var diffs_a = this.diff_main(text1_a, text2_a, checklines, deadline);\n var diffs_b = this.diff_main(text1_b, text2_b, checklines, deadline);\n // Merge the results.\n return diffs_a.concat([new diff_match_patch.Diff(DIFF_EQUAL, mid_common)],\n diffs_b);\n }\n\n if (checklines && text1.length > 100 && text2.length > 100) {\n return this.diff_lineMode_(text1, text2, deadline);\n }\n\n return this.diff_bisect_(text1, text2, deadline);\n};\n\n\n/**\n * Do a quick line-level diff on both strings, then rediff the parts for\n * greater accuracy.\n * This speedup can produce non-minimal diffs.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {number} deadline Time when the diff should be complete by.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @private\n */\ndiff_match_patch.prototype.diff_lineMode_ = function(text1, text2, deadline) {\n // Scan the text on a line-by-line basis first.\n var a = this.diff_linesToChars_(text1, text2);\n text1 = a.chars1;\n text2 = a.chars2;\n var linearray = a.lineArray;\n\n var diffs = this.diff_main(text1, text2, false, deadline);\n\n // Convert the diff back to original text.\n this.diff_charsToLines_(diffs, linearray);\n // Eliminate freak matches (e.g. blank lines)\n this.diff_cleanupSemantic(diffs);\n\n // Rediff any replacement blocks, this time character-by-character.\n // Add a dummy entry at the end.\n diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, ''));\n var pointer = 0;\n var count_delete = 0;\n var count_insert = 0;\n var text_delete = '';\n var text_insert = '';\n while (pointer < diffs.length) {\n switch (diffs[pointer][0]) {\n case DIFF_INSERT:\n count_insert++;\n text_insert += diffs[pointer][1];\n break;\n case DIFF_DELETE:\n count_delete++;\n text_delete += diffs[pointer][1];\n break;\n case DIFF_EQUAL:\n // Upon reaching an equality, check for prior redundancies.\n if (count_delete >= 1 && count_insert >= 1) {\n // Delete the offending records and add the merged ones.\n diffs.splice(pointer - count_delete - count_insert,\n count_delete + count_insert);\n pointer = pointer - count_delete - count_insert;\n var subDiff =\n this.diff_main(text_delete, text_insert, false, deadline);\n for (var j = subDiff.length - 1; j >= 0; j--) {\n diffs.splice(pointer, 0, subDiff[j]);\n }\n pointer = pointer + subDiff.length;\n }\n count_insert = 0;\n count_delete = 0;\n text_delete = '';\n text_insert = '';\n break;\n }\n pointer++;\n }\n diffs.pop(); // Remove the dummy entry at the end.\n\n return diffs;\n};\n\n\n/**\n * Find the 'middle snake' of a diff, split the problem in two\n * and return the recursively constructed diff.\n * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {number} deadline Time at which to bail if not yet complete.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @private\n */\ndiff_match_patch.prototype.diff_bisect_ = function(text1, text2, deadline) {\n // Cache the text lengths to prevent multiple calls.\n var text1_length = text1.length;\n var text2_length = text2.length;\n var max_d = Math.ceil((text1_length + text2_length) / 2);\n var v_offset = max_d;\n var v_length = 2 * max_d;\n var v1 = new Array(v_length);\n var v2 = new Array(v_length);\n // Setting all elements to -1 is faster in Chrome & Firefox than mixing\n // integers and undefined.\n for (var x = 0; x < v_length; x++) {\n v1[x] = -1;\n v2[x] = -1;\n }\n v1[v_offset + 1] = 0;\n v2[v_offset + 1] = 0;\n var delta = text1_length - text2_length;\n // If the total number of characters is odd, then the front path will collide\n // with the reverse path.\n var front = (delta % 2 != 0);\n // Offsets for start and end of k loop.\n // Prevents mapping of space beyond the grid.\n var k1start = 0;\n var k1end = 0;\n var k2start = 0;\n var k2end = 0;\n for (var d = 0; d < max_d; d++) {\n // Bail out if deadline is reached.\n if ((new Date()).getTime() > deadline) {\n break;\n }\n\n // Walk the front path one step.\n for (var k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {\n var k1_offset = v_offset + k1;\n var x1;\n if (k1 == -d || (k1 != d && v1[k1_offset - 1] < v1[k1_offset + 1])) {\n x1 = v1[k1_offset + 1];\n } else {\n x1 = v1[k1_offset - 1] + 1;\n }\n var y1 = x1 - k1;\n while (x1 < text1_length && y1 < text2_length &&\n text1.charAt(x1) == text2.charAt(y1)) {\n x1++;\n y1++;\n }\n v1[k1_offset] = x1;\n if (x1 > text1_length) {\n // Ran off the right of the graph.\n k1end += 2;\n } else if (y1 > text2_length) {\n // Ran off the bottom of the graph.\n k1start += 2;\n } else if (front) {\n var k2_offset = v_offset + delta - k1;\n if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] != -1) {\n // Mirror x2 onto top-left coordinate system.\n var x2 = text1_length - v2[k2_offset];\n if (x1 >= x2) {\n // Overlap detected.\n return this.diff_bisectSplit_(text1, text2, x1, y1, deadline);\n }\n }\n }\n }\n\n // Walk the reverse path one step.\n for (var k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {\n var k2_offset = v_offset + k2;\n var x2;\n if (k2 == -d || (k2 != d && v2[k2_offset - 1] < v2[k2_offset + 1])) {\n x2 = v2[k2_offset + 1];\n } else {\n x2 = v2[k2_offset - 1] + 1;\n }\n var y2 = x2 - k2;\n while (x2 < text1_length && y2 < text2_length &&\n text1.charAt(text1_length - x2 - 1) ==\n text2.charAt(text2_length - y2 - 1)) {\n x2++;\n y2++;\n }\n v2[k2_offset] = x2;\n if (x2 > text1_length) {\n // Ran off the left of the graph.\n k2end += 2;\n } else if (y2 > text2_length) {\n // Ran off the top of the graph.\n k2start += 2;\n } else if (!front) {\n var k1_offset = v_offset + delta - k2;\n if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] != -1) {\n var x1 = v1[k1_offset];\n var y1 = v_offset + x1 - k1_offset;\n // Mirror x2 onto top-left coordinate system.\n x2 = text1_length - x2;\n if (x1 >= x2) {\n // Overlap detected.\n return this.diff_bisectSplit_(text1, text2, x1, y1, deadline);\n }\n }\n }\n }\n }\n // Diff took too long and hit the deadline or\n // number of diffs equals number of characters, no commonality at all.\n return [new diff_match_patch.Diff(DIFF_DELETE, text1),\n new diff_match_patch.Diff(DIFF_INSERT, text2)];\n};\n\n\n/**\n * Given the location of the 'middle snake', split the diff in two parts\n * and recurse.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {number} x Index of split point in text1.\n * @param {number} y Index of split point in text2.\n * @param {number} deadline Time at which to bail if not yet complete.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @private\n */\ndiff_match_patch.prototype.diff_bisectSplit_ = function(text1, text2, x, y,\n deadline) {\n var text1a = text1.substring(0, x);\n var text2a = text2.substring(0, y);\n var text1b = text1.substring(x);\n var text2b = text2.substring(y);\n\n // Compute both diffs serially.\n var diffs = this.diff_main(text1a, text2a, false, deadline);\n var diffsb = this.diff_main(text1b, text2b, false, deadline);\n\n return diffs.concat(diffsb);\n};\n\n\n/**\n * Split two texts into an array of strings. Reduce the texts to a string of\n * hashes where each Unicode character represents one line.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}\n * An object containing the encoded text1, the encoded text2 and\n * the array of unique strings.\n * The zeroth element of the array of unique strings is intentionally blank.\n * @private\n */\ndiff_match_patch.prototype.diff_linesToChars_ = function(text1, text2) {\n var lineArray = []; // e.g. lineArray[4] == 'Hello\\n'\n var lineHash = {}; // e.g. lineHash['Hello\\n'] == 4\n\n // '\\x00' is a valid character, but various debuggers don't like it.\n // So we'll insert a junk entry to avoid generating a null character.\n lineArray[0] = '';\n\n /**\n * Split a text into an array of strings. Reduce the texts to a string of\n * hashes where each Unicode character represents one line.\n * Modifies linearray and linehash through being a closure.\n * @param {string} text String to encode.\n * @return {string} Encoded string.\n * @private\n */\n function diff_linesToCharsMunge_(text) {\n var chars = '';\n // Walk the text, pulling out a substring for each line.\n // text.split('\\n') would would temporarily double our memory footprint.\n // Modifying text would create many large strings to garbage collect.\n var lineStart = 0;\n var lineEnd = -1;\n // Keeping our own length variable is faster than looking it up.\n var lineArrayLength = lineArray.length;\n while (lineEnd < text.length - 1) {\n lineEnd = text.indexOf('\\n', lineStart);\n if (lineEnd == -1) {\n lineEnd = text.length - 1;\n }\n var line = text.substring(lineStart, lineEnd + 1);\n\n if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) :\n (lineHash[line] !== undefined)) {\n chars += String.fromCharCode(lineHash[line]);\n } else {\n if (lineArrayLength == maxLines) {\n // Bail out at 65535 because\n // String.fromCharCode(65536) == String.fromCharCode(0)\n line = text.substring(lineStart);\n lineEnd = text.length;\n }\n chars += String.fromCharCode(lineArrayLength);\n lineHash[line] = lineArrayLength;\n lineArray[lineArrayLength++] = line;\n }\n lineStart = lineEnd + 1;\n }\n return chars;\n }\n // Allocate 2/3rds of the space for text1, the rest for text2.\n var maxLines = 40000;\n var chars1 = diff_linesToCharsMunge_(text1);\n maxLines = 65535;\n var chars2 = diff_linesToCharsMunge_(text2);\n return {chars1: chars1, chars2: chars2, lineArray: lineArray};\n};\n\n\n/**\n * Rehydrate the text in a diff from a string of line hashes to real lines of\n * text.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @param {!Array.<string>} lineArray Array of unique strings.\n * @private\n */\ndiff_match_patch.prototype.diff_charsToLines_ = function(diffs, lineArray) {\n for (var i = 0; i < diffs.length; i++) {\n var chars = diffs[i][1];\n var text = [];\n for (var j = 0; j < chars.length; j++) {\n text[j] = lineArray[chars.charCodeAt(j)];\n }\n diffs[i][1] = text.join('');\n }\n};\n\n\n/**\n * Determine the common prefix of two strings.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {number} The number of characters common to the start of each\n * string.\n */\ndiff_match_patch.prototype.diff_commonPrefix = function(text1, text2) {\n // Quick check for common null cases.\n if (!text1 || !text2 || text1.charAt(0) != text2.charAt(0)) {\n return 0;\n }\n // Binary search.\n // Performance analysis: https://neil.fraser.name/news/2007/10/09/\n var pointermin = 0;\n var pointermax = Math.min(text1.length, text2.length);\n var pointermid = pointermax;\n var pointerstart = 0;\n while (pointermin < pointermid) {\n if (text1.substring(pointerstart, pointermid) ==\n text2.substring(pointerstart, pointermid)) {\n pointermin = pointermid;\n pointerstart = pointermin;\n } else {\n pointermax = pointermid;\n }\n pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);\n }\n return pointermid;\n};\n\n\n/**\n * Determine the common suffix of two strings.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {number} The number of characters common to the end of each string.\n */\ndiff_match_patch.prototype.diff_commonSuffix = function(text1, text2) {\n // Quick check for common null cases.\n if (!text1 || !text2 ||\n text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)) {\n return 0;\n }\n // Binary search.\n // Performance analysis: https://neil.fraser.name/news/2007/10/09/\n var pointermin = 0;\n var pointermax = Math.min(text1.length, text2.length);\n var pointermid = pointermax;\n var pointerend = 0;\n while (pointermin < pointermid) {\n if (text1.substring(text1.length - pointermid, text1.length - pointerend) ==\n text2.substring(text2.length - pointermid, text2.length - pointerend)) {\n pointermin = pointermid;\n pointerend = pointermin;\n } else {\n pointermax = pointermid;\n }\n pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);\n }\n return pointermid;\n};\n\n\n/**\n * Determine if the suffix of one string is the prefix of another.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {number} The number of characters common to the end of the first\n * string and the start of the second string.\n * @private\n */\ndiff_match_patch.prototype.diff_commonOverlap_ = function(text1, text2) {\n // Cache the text lengths to prevent multiple calls.\n var text1_length = text1.length;\n var text2_length = text2.length;\n // Eliminate the null case.\n if (text1_length == 0 || text2_length == 0) {\n return 0;\n }\n // Truncate the longer string.\n if (text1_length > text2_length) {\n text1 = text1.substring(text1_length - text2_length);\n } else if (text1_length < text2_length) {\n text2 = text2.substring(0, text1_length);\n }\n var text_length = Math.min(text1_length, text2_length);\n // Quick check for the worst case.\n if (text1 == text2) {\n return text_length;\n }\n\n // Start by looking for a single character match\n // and increase length until no match is found.\n // Performance analysis: https://neil.fraser.name/news/2010/11/04/\n var best = 0;\n var length = 1;\n while (true) {\n var pattern = text1.substring(text_length - length);\n var found = text2.indexOf(pattern);\n if (found == -1) {\n return best;\n }\n length += found;\n if (found == 0 || text1.substring(text_length - length) ==\n text2.substring(0, length)) {\n best = length;\n length++;\n }\n }\n};\n\n\n/**\n * Do the two texts share a substring which is at least half the length of the\n * longer text?\n * This speedup can produce non-minimal diffs.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {Array.<string>} Five element Array, containing the prefix of\n * text1, the suffix of text1, the prefix of text2, the suffix of\n * text2 and the common middle. Or null if there was no match.\n * @private\n */\ndiff_match_patch.prototype.diff_halfMatch_ = function(text1, text2) {\n if (this.Diff_Timeout <= 0) {\n // Don't risk returning a non-optimal diff if we have unlimited time.\n return null;\n }\n var longtext = text1.length > text2.length ? text1 : text2;\n var shorttext = text1.length > text2.length ? text2 : text1;\n if (longtext.length < 4 || shorttext.length * 2 < longtext.length) {\n return null; // Pointless.\n }\n var dmp = this; // 'this' becomes 'window' in a closure.\n\n /**\n * Does a substring of shorttext exist within longtext such that the substring\n * is at least half the length of longtext?\n * Closure, but does not reference any external variables.\n * @param {string} longtext Longer string.\n * @param {string} shorttext Shorter string.\n * @param {number} i Start index of quarter length substring within longtext.\n * @return {Array.<string>} Five element Array, containing the prefix of\n * longtext, the suffix of longtext, the prefix of shorttext, the suffix\n * of shorttext and the common middle. Or null if there was no match.\n * @private\n */\n function diff_halfMatchI_(longtext, shorttext, i) {\n // Start with a 1/4 length substring at position i as a seed.\n var seed = longtext.substring(i, i + Math.floor(longtext.length / 4));\n var j = -1;\n var best_common = '';\n var best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b;\n while ((j = shorttext.indexOf(seed, j + 1)) != -1) {\n var prefixLength = dmp.diff_commonPrefix(longtext.substring(i),\n shorttext.substring(j));\n var suffixLength = dmp.diff_commonSuffix(longtext.substring(0, i),\n shorttext.substring(0, j));\n if (best_common.length < suffixLength + prefixLength) {\n best_common = shorttext.substring(j - suffixLength, j) +\n shorttext.substring(j, j + prefixLength);\n best_longtext_a = longtext.substring(0, i - suffixLength);\n best_longtext_b = longtext.substring(i + prefixLength);\n best_shorttext_a = shorttext.substring(0, j - suffixLength);\n best_shorttext_b = shorttext.substring(j + prefixLength);\n }\n }\n if (best_common.length * 2 >= longtext.length) {\n return [best_longtext_a, best_longtext_b,\n best_shorttext_a, best_shorttext_b, best_common];\n } else {\n return null;\n }\n }\n\n // First check if the second quarter is the seed for a half-match.\n var hm1 = diff_halfMatchI_(longtext, shorttext,\n Math.ceil(longtext.length / 4));\n // Check again based on the third quarter.\n var hm2 = diff_halfMatchI_(longtext, shorttext,\n Math.ceil(longtext.length / 2));\n var hm;\n if (!hm1 && !hm2) {\n return null;\n } else if (!hm2) {\n hm = hm1;\n } else if (!hm1) {\n hm = hm2;\n } else {\n // Both matched. Select the longest.\n hm = hm1[4].length > hm2[4].length ? hm1 : hm2;\n }\n\n // A half-match was found, sort out the return data.\n var text1_a, text1_b, text2_a, text2_b;\n if (text1.length > text2.length) {\n text1_a = hm[0];\n text1_b = hm[1];\n text2_a = hm[2];\n text2_b = hm[3];\n } else {\n text2_a = hm[0];\n text2_b = hm[1];\n text1_a = hm[2];\n text1_b = hm[3];\n }\n var mid_common = hm[4];\n return [text1_a, text1_b, text2_a, text2_b, mid_common];\n};\n\n\n/**\n * Reduce the number of edits by eliminating semantically trivial equalities.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_cleanupSemantic = function(diffs) {\n var changes = false;\n var equalities = []; // Stack of indices where equalities are found.\n var equalitiesLength = 0; // Keeping our own length var is faster in JS.\n /** @type {?string} */\n var lastEquality = null;\n // Always equal to diffs[equalities[equalitiesLength - 1]][1]\n var pointer = 0; // Index of current position.\n // Number of characters that changed prior to the equality.\n var length_insertions1 = 0;\n var length_deletions1 = 0;\n // Number of characters that changed after the equality.\n var length_insertions2 = 0;\n var length_deletions2 = 0;\n while (pointer < diffs.length) {\n if (diffs[pointer][0] == DIFF_EQUAL) { // Equality found.\n equalities[equalitiesLength++] = pointer;\n length_insertions1 = length_insertions2;\n length_deletions1 = length_deletions2;\n length_insertions2 = 0;\n length_deletions2 = 0;\n lastEquality = diffs[pointer][1];\n } else { // An insertion or deletion.\n if (diffs[pointer][0] == DIFF_INSERT) {\n length_insertions2 += diffs[pointer][1].length;\n } else {\n length_deletions2 += diffs[pointer][1].length;\n }\n // Eliminate an equality that is smaller or equal to the edits on both\n // sides of it.\n if (lastEquality && (lastEquality.length <=\n Math.max(length_insertions1, length_deletions1)) &&\n (lastEquality.length <= Math.max(length_insertions2,\n length_deletions2))) {\n // Duplicate record.\n diffs.splice(equalities[equalitiesLength - 1], 0,\n new diff_match_patch.Diff(DIFF_DELETE, lastEquality));\n // Change second copy to insert.\n diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;\n // Throw away the equality we just deleted.\n equalitiesLength--;\n // Throw away the previous equality (it needs to be reevaluated).\n equalitiesLength--;\n pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;\n length_insertions1 = 0; // Reset the counters.\n length_deletions1 = 0;\n length_insertions2 = 0;\n length_deletions2 = 0;\n lastEquality = null;\n changes = true;\n }\n }\n pointer++;\n }\n\n // Normalize the diff.\n if (changes) {\n this.diff_cleanupMerge(diffs);\n }\n this.diff_cleanupSemanticLossless(diffs);\n\n // Find any overlaps between deletions and insertions.\n // e.g: <del>abcxxx</del><ins>xxxdef</ins>\n // -> <del>abc</del>xxx<ins>def</ins>\n // e.g: <del>xxxabc</del><ins>defxxx</ins>\n // -> <ins>def</ins>xxx<del>abc</del>\n // Only extract an overlap if it is as big as the edit ahead or behind it.\n pointer = 1;\n while (pointer < diffs.length) {\n if (diffs[pointer - 1][0] == DIFF_DELETE &&\n diffs[pointer][0] == DIFF_INSERT) {\n var deletion = diffs[pointer - 1][1];\n var insertion = diffs[pointer][1];\n var overlap_length1 = this.diff_commonOverlap_(deletion, insertion);\n var overlap_length2 = this.diff_commonOverlap_(insertion, deletion);\n if (overlap_length1 >= overlap_length2) {\n if (overlap_length1 >= deletion.length / 2 ||\n overlap_length1 >= insertion.length / 2) {\n // Overlap found. Insert an equality and trim the surrounding edits.\n diffs.splice(pointer, 0, new diff_match_patch.Diff(DIFF_EQUAL,\n insertion.substring(0, overlap_length1)));\n diffs[pointer - 1][1] =\n deletion.substring(0, deletion.length - overlap_length1);\n diffs[pointer + 1][1] = insertion.substring(overlap_length1);\n pointer++;\n }\n } else {\n if (overlap_length2 >= deletion.length / 2 ||\n overlap_length2 >= insertion.length / 2) {\n // Reverse overlap found.\n // Insert an equality and swap and trim the surrounding edits.\n diffs.splice(pointer, 0, new diff_match_patch.Diff(DIFF_EQUAL,\n deletion.substring(0, overlap_length2)));\n diffs[pointer - 1][0] = DIFF_INSERT;\n diffs[pointer - 1][1] =\n insertion.substring(0, insertion.length - overlap_length2);\n diffs[pointer + 1][0] = DIFF_DELETE;\n diffs[pointer + 1][1] =\n deletion.substring(overlap_length2);\n pointer++;\n }\n }\n pointer++;\n }\n pointer++;\n }\n};\n\n\n/**\n * Look for single edits surrounded on both sides by equalities\n * which can be shifted sideways to align the edit to a word boundary.\n * e.g: The c<ins>at c</ins>ame. -> The <ins>cat </ins>came.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_cleanupSemanticLossless = function(diffs) {\n /**\n * Given two strings, compute a score representing whether the internal\n * boundary falls on logical boundaries.\n * Scores range from 6 (best) to 0 (worst).\n * Closure, but does not reference any external variables.\n * @param {string} one First string.\n * @param {string} two Second string.\n * @return {number} The score.\n * @private\n */\n function diff_cleanupSemanticScore_(one, two) {\n if (!one || !two) {\n // Edges are the best.\n return 6;\n }\n\n // Each port of this function behaves slightly differently due to\n // subtle differences in each language's definition of things like\n // 'whitespace'. Since this function's purpose is largely cosmetic,\n // the choice has been made to use each language's native features\n // rather than force total conformity.\n var char1 = one.charAt(one.length - 1);\n var char2 = two.charAt(0);\n var nonAlphaNumeric1 = char1.match(diff_match_patch.nonAlphaNumericRegex_);\n var nonAlphaNumeric2 = char2.match(diff_match_patch.nonAlphaNumericRegex_);\n var whitespace1 = nonAlphaNumeric1 &&\n char1.match(diff_match_patch.whitespaceRegex_);\n var whitespace2 = nonAlphaNumeric2 &&\n char2.match(diff_match_patch.whitespaceRegex_);\n var lineBreak1 = whitespace1 &&\n char1.match(diff_match_patch.linebreakRegex_);\n var lineBreak2 = whitespace2 &&\n char2.match(diff_match_patch.linebreakRegex_);\n var blankLine1 = lineBreak1 &&\n one.match(diff_match_patch.blanklineEndRegex_);\n var blankLine2 = lineBreak2 &&\n two.match(diff_match_patch.blanklineStartRegex_);\n\n if (blankLine1 || blankLine2) {\n // Five points for blank lines.\n return 5;\n } else if (lineBreak1 || lineBreak2) {\n // Four points for line breaks.\n return 4;\n } else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) {\n // Three points for end of sentences.\n return 3;\n } else if (whitespace1 || whitespace2) {\n // Two points for whitespace.\n return 2;\n } else if (nonAlphaNumeric1 || nonAlphaNumeric2) {\n // One point for non-alphanumeric.\n return 1;\n }\n return 0;\n }\n\n var pointer = 1;\n // Intentionally ignore the first and last element (don't need checking).\n while (pointer < diffs.length - 1) {\n if (diffs[pointer - 1][0] == DIFF_EQUAL &&\n diffs[pointer + 1][0] == DIFF_EQUAL) {\n // This is a single edit surrounded by equalities.\n var equality1 = diffs[pointer - 1][1];\n var edit = diffs[pointer][1];\n var equality2 = diffs[pointer + 1][1];\n\n // First, shift the edit as far left as possible.\n var commonOffset = this.diff_commonSuffix(equality1, edit);\n if (commonOffset) {\n var commonString = edit.substring(edit.length - commonOffset);\n equality1 = equality1.substring(0, equality1.length - commonOffset);\n edit = commonString + edit.substring(0, edit.length - commonOffset);\n equality2 = commonString + equality2;\n }\n\n // Second, step character by character right, looking for the best fit.\n var bestEquality1 = equality1;\n var bestEdit = edit;\n var bestEquality2 = equality2;\n var bestScore = diff_cleanupSemanticScore_(equality1, edit) +\n diff_cleanupSemanticScore_(edit, equality2);\n while (edit.charAt(0) === equality2.charAt(0)) {\n equality1 += edit.charAt(0);\n edit = edit.substring(1) + equality2.charAt(0);\n equality2 = equality2.substring(1);\n var score = diff_cleanupSemanticScore_(equality1, edit) +\n diff_cleanupSemanticScore_(edit, equality2);\n // The >= encourages trailing rather than leading whitespace on edits.\n if (score >= bestScore) {\n bestScore = score;\n bestEquality1 = equality1;\n bestEdit = edit;\n bestEquality2 = equality2;\n }\n }\n\n if (diffs[pointer - 1][1] != bestEquality1) {\n // We have an improvement, save it back to the diff.\n if (bestEquality1) {\n diffs[pointer - 1][1] = bestEquality1;\n } else {\n diffs.splice(pointer - 1, 1);\n pointer--;\n }\n diffs[pointer][1] = bestEdit;\n if (bestEquality2) {\n diffs[pointer + 1][1] = bestEquality2;\n } else {\n diffs.splice(pointer + 1, 1);\n pointer--;\n }\n }\n }\n pointer++;\n }\n};\n\n// Define some regex patterns for matching boundaries.\ndiff_match_patch.nonAlphaNumericRegex_ = /[^a-zA-Z0-9]/;\ndiff_match_patch.whitespaceRegex_ = /\\s/;\ndiff_match_patch.linebreakRegex_ = /[\\r\\n]/;\ndiff_match_patch.blanklineEndRegex_ = /\\n\\r?\\n$/;\ndiff_match_patch.blanklineStartRegex_ = /^\\r?\\n\\r?\\n/;\n\n/**\n * Reduce the number of edits by eliminating operationally trivial equalities.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_cleanupEfficiency = function(diffs) {\n var changes = false;\n var equalities = []; // Stack of indices where equalities are found.\n var equalitiesLength = 0; // Keeping our own length var is faster in JS.\n /** @type {?string} */\n var lastEquality = null;\n // Always equal to diffs[equalities[equalitiesLength - 1]][1]\n var pointer = 0; // Index of current position.\n // Is there an insertion operation before the last equality.\n var pre_ins = false;\n // Is there a deletion operation before the last equality.\n var pre_del = false;\n // Is there an insertion operation after the last equality.\n var post_ins = false;\n // Is there a deletion operation after the last equality.\n var post_del = false;\n while (pointer < diffs.length) {\n if (diffs[pointer][0] == DIFF_EQUAL) { // Equality found.\n if (diffs[pointer][1].length < this.Diff_EditCost &&\n (post_ins || post_del)) {\n // Candidate found.\n equalities[equalitiesLength++] = pointer;\n pre_ins = post_ins;\n pre_del = post_del;\n lastEquality = diffs[pointer][1];\n } else {\n // Not a candidate, and can never become one.\n equalitiesLength = 0;\n lastEquality = null;\n }\n post_ins = post_del = false;\n } else { // An insertion or deletion.\n if (diffs[pointer][0] == DIFF_DELETE) {\n post_del = true;\n } else {\n post_ins = true;\n }\n /*\n * Five types to be split:\n * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>\n * <ins>A</ins>X<ins>C</ins><del>D</del>\n * <ins>A</ins><del>B</del>X<ins>C</ins>\n * <ins>A</del>X<ins>C</ins><del>D</del>\n * <ins>A</ins><del>B</del>X<del>C</del>\n */\n if (lastEquality && ((pre_ins && pre_del && post_ins && post_del) ||\n ((lastEquality.length < this.Diff_EditCost / 2) &&\n (pre_ins + pre_del + post_ins + post_del) == 3))) {\n // Duplicate record.\n diffs.splice(equalities[equalitiesLength - 1], 0,\n new diff_match_patch.Diff(DIFF_DELETE, lastEquality));\n // Change second copy to insert.\n diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;\n equalitiesLength--; // Throw away the equality we just deleted;\n lastEquality = null;\n if (pre_ins && pre_del) {\n // No changes made which could affect previous entry, keep going.\n post_ins = post_del = true;\n equalitiesLength = 0;\n } else {\n equalitiesLength--; // Throw away the previous equality.\n pointer = equalitiesLength > 0 ?\n equalities[equalitiesLength - 1] : -1;\n post_ins = post_del = false;\n }\n changes = true;\n }\n }\n pointer++;\n }\n\n if (changes) {\n this.diff_cleanupMerge(diffs);\n }\n};\n\n\n/**\n * Reorder and merge like edit sections. Merge equalities.\n * Any edit section can move as long as it doesn't cross an equality.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_cleanupMerge = function(diffs) {\n // Add a dummy entry at the end.\n diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, ''));\n var pointer = 0;\n var count_delete = 0;\n var count_insert = 0;\n var text_delete = '';\n var text_insert = '';\n var commonlength;\n while (pointer < diffs.length) {\n switch (diffs[pointer][0]) {\n case DIFF_INSERT:\n count_insert++;\n text_insert += diffs[pointer][1];\n pointer++;\n break;\n case DIFF_DELETE:\n count_delete++;\n text_delete += diffs[pointer][1];\n pointer++;\n break;\n case DIFF_EQUAL:\n // Upon reaching an equality, check for prior redundancies.\n if (count_delete + count_insert > 1) {\n if (count_delete !== 0 && count_insert !== 0) {\n // Factor out any common prefixies.\n commonlength = this.diff_commonPrefix(text_insert, text_delete);\n if (commonlength !== 0) {\n if ((pointer - count_delete - count_insert) > 0 &&\n diffs[pointer - count_delete - count_insert - 1][0] ==\n DIFF_EQUAL) {\n diffs[pointer - count_delete - count_insert - 1][1] +=\n text_insert.substring(0, commonlength);\n } else {\n diffs.splice(0, 0, new diff_match_patch.Diff(DIFF_EQUAL,\n text_insert.substring(0, commonlength)));\n pointer++;\n }\n text_insert = text_insert.substring(commonlength);\n text_delete = text_delete.substring(commonlength);\n }\n // Factor out any common suffixies.\n commonlength = this.diff_commonSuffix(text_insert, text_delete);\n if (commonlength !== 0) {\n diffs[pointer][1] = text_insert.substring(text_insert.length -\n commonlength) + diffs[pointer][1];\n text_insert = text_insert.substring(0, text_insert.length -\n commonlength);\n text_delete = text_delete.substring(0, text_delete.length -\n commonlength);\n }\n }\n // Delete the offending records and add the merged ones.\n pointer -= count_delete + count_insert;\n diffs.splice(pointer, count_delete + count_insert);\n if (text_delete.length) {\n diffs.splice(pointer, 0,\n new diff_match_patch.Diff(DIFF_DELETE, text_delete));\n pointer++;\n }\n if (text_insert.length) {\n diffs.splice(pointer, 0,\n new diff_match_patch.Diff(DIFF_INSERT, text_insert));\n pointer++;\n }\n pointer++;\n } else if (pointer !== 0 && diffs[pointer - 1][0] == DIFF_EQUAL) {\n // Merge this equality with the previous one.\n diffs[pointer - 1][1] += diffs[pointer][1];\n diffs.splice(pointer, 1);\n } else {\n pointer++;\n }\n count_insert = 0;\n count_delete = 0;\n text_delete = '';\n text_insert = '';\n break;\n }\n }\n if (diffs[diffs.length - 1][1] === '') {\n diffs.pop(); // Remove the dummy entry at the end.\n }\n\n // Second pass: look for single edits surrounded on both sides by equalities\n // which can be shifted sideways to eliminate an equality.\n // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC\n var changes = false;\n pointer = 1;\n // Intentionally ignore the first and last element (don't need checking).\n while (pointer < diffs.length - 1) {\n if (diffs[pointer - 1][0] == DIFF_EQUAL &&\n diffs[pointer + 1][0] == DIFF_EQUAL) {\n // This is a single edit surrounded by equalities.\n if (diffs[pointer][1].substring(diffs[pointer][1].length -\n diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) {\n // Shift the edit over the previous equality.\n diffs[pointer][1] = diffs[pointer - 1][1] +\n diffs[pointer][1].substring(0, diffs[pointer][1].length -\n diffs[pointer - 1][1].length);\n diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];\n diffs.splice(pointer - 1, 1);\n changes = true;\n } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) ==\n diffs[pointer + 1][1]) {\n // Shift the edit over the next equality.\n diffs[pointer - 1][1] += diffs[pointer + 1][1];\n diffs[pointer][1] =\n diffs[pointer][1].substring(diffs[pointer + 1][1].length) +\n diffs[pointer + 1][1];\n diffs.splice(pointer + 1, 1);\n changes = true;\n }\n }\n pointer++;\n }\n // If shifts were made, the diff needs reordering and another shift sweep.\n if (changes) {\n this.diff_cleanupMerge(diffs);\n }\n};\n\n\n/**\n * loc is a location in text1, compute and return the equivalent location in\n * text2.\n * e.g. 'The cat' vs 'The big cat', 1->1, 5->8\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @param {number} loc Location within text1.\n * @return {number} Location within text2.\n */\ndiff_match_patch.prototype.diff_xIndex = function(diffs, loc) {\n var chars1 = 0;\n var chars2 = 0;\n var last_chars1 = 0;\n var last_chars2 = 0;\n var x;\n for (x = 0; x < diffs.length; x++) {\n if (diffs[x][0] !== DIFF_INSERT) { // Equality or deletion.\n chars1 += diffs[x][1].length;\n }\n if (diffs[x][0] !== DIFF_DELETE) { // Equality or insertion.\n chars2 += diffs[x][1].length;\n }\n if (chars1 > loc) { // Overshot the location.\n break;\n }\n last_chars1 = chars1;\n last_chars2 = chars2;\n }\n // Was the location was deleted?\n if (diffs.length != x && diffs[x][0] === DIFF_DELETE) {\n return last_chars2;\n }\n // Add the remaining character length.\n return last_chars2 + (loc - last_chars1);\n};\n\n\n/**\n * Convert a diff array into a pretty HTML report.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {string} HTML representation.\n */\ndiff_match_patch.prototype.diff_prettyHtml = function(diffs) {\n var html = [];\n var pattern_amp = /&/g;\n var pattern_lt = /</g;\n var pattern_gt = />/g;\n var pattern_para = /\\n/g;\n for (var x = 0; x < diffs.length; x++) {\n var op = diffs[x][0]; // Operation (insert, delete, equal)\n var data = diffs[x][1]; // Text of change.\n var text = data.replace(pattern_amp, '&amp;').replace(pattern_lt, '&lt;')\n .replace(pattern_gt, '&gt;').replace(pattern_para, '&para;<br>');\n switch (op) {\n case DIFF_INSERT:\n html[x] = '<ins style=\"background:#e6ffe6;\">' + text + '</ins>';\n break;\n case DIFF_DELETE:\n html[x] = '<del style=\"background:#ffe6e6;\">' + text + '</del>';\n break;\n case DIFF_EQUAL:\n html[x] = '<span>' + text + '</span>';\n break;\n }\n }\n return html.join('');\n};\n\n\n/**\n * Compute and return the source text (all equalities and deletions).\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {string} Source text.\n */\ndiff_match_patch.prototype.diff_text1 = function(diffs) {\n var text = [];\n for (var x = 0; x < diffs.length; x++) {\n if (diffs[x][0] !== DIFF_INSERT) {\n text[x] = diffs[x][1];\n }\n }\n return text.join('');\n};\n\n\n/**\n * Compute and return the destination text (all equalities and insertions).\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {string} Destination text.\n */\ndiff_match_patch.prototype.diff_text2 = function(diffs) {\n var text = [];\n for (var x = 0; x < diffs.length; x++) {\n if (diffs[x][0] !== DIFF_DELETE) {\n text[x] = diffs[x][1];\n }\n }\n return text.join('');\n};\n\n\n/**\n * Compute the Levenshtein distance; the number of inserted, deleted or\n * substituted characters.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {number} Number of changes.\n */\ndiff_match_patch.prototype.diff_levenshtein = function(diffs) {\n var levenshtein = 0;\n var insertions = 0;\n var deletions = 0;\n for (var x = 0; x < diffs.length; x++) {\n var op = diffs[x][0];\n var data = diffs[x][1];\n switch (op) {\n case DIFF_INSERT:\n insertions += data.length;\n break;\n case DIFF_DELETE:\n deletions += data.length;\n break;\n case DIFF_EQUAL:\n // A deletion and an insertion is one substitution.\n levenshtein += Math.max(insertions, deletions);\n insertions = 0;\n deletions = 0;\n break;\n }\n }\n levenshtein += Math.max(insertions, deletions);\n return levenshtein;\n};\n\n\n/**\n * Crush the diff into an encoded string which describes the operations\n * required to transform text1 into text2.\n * E.g. =3\\t-2\\t+ing -> Keep 3 chars, delete 2 chars, insert 'ing'.\n * Operations are tab-separated. Inserted text is escaped using %xx notation.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {string} Delta text.\n */\ndiff_match_patch.prototype.diff_toDelta = function(diffs) {\n var text = [];\n for (var x = 0; x < diffs.length; x++) {\n switch (diffs[x][0]) {\n case DIFF_INSERT:\n text[x] = '+' + encodeURI(diffs[x][1]);\n break;\n case DIFF_DELETE:\n text[x] = '-' + diffs[x][1].length;\n break;\n case DIFF_EQUAL:\n text[x] = '=' + diffs[x][1].length;\n break;\n }\n }\n return text.join('\\t').replace(/%20/g, ' ');\n};\n\n\n/**\n * Given the original text1, and an encoded string which describes the\n * operations required to transform text1 into text2, compute the full diff.\n * @param {string} text1 Source string for the diff.\n * @param {string} delta Delta text.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @throws {!Error} If invalid input.\n */\ndiff_match_patch.prototype.diff_fromDelta = function(text1, delta) {\n var diffs = [];\n var diffsLength = 0; // Keeping our own length var is faster in JS.\n var pointer = 0; // Cursor in text1\n var tokens = delta.split(/\\t/g);\n for (var x = 0; x < tokens.length; x++) {\n // Each token begins with a one character parameter which specifies the\n // operation of this token (delete, insert, equality).\n var param = tokens[x].substring(1);\n switch (tokens[x].charAt(0)) {\n case '+':\n try {\n diffs[diffsLength++] =\n new diff_match_patch.Diff(DIFF_INSERT, decodeURI(param));\n } catch (ex) {\n // Malformed URI sequence.\n throw new Error('Illegal escape in diff_fromDelta: ' + param);\n }\n break;\n case '-':\n // Fall through.\n case '=':\n var n = parseInt(param, 10);\n if (isNaN(n) || n < 0) {\n throw new Error('Invalid number in diff_fromDelta: ' + param);\n }\n var text = text1.substring(pointer, pointer += n);\n if (tokens[x].charAt(0) == '=') {\n diffs[diffsLength++] = new diff_match_patch.Diff(DIFF_EQUAL, text);\n } else {\n diffs[diffsLength++] = new diff_match_patch.Diff(DIFF_DELETE, text);\n }\n break;\n default:\n // Blank tokens are ok (from a trailing \\t).\n // Anything else is an error.\n if (tokens[x]) {\n throw new Error('Invalid diff operation in diff_fromDelta: ' +\n tokens[x]);\n }\n }\n }\n if (pointer != text1.length) {\n throw new Error('Delta length (' + pointer +\n ') does not equal source text length (' + text1.length + ').');\n }\n return diffs;\n};\n\n\n// MATCH FUNCTIONS\n\n\n/**\n * Locate the best instance of 'pattern' in 'text' near 'loc'.\n * @param {string} text The text to search.\n * @param {string} pattern The pattern to search for.\n * @param {number} loc The location to search around.\n * @return {number} Best match index or -1.\n */\ndiff_match_patch.prototype.match_main = function(text, pattern, loc) {\n // Check for null inputs.\n if (text == null || pattern == null || loc == null) {\n throw new Error('Null input. (match_main)');\n }\n\n loc = Math.max(0, Math.min(loc, text.length));\n if (text == pattern) {\n // Shortcut (potentially not guaranteed by the algorithm)\n return 0;\n } else if (!text.length) {\n // Nothing to match.\n return -1;\n } else if (text.substring(loc, loc + pattern.length) == pattern) {\n // Perfect match at the perfect spot! (Includes case of null pattern)\n return loc;\n } else {\n // Do a fuzzy compare.\n return this.match_bitap_(text, pattern, loc);\n }\n};\n\n\n/**\n * Locate the best instance of 'pattern' in 'text' near 'loc' using the\n * Bitap algorithm.\n * @param {string} text The text to search.\n * @param {string} pattern The pattern to search for.\n * @param {number} loc The location to search around.\n * @return {number} Best match index or -1.\n * @private\n */\ndiff_match_patch.prototype.match_bitap_ = function(text, pattern, loc) {\n if (pattern.length > this.Match_MaxBits) {\n throw new Error('Pattern too long for this browser.');\n }\n\n // Initialise the alphabet.\n var s = this.match_alphabet_(pattern);\n\n var dmp = this; // 'this' becomes 'window' in a closure.\n\n /**\n * Compute and return the score for a match with e errors and x location.\n * Accesses loc and pattern through being a closure.\n * @param {number} e Number of errors in match.\n * @param {number} x Location of match.\n * @return {number} Overall score for match (0.0 = good, 1.0 = bad).\n * @private\n */\n function match_bitapScore_(e, x) {\n var accuracy = e / pattern.length;\n var proximity = Math.abs(loc - x);\n if (!dmp.Match_Distance) {\n // Dodge divide by zero error.\n return proximity ? 1.0 : accuracy;\n }\n return accuracy + (proximity / dmp.Match_Distance);\n }\n\n // Highest score beyond which we give up.\n var score_threshold = this.Match_Threshold;\n // Is there a nearby exact match? (speedup)\n var best_loc = text.indexOf(pattern, loc);\n if (best_loc != -1) {\n score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold);\n // What about in the other direction? (speedup)\n best_loc = text.lastIndexOf(pattern, loc + pattern.length);\n if (best_loc != -1) {\n score_threshold =\n Math.min(match_bitapScore_(0, best_loc), score_threshold);\n }\n }\n\n // Initialise the bit arrays.\n var matchmask = 1 << (pattern.length - 1);\n best_loc = -1;\n\n var bin_min, bin_mid;\n var bin_max = pattern.length + text.length;\n var last_rd;\n for (var d = 0; d < pattern.length; d++) {\n // Scan for the best match; each iteration allows for one more error.\n // Run a binary search to determine how far from 'loc' we can stray at this\n // error level.\n bin_min = 0;\n bin_mid = bin_max;\n while (bin_min < bin_mid) {\n if (match_bitapScore_(d, loc + bin_mid) <= score_threshold) {\n bin_min = bin_mid;\n } else {\n bin_max = bin_mid;\n }\n bin_mid = Math.floor((bin_max - bin_min) / 2 + bin_min);\n }\n // Use the result from this iteration as the maximum for the next.\n bin_max = bin_mid;\n var start = Math.max(1, loc - bin_mid + 1);\n var finish = Math.min(loc + bin_mid, text.length) + pattern.length;\n\n var rd = Array(finish + 2);\n rd[finish + 1] = (1 << d) - 1;\n for (var j = finish; j >= start; j--) {\n // The alphabet (s) is a sparse hash, so the following line generates\n // warnings.\n var charMatch = s[text.charAt(j - 1)];\n if (d === 0) { // First pass: exact match.\n rd[j] = ((rd[j + 1] << 1) | 1) & charMatch;\n } else { // Subsequent passes: fuzzy match.\n rd[j] = (((rd[j + 1] << 1) | 1) & charMatch) |\n (((last_rd[j + 1] | last_rd[j]) << 1) | 1) |\n last_rd[j + 1];\n }\n if (rd[j] & matchmask) {\n var score = match_bitapScore_(d, j - 1);\n // This match will almost certainly be better than any existing match.\n // But check anyway.\n if (score <= score_threshold) {\n // Told you so.\n score_threshold = score;\n best_loc = j - 1;\n if (best_loc > loc) {\n // When passing loc, don't exceed our current distance from loc.\n start = Math.max(1, 2 * loc - best_loc);\n } else {\n // Already passed loc, downhill from here on in.\n break;\n }\n }\n }\n }\n // No hope for a (better) match at greater error levels.\n if (match_bitapScore_(d + 1, loc) > score_threshold) {\n break;\n }\n last_rd = rd;\n }\n return best_loc;\n};\n\n\n/**\n * Initialise the alphabet for the Bitap algorithm.\n * @param {string} pattern The text to encode.\n * @return {!Object} Hash of character locations.\n * @private\n */\ndiff_match_patch.prototype.match_alphabet_ = function(pattern) {\n var s = {};\n for (var i = 0; i < pattern.length; i++) {\n s[pattern.charAt(i)] = 0;\n }\n for (var i = 0; i < pattern.length; i++) {\n s[pattern.charAt(i)] |= 1 << (pattern.length - i - 1);\n }\n return s;\n};\n\n\n// PATCH FUNCTIONS\n\n\n/**\n * Increase the context until it is unique,\n * but don't let the pattern expand beyond Match_MaxBits.\n * @param {!diff_match_patch.patch_obj} patch The patch to grow.\n * @param {string} text Source text.\n * @private\n */\ndiff_match_patch.prototype.patch_addContext_ = function(patch, text) {\n if (text.length == 0) {\n return;\n }\n if (patch.start2 === null) {\n throw Error('patch not initialized');\n }\n var pattern = text.substring(patch.start2, patch.start2 + patch.length1);\n var padding = 0;\n\n // Look for the first and last matches of pattern in text. If two different\n // matches are found, increase the pattern length.\n while (text.indexOf(pattern) != text.lastIndexOf(pattern) &&\n pattern.length < this.Match_MaxBits - this.Patch_Margin -\n this.Patch_Margin) {\n padding += this.Patch_Margin;\n pattern = text.substring(patch.start2 - padding,\n patch.start2 + patch.length1 + padding);\n }\n // Add one chunk for good luck.\n padding += this.Patch_Margin;\n\n // Add the prefix.\n var prefix = text.substring(patch.start2 - padding, patch.start2);\n if (prefix) {\n patch.diffs.unshift(new diff_match_patch.Diff(DIFF_EQUAL, prefix));\n }\n // Add the suffix.\n var suffix = text.substring(patch.start2 + patch.length1,\n patch.start2 + patch.length1 + padding);\n if (suffix) {\n patch.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, suffix));\n }\n\n // Roll back the start points.\n patch.start1 -= prefix.length;\n patch.start2 -= prefix.length;\n // Extend the lengths.\n patch.length1 += prefix.length + suffix.length;\n patch.length2 += prefix.length + suffix.length;\n};\n\n\n/**\n * Compute a list of patches to turn text1 into text2.\n * Use diffs if provided, otherwise compute it ourselves.\n * There are four ways to call this function, depending on what data is\n * available to the caller:\n * Method 1:\n * a = text1, b = text2\n * Method 2:\n * a = diffs\n * Method 3 (optimal):\n * a = text1, b = diffs\n * Method 4 (deprecated, use method 3):\n * a = text1, b = text2, c = diffs\n *\n * @param {string|!Array.<!diff_match_patch.Diff>} a text1 (methods 1,3,4) or\n * Array of diff tuples for text1 to text2 (method 2).\n * @param {string|!Array.<!diff_match_patch.Diff>=} opt_b text2 (methods 1,4) or\n * Array of diff tuples for text1 to text2 (method 3) or undefined (method 2).\n * @param {string|!Array.<!diff_match_patch.Diff>=} opt_c Array of diff tuples\n * for text1 to text2 (method 4) or undefined (methods 1,2,3).\n * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.\n */\ndiff_match_patch.prototype.patch_make = function(a, opt_b, opt_c) {\n var text1, diffs;\n if (typeof a == 'string' && typeof opt_b == 'string' &&\n typeof opt_c == 'undefined') {\n // Method 1: text1, text2\n // Compute diffs from text1 and text2.\n text1 = /** @type {string} */(a);\n diffs = this.diff_main(text1, /** @type {string} */(opt_b), true);\n if (diffs.length > 2) {\n this.diff_cleanupSemantic(diffs);\n this.diff_cleanupEfficiency(diffs);\n }\n } else if (a && typeof a == 'object' && typeof opt_b == 'undefined' &&\n typeof opt_c == 'undefined') {\n // Method 2: diffs\n // Compute text1 from diffs.\n diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(a);\n text1 = this.diff_text1(diffs);\n } else if (typeof a == 'string' && opt_b && typeof opt_b == 'object' &&\n typeof opt_c == 'undefined') {\n // Method 3: text1, diffs\n text1 = /** @type {string} */(a);\n diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(opt_b);\n } else if (typeof a == 'string' && typeof opt_b == 'string' &&\n opt_c && typeof opt_c == 'object') {\n // Method 4: text1, text2, diffs\n // text2 is not used.\n text1 = /** @type {string} */(a);\n diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(opt_c);\n } else {\n throw new Error('Unknown call format to patch_make.');\n }\n\n if (diffs.length === 0) {\n return []; // Get rid of the null case.\n }\n var patches = [];\n var patch = new diff_match_patch.patch_obj();\n var patchDiffLength = 0; // Keeping our own length var is faster in JS.\n var char_count1 = 0; // Number of characters into the text1 string.\n var char_count2 = 0; // Number of characters into the text2 string.\n // Start with text1 (prepatch_text) and apply the diffs until we arrive at\n // text2 (postpatch_text). We recreate the patches one by one to determine\n // context info.\n var prepatch_text = text1;\n var postpatch_text = text1;\n for (var x = 0; x < diffs.length; x++) {\n var diff_type = diffs[x][0];\n var diff_text = diffs[x][1];\n\n if (!patchDiffLength && diff_type !== DIFF_EQUAL) {\n // A new patch starts here.\n patch.start1 = char_count1;\n patch.start2 = char_count2;\n }\n\n switch (diff_type) {\n case DIFF_INSERT:\n patch.diffs[patchDiffLength++] = diffs[x];\n patch.length2 += diff_text.length;\n postpatch_text = postpatch_text.substring(0, char_count2) + diff_text +\n postpatch_text.substring(char_count2);\n break;\n case DIFF_DELETE:\n patch.length1 += diff_text.length;\n patch.diffs[patchDiffLength++] = diffs[x];\n postpatch_text = postpatch_text.substring(0, char_count2) +\n postpatch_text.substring(char_count2 +\n diff_text.length);\n break;\n case DIFF_EQUAL:\n if (diff_text.length <= 2 * this.Patch_Margin &&\n patchDiffLength && diffs.length != x + 1) {\n // Small equality inside a patch.\n patch.diffs[patchDiffLength++] = diffs[x];\n patch.length1 += diff_text.length;\n patch.length2 += diff_text.length;\n } else if (diff_text.length >= 2 * this.Patch_Margin) {\n // Time for a new patch.\n if (patchDiffLength) {\n this.patch_addContext_(patch, prepatch_text);\n patches.push(patch);\n patch = new diff_match_patch.patch_obj();\n patchDiffLength = 0;\n // Unlike Unidiff, our patch lists have a rolling context.\n // https://github.com/google/diff-match-patch/wiki/Unidiff\n // Update prepatch text & pos to reflect the application of the\n // just completed patch.\n prepatch_text = postpatch_text;\n char_count1 = char_count2;\n }\n }\n break;\n }\n\n // Update the current character count.\n if (diff_type !== DIFF_INSERT) {\n char_count1 += diff_text.length;\n }\n if (diff_type !== DIFF_DELETE) {\n char_count2 += diff_text.length;\n }\n }\n // Pick up the leftover patch if not empty.\n if (patchDiffLength) {\n this.patch_addContext_(patch, prepatch_text);\n patches.push(patch);\n }\n\n return patches;\n};\n\n\n/**\n * Given an array of patches, return another array that is identical.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.\n */\ndiff_match_patch.prototype.patch_deepCopy = function(patches) {\n // Making deep copies is hard in JavaScript.\n var patchesCopy = [];\n for (var x = 0; x < patches.length; x++) {\n var patch = patches[x];\n var patchCopy = new diff_match_patch.patch_obj();\n patchCopy.diffs = [];\n for (var y = 0; y < patch.diffs.length; y++) {\n patchCopy.diffs[y] =\n new diff_match_patch.Diff(patch.diffs[y][0], patch.diffs[y][1]);\n }\n patchCopy.start1 = patch.start1;\n patchCopy.start2 = patch.start2;\n patchCopy.length1 = patch.length1;\n patchCopy.length2 = patch.length2;\n patchesCopy[x] = patchCopy;\n }\n return patchesCopy;\n};\n\n\n/**\n * Merge a set of patches onto the text. Return a patched text, as well\n * as a list of true/false values indicating which patches were applied.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n * @param {string} text Old text.\n * @return {!Array.<string|!Array.<boolean>>} Two element Array, containing the\n * new text and an array of boolean values.\n */\ndiff_match_patch.prototype.patch_apply = function(patches, text) {\n if (patches.length == 0) {\n return [text, []];\n }\n\n // Deep copy the patches so that no changes are made to originals.\n patches = this.patch_deepCopy(patches);\n\n var nullPadding = this.patch_addPadding(patches);\n text = nullPadding + text + nullPadding;\n\n this.patch_splitMax(patches);\n // delta keeps track of the offset between the expected and actual location\n // of the previous patch. If there are patches expected at positions 10 and\n // 20, but the first patch was found at 12, delta is 2 and the second patch\n // has an effective expected position of 22.\n var delta = 0;\n var results = [];\n for (var x = 0; x < patches.length; x++) {\n var expected_loc = patches[x].start2 + delta;\n var text1 = this.diff_text1(patches[x].diffs);\n var start_loc;\n var end_loc = -1;\n if (text1.length > this.Match_MaxBits) {\n // patch_splitMax will only provide an oversized pattern in the case of\n // a monster delete.\n start_loc = this.match_main(text, text1.substring(0, this.Match_MaxBits),\n expected_loc);\n if (start_loc != -1) {\n end_loc = this.match_main(text,\n text1.substring(text1.length - this.Match_MaxBits),\n expected_loc + text1.length - this.Match_MaxBits);\n if (end_loc == -1 || start_loc >= end_loc) {\n // Can't find valid trailing context. Drop this patch.\n start_loc = -1;\n }\n }\n } else {\n start_loc = this.match_main(text, text1, expected_loc);\n }\n if (start_loc == -1) {\n // No match found. :(\n results[x] = false;\n // Subtract the delta for this failed patch from subsequent patches.\n delta -= patches[x].length2 - patches[x].length1;\n } else {\n // Found a match. :)\n results[x] = true;\n delta = start_loc - expected_loc;\n var text2;\n if (end_loc == -1) {\n text2 = text.substring(start_loc, start_loc + text1.length);\n } else {\n text2 = text.substring(start_loc, end_loc + this.Match_MaxBits);\n }\n if (text1 == text2) {\n // Perfect match, just shove the replacement text in.\n text = text.substring(0, start_loc) +\n this.diff_text2(patches[x].diffs) +\n text.substring(start_loc + text1.length);\n } else {\n // Imperfect match. Run a diff to get a framework of equivalent\n // indices.\n var diffs = this.diff_main(text1, text2, false);\n if (text1.length > this.Match_MaxBits &&\n this.diff_levenshtein(diffs) / text1.length >\n this.Patch_DeleteThreshold) {\n // The end points match, but the content is unacceptably bad.\n results[x] = false;\n } else {\n this.diff_cleanupSemanticLossless(diffs);\n var index1 = 0;\n var index2;\n for (var y = 0; y < patches[x].diffs.length; y++) {\n var mod = patches[x].diffs[y];\n if (mod[0] !== DIFF_EQUAL) {\n index2 = this.diff_xIndex(diffs, index1);\n }\n if (mod[0] === DIFF_INSERT) { // Insertion\n text = text.substring(0, start_loc + index2) + mod[1] +\n text.substring(start_loc + index2);\n } else if (mod[0] === DIFF_DELETE) { // Deletion\n text = text.substring(0, start_loc + index2) +\n text.substring(start_loc + this.diff_xIndex(diffs,\n index1 + mod[1].length));\n }\n if (mod[0] !== DIFF_DELETE) {\n index1 += mod[1].length;\n }\n }\n }\n }\n }\n }\n // Strip the padding off.\n text = text.substring(nullPadding.length, text.length - nullPadding.length);\n return [text, results];\n};\n\n\n/**\n * Add some padding on text start and end so that edges can match something.\n * Intended to be called only from within patch_apply.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n * @return {string} The padding string added to each side.\n */\ndiff_match_patch.prototype.patch_addPadding = function(patches) {\n var paddingLength = this.Patch_Margin;\n var nullPadding = '';\n for (var x = 1; x <= paddingLength; x++) {\n nullPadding += String.fromCharCode(x);\n }\n\n // Bump all the patches forward.\n for (var x = 0; x < patches.length; x++) {\n patches[x].start1 += paddingLength;\n patches[x].start2 += paddingLength;\n }\n\n // Add some padding on start of first diff.\n var patch = patches[0];\n var diffs = patch.diffs;\n if (diffs.length == 0 || diffs[0][0] != DIFF_EQUAL) {\n // Add nullPadding equality.\n diffs.unshift(new diff_match_patch.Diff(DIFF_EQUAL, nullPadding));\n patch.start1 -= paddingLength; // Should be 0.\n patch.start2 -= paddingLength; // Should be 0.\n patch.length1 += paddingLength;\n patch.length2 += paddingLength;\n } else if (paddingLength > diffs[0][1].length) {\n // Grow first equality.\n var extraLength = paddingLength - diffs[0][1].length;\n diffs[0][1] = nullPadding.substring(diffs[0][1].length) + diffs[0][1];\n patch.start1 -= extraLength;\n patch.start2 -= extraLength;\n patch.length1 += extraLength;\n patch.length2 += extraLength;\n }\n\n // Add some padding on end of last diff.\n patch = patches[patches.length - 1];\n diffs = patch.diffs;\n if (diffs.length == 0 || diffs[diffs.length - 1][0] != DIFF_EQUAL) {\n // Add nullPadding equality.\n diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, nullPadding));\n patch.length1 += paddingLength;\n patch.length2 += paddingLength;\n } else if (paddingLength > diffs[diffs.length - 1][1].length) {\n // Grow last equality.\n var extraLength = paddingLength - diffs[diffs.length - 1][1].length;\n diffs[diffs.length - 1][1] += nullPadding.substring(0, extraLength);\n patch.length1 += extraLength;\n patch.length2 += extraLength;\n }\n\n return nullPadding;\n};\n\n\n/**\n * Look through the patches and break up any which are longer than the maximum\n * limit of the match algorithm.\n * Intended to be called only from within patch_apply.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n */\ndiff_match_patch.prototype.patch_splitMax = function(patches) {\n var patch_size = this.Match_MaxBits;\n for (var x = 0; x < patches.length; x++) {\n if (patches[x].length1 <= patch_size) {\n continue;\n }\n var bigpatch = patches[x];\n // Remove the big old patch.\n patches.splice(x--, 1);\n var start1 = bigpatch.start1;\n var start2 = bigpatch.start2;\n var precontext = '';\n while (bigpatch.diffs.length !== 0) {\n // Create one of several smaller patches.\n var patch = new diff_match_patch.patch_obj();\n var empty = true;\n patch.start1 = start1 - precontext.length;\n patch.start2 = start2 - precontext.length;\n if (precontext !== '') {\n patch.length1 = patch.length2 = precontext.length;\n patch.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, precontext));\n }\n while (bigpatch.diffs.length !== 0 &&\n patch.length1 < patch_size - this.Patch_Margin) {\n var diff_type = bigpatch.diffs[0][0];\n var diff_text = bigpatch.diffs[0][1];\n if (diff_type === DIFF_INSERT) {\n // Insertions are harmless.\n patch.length2 += diff_text.length;\n start2 += diff_text.length;\n patch.diffs.push(bigpatch.diffs.shift());\n empty = false;\n } else if (diff_type === DIFF_DELETE && patch.diffs.length == 1 &&\n patch.diffs[0][0] == DIFF_EQUAL &&\n diff_text.length > 2 * patch_size) {\n // This is a large deletion. Let it pass in one chunk.\n patch.length1 += diff_text.length;\n start1 += diff_text.length;\n empty = false;\n patch.diffs.push(new diff_match_patch.Diff(diff_type, diff_text));\n bigpatch.diffs.shift();\n } else {\n // Deletion or equality. Only take as much as we can stomach.\n diff_text = diff_text.substring(0,\n patch_size - patch.length1 - this.Patch_Margin);\n patch.length1 += diff_text.length;\n start1 += diff_text.length;\n if (diff_type === DIFF_EQUAL) {\n patch.length2 += diff_text.length;\n start2 += diff_text.length;\n } else {\n empty = false;\n }\n patch.diffs.push(new diff_match_patch.Diff(diff_type, diff_text));\n if (diff_text == bigpatch.diffs[0][1]) {\n bigpatch.diffs.shift();\n } else {\n bigpatch.diffs[0][1] =\n bigpatch.diffs[0][1].substring(diff_text.length);\n }\n }\n }\n // Compute the head context for the next patch.\n precontext = this.diff_text2(patch.diffs);\n precontext =\n precontext.substring(precontext.length - this.Patch_Margin);\n // Append the end context for this patch.\n var postcontext = this.diff_text1(bigpatch.diffs)\n .substring(0, this.Patch_Margin);\n if (postcontext !== '') {\n patch.length1 += postcontext.length;\n patch.length2 += postcontext.length;\n if (patch.diffs.length !== 0 &&\n patch.diffs[patch.diffs.length - 1][0] === DIFF_EQUAL) {\n patch.diffs[patch.diffs.length - 1][1] += postcontext;\n } else {\n patch.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, postcontext));\n }\n }\n if (!empty) {\n patches.splice(++x, 0, patch);\n }\n }\n }\n};\n\n\n/**\n * Take a list of patches and return a textual representation.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n * @return {string} Text representation of patches.\n */\ndiff_match_patch.prototype.patch_toText = function(patches) {\n var text = [];\n for (var x = 0; x < patches.length; x++) {\n text[x] = patches[x];\n }\n return text.join('');\n};\n\n\n/**\n * Parse a textual representation of patches and return a list of Patch objects.\n * @param {string} textline Text representation of patches.\n * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.\n * @throws {!Error} If invalid input.\n */\ndiff_match_patch.prototype.patch_fromText = function(textline) {\n var patches = [];\n if (!textline) {\n return patches;\n }\n var text = textline.split('\\n');\n var textPointer = 0;\n var patchHeader = /^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$/;\n while (textPointer < text.length) {\n var m = text[textPointer].match(patchHeader);\n if (!m) {\n throw new Error('Invalid patch string: ' + text[textPointer]);\n }\n var patch = new diff_match_patch.patch_obj();\n patches.push(patch);\n patch.start1 = parseInt(m[1], 10);\n if (m[2] === '') {\n patch.start1--;\n patch.length1 = 1;\n } else if (m[2] == '0') {\n patch.length1 = 0;\n } else {\n patch.start1--;\n patch.length1 = parseInt(m[2], 10);\n }\n\n patch.start2 = parseInt(m[3], 10);\n if (m[4] === '') {\n patch.start2--;\n patch.length2 = 1;\n } else if (m[4] == '0') {\n patch.length2 = 0;\n } else {\n patch.start2--;\n patch.length2 = parseInt(m[4], 10);\n }\n textPointer++;\n\n while (textPointer < text.length) {\n var sign = text[textPointer].charAt(0);\n try {\n var line = decodeURI(text[textPointer].substring(1));\n } catch (ex) {\n // Malformed URI sequence.\n throw new Error('Illegal escape in patch_fromText: ' + line);\n }\n if (sign == '-') {\n // Deletion.\n patch.diffs.push(new diff_match_patch.Diff(DIFF_DELETE, line));\n } else if (sign == '+') {\n // Insertion.\n patch.diffs.push(new diff_match_patch.Diff(DIFF_INSERT, line));\n } else if (sign == ' ') {\n // Minor equality.\n patch.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, line));\n } else if (sign == '@') {\n // Start of next patch.\n break;\n } else if (sign === '') {\n // Blank line? Whatever.\n } else {\n // WTF?\n throw new Error('Invalid patch mode \"' + sign + '\" in: ' + line);\n }\n textPointer++;\n }\n }\n return patches;\n};\n\n\n/**\n * Class representing one patch operation.\n * @constructor\n */\ndiff_match_patch.patch_obj = function() {\n /** @type {!Array.<!diff_match_patch.Diff>} */\n this.diffs = [];\n /** @type {?number} */\n this.start1 = null;\n /** @type {?number} */\n this.start2 = null;\n /** @type {number} */\n this.length1 = 0;\n /** @type {number} */\n this.length2 = 0;\n};\n\n\n/**\n * Emulate GNU diff's format.\n * Header: @@ -382,8 +481,9 @@\n * Indices are printed as 1-based, not 0-based.\n * @return {string} The GNU diff string.\n */\ndiff_match_patch.patch_obj.prototype.toString = function() {\n var coords1, coords2;\n if (this.length1 === 0) {\n coords1 = this.start1 + ',0';\n } else if (this.length1 == 1) {\n coords1 = this.start1 + 1;\n } else {\n coords1 = (this.start1 + 1) + ',' + this.length1;\n }\n if (this.length2 === 0) {\n coords2 = this.start2 + ',0';\n } else if (this.length2 == 1) {\n coords2 = this.start2 + 1;\n } else {\n coords2 = (this.start2 + 1) + ',' + this.length2;\n }\n var text = ['@@ -' + coords1 + ' +' + coords2 + ' @@\\n'];\n var op;\n // Escape the body of the patch with %xx notation.\n for (var x = 0; x < this.diffs.length; x++) {\n switch (this.diffs[x][0]) {\n case DIFF_INSERT:\n op = '+';\n break;\n case DIFF_DELETE:\n op = '-';\n break;\n case DIFF_EQUAL:\n op = ' ';\n break;\n }\n text[x + 1] = op + encodeURI(this.diffs[x][1]) + '\\n';\n }\n return text.join('').replace(/%20/g, ' ');\n};\n\n\n// The following export code was added by @ForbesLindesay\nmodule.exports = diff_match_patch;\nmodule.exports['diff_match_patch'] = diff_match_patch;\nmodule.exports['DIFF_DELETE'] = DIFF_DELETE;\nmodule.exports['DIFF_INSERT'] = DIFF_INSERT;\nmodule.exports['DIFF_EQUAL'] = DIFF_EQUAL;","import type {EncodedBinary} from '@leafrelay/protocol';\n\nfunction isEncodedBinary(value:unknown):value is EncodedBinary {\n return typeof value==='object' && value!==null\n && (value as Partial<EncodedBinary>).$leafrelay==='bytes'\n && typeof (value as Partial<EncodedBinary>).base64==='string';\n}\n\nexport function encodeRpcValue(value:unknown):unknown {\n if (value instanceof Uint8Array) {\n return {$leafrelay:'bytes', base64:Buffer.from(value).toString('base64')} satisfies EncodedBinary;\n }\n if (Array.isArray(value)) { return value.map(encodeRpcValue); }\n if (typeof value==='object' && value!==null) {\n return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, encodeRpcValue(child)]));\n }\n return value;\n}\n\nexport function decodeRpcValue(value:unknown):unknown {\n if (isEncodedBinary(value)) { return Uint8Array.from(Buffer.from(value.base64, 'base64')); }\n if (Array.isArray(value)) { return value.map(decodeRpcValue); }\n if (typeof value==='object' && value!==null) {\n return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, decodeRpcValue(child)]));\n }\n return value;\n}\n","import {createHash} from 'node:crypto';\nimport {homedir} from 'node:os';\nimport {join, resolve} from 'node:path';\n\nexport interface DaemonPaths {\n home:string;\n socketPath:string;\n metadataPath:string;\n logPath:string;\n startupLockPath:string;\n}\n\nexport function daemonPaths(environment:NodeJS.ProcessEnv=process.env):DaemonPaths {\n const home = environment.LEAFRELAY_HOME ? resolve(environment.LEAFRELAY_HOME) : join(homedir(), '.leafrelay');\n const socketPath = process.platform==='win32'\n ? `\\\\\\\\.\\\\pipe\\\\leafrelay-${createHash('sha256').update(home).digest('hex').slice(0, 16)}`\n : join(home, 'daemon.sock');\n return {\n home,\n socketPath,\n metadataPath:join(home, 'daemon.json'),\n logPath:join(home, 'daemon.log'),\n startupLockPath:join(home, 'daemon.starting'),\n };\n}\n","/* eslint-disable @typescript-eslint/naming-convention */\nimport { Blob } from 'node:buffer';\nimport mime from 'mime';\nimport {OverleafRealtimeSocket} from './overleafRealtimeSocket';\nimport { v4 as uuidv4 } from 'uuid';\nimport { FileEntity, FileType, FolderEntity, OutputFileEntity } from '../core/projectTypes';\nimport { log } from '../core/logger';\nimport type { MemberEntity, ProjectSettingsSchema } from '../core/projectTypes';\nimport {HttpRequestScheduler, sharedHttpRequestScheduler} from './requestScheduler';\n\nexport type { MemberEntity, ProjectSettingsSchema } from '../core/projectTypes';\n\n/** Extract set-cookie headers from an undici/Response object. */\nfunction getSetCookie(res: any): string[] {\n if (typeof res.headers?.getSetCookie === 'function') {\n return res.headers.getSetCookie();\n }\n const raw = res.headers?.raw?.()?.['set-cookie'];\n if (raw) {\n return raw;\n }\n return [];\n}\n\nexport interface Identity {\n csrfToken: string;\n cookies: string;\n}\n\nexport interface NewProjectResponseSchema {\n project_id: string,\n owner_ref: string,\n owner: MemberEntity\n}\n\nexport interface CompileResponseSchema {\n status: 'success' | 'failure' | 'error';\n compileGroup: string;\n clsiServerId?: string;\n pdfDownloadDomain?: string;\n outputFiles: Array<OutputFileEntity>;\n stats: {\n \"latexmk-errors\":number, \"pdf-size\":number,\n \"latex-runs\":number, \"latex-runs-with-errors\":number,\n \"latex-runs-0\":number, \"latex-runs-with-error-0s\":number,\n };\n timings: {\n \"sync\":number, \"compile\":number, \"output\":number, \"compileE2E\":number,\n };\n enableHybridPdfDownload: boolean;\n}\n\nexport interface SyncPdfResponseSchema {\n file: string,\n line: number,\n column: number\n}\n\nexport interface SyncCodeResponseSchema {\n pdf: Array<{\n page: number,\n h: number,\n v: number,\n width: number,\n height: number,\n }>\n}\n\nexport interface SnippetItemSchema {\n meta: string,\n score: number,\n caption: string,\n snippet: string,\n}\n\nexport interface MisspellingItemSchema {\n index: number,\n suggestions: string[]\n}\n\nexport interface MetadataResponseScheme {\n projectId: string,\n projectMeta: {\n [id:string]: {\n labels: string[],\n packages: {[K:string]: SnippetItemSchema[]}\n }\n }\n}\n\nexport interface ProjectPersist {\n id: string;\n userId: string;\n name: string;\n lastUpdated?: string;\n lastUpdatedBy?: MemberEntity;\n source?: 'owner' | 'collaborator' | 'readOnly';\n accessLevel: 'owner' | 'collaborator' | 'readOnly';\n archived?: boolean;\n trashed?: boolean;\n scm?: any; //injected by SCMCollectionProvider\n}\n\nexport interface ProjectTagsResponseSchema {\n __v: number,\n _id: string,\n name: string,\n user_id: string,\n project_ids: string[],\n}\n\nexport interface ProjectLabelResponseSchema {\n id: string,\n comment: string,\n version: string,\n user_id: string,\n created_at: number,\n user_display_name?: string,\n}\n\nexport interface ProjectUpdateMeta {\n users: {id:string, first_name:string, last_name?:string, email:string}[],\n start_ts: number,\n end_ts: number,\n}\n\nexport interface ProjectHistoryResponseSchema {\n fromV: number,\n toV: number,\n meta: ProjectUpdateMeta,\n labels: ProjectLabelResponseSchema[],\n pathnames: string[],\n project_ops:{\n add?: {pathname:string},\n remove?: {pathname:string},\n atV: number,\n }[],\n}\n\nexport interface ProjectUpdateResponseSchema {\n updates: ProjectHistoryResponseSchema[],\n nextBeforeTimestamp: number,\n}\n\nexport interface ProjectFileDiffResponseSchema {\n diff: {\n u?: string, d?: string, i?: string,\n meta?: ProjectUpdateMeta,\n }[]\n}\n\nexport interface ProjectFileTreeDiffResponseSchema {\n diff: {\n pathname: string,\n newPathname?: string,\n operation?: 'edited' | 'added' | 'removed' | 'renamed',\n deletedAtV?: number,\n }[]\n}\n\nexport interface ProjectMessageResponseSchema {\n id: string,\n content: string,\n timestamp: number,\n user_id: string,\n user: {id:string, first_name:string, last_name?:string, email:string},\n clientId: string,\n}\n\nexport interface ResponseSchema {\n type: 'success' | 'error';\n statusCode?: number;\n raw?: ArrayBuffer;\n message?: string;\n userInfo?: {userId:string, userEmail:string};\n identity?: Identity;\n projects?: ProjectPersist[];\n entity?: FileEntity;\n entities?: {path:string, type:string}[];\n compile?: CompileResponseSchema;\n content?: Uint8Array;\n syncPdf?: SyncPdfResponseSchema;\n syncCode?: SyncCodeResponseSchema;\n meta?: MetadataResponseScheme;\n misspellings?: MisspellingItemSchema[];\n tags?: ProjectTagsResponseSchema[];\n labels?: ProjectLabelResponseSchema[];\n updates?: ProjectUpdateResponseSchema;\n diff?: ProjectFileDiffResponseSchema;\n treeDiff?: ProjectFileTreeDiffResponseSchema;\n messages?: ProjectMessageResponseSchema[];\n settings?: ProjectSettingsSchema;\n}\n\nexport class BaseAPI {\n private url: string;\n private identity?: Identity;\n\n private retryAfterMs(response: any, attempt: number): number {\n const retryAfter = response.headers?.get?.('retry-after');\n if (retryAfter!==undefined && retryAfter!==null) {\n const seconds = Number(retryAfter);\n if (Number.isFinite(seconds)) {\n return Math.max(1000, seconds*1000);\n }\n const retryAt = Date.parse(retryAfter);\n if (Number.isFinite(retryAt)) {\n return Math.max(1000, retryAt-Date.now());\n }\n }\n return 5000 * Math.pow(2, attempt);\n }\n\n constructor(url:string, private readonly scheduler:HttpRequestScheduler=sharedHttpRequestScheduler) {\n this.url = url;\n }\n\n private async getCsrfToken(): Promise<Identity> {\n const res = await this.scheduler.fetch(this.url+'login', {\n method: 'GET', redirect: 'manual',\n });\n const body = await res.text();\n const match = body.match(/<input.*name=\"_csrf\".*value=\"([^\"]*)\">/);\n if (!match) {\n throw new Error('Failed to get CSRF token.');\n } else {\n const csrfToken = match[1];\n const cookies = getSetCookie(res)[0]?.split(';')[0] ?? '';\n return { csrfToken, cookies };\n }\n }\n\n private async getUserId(cookies:string) {\n const res = await this.scheduler.fetch(this.url+'project', {\n method: 'GET', redirect:'manual',\n headers: {\n 'Connection': 'keep-alive',\n 'Cookie': cookies,\n }\n });\n\n const body = await res.text();\n const userIDMatch = body.match(/<meta\\s+name=\"ol-user_id\"\\s+content=\"([^\"]*)\">/);\n const userEmailMatch = body.match(/<meta\\s+name=\"ol-usersEmail\"\\s+content=\"([^\"]*)\">/);\n const csrfTokenMatch = body.match(/<meta\\s+name=\"ol-csrfToken\"\\s+content=\"([^\"]*)\">/);\n if (userIDMatch!==null && csrfTokenMatch!==null) {\n const userId = userIDMatch[1];\n const csrfToken = csrfTokenMatch[1];\n const userEmail = userEmailMatch ? userEmailMatch[1] : '';\n return {userId, userEmail, csrfToken};\n } else {\n return undefined;\n }\n }\n\n // Reference: \"github:overleaf/overleaf/services/web/frontend/js/ide/connection/ConnectionManager.js#L137\"\n _initSocketV0(identity:Identity, query?:string) {\n const url = new URL(this.url).origin + (query ?? '');\n return new OverleafRealtimeSocket(url, {\n origin:new URL(this.url).origin,\n cookie:identity.cookies,\n reconnect: true,\n reconnectionDelay:1000,\n reconnectionLimit:16000,\n maxReconnectionAttempts:10,\n fetch:(input, init) => this.scheduler.fetch(input, init),\n });\n }\n\n async passportLogin(email:string, password:string): Promise<ResponseSchema> {\n const identity = await this.getCsrfToken();\n const res = await this.scheduler.fetch(this.url+'login', {\n method: 'POST', redirect: 'manual',\n headers: {\n 'Accept': '*/*',\n 'Accept-Encoding': 'gzip, deflate, br',\n 'Connection': 'keep-alive',\n 'Content-Type': 'application/json',\n 'Cookie': identity.cookies,\n 'X-Csrf-Token': identity.csrfToken,\n },\n body: JSON.stringify({ _csrf: identity.csrfToken, email: email, password: password })\n });\n\n if (res.status===302) {\n const redirect = ((await res.text()).match(/Found. Redirecting to (.*)/) as any)[1];\n if (redirect==='/project') {\n const cookies = getSetCookie(res)[0] ?? '';\n return (await this.cookiesLogin(cookies));\n } else {\n return {\n type: 'error',\n message: `Redirecting to /${redirect}`\n };\n }\n }\n else if (res.status===200) {\n return {\n type: 'error',\n message: (await res.json() as any).message.message\n };\n } else if (res.status===401) {\n return {\n type: 'error',\n message: (await res.json() as any).message.text\n };\n } else {\n return {\n type: 'error',\n message: `${res.status}: `+await res.text()\n };\n }\n }\n\n async cookiesLogin(cookies: string): Promise<ResponseSchema> {\n const res = await this.getUserId(cookies);\n if (res) {\n const { userId, userEmail, csrfToken } = res;\n const identity: Identity = await this.updateCookies({ cookies, csrfToken });\n return {\n type: 'success',\n userInfo: {userId, userEmail},\n identity: identity\n };\n } else {\n return {\n type: 'error',\n message: 'Failed to get User ID.'\n };\n }\n }\n\n async updateCookies(identity: Identity) {\n const res = await this.scheduler.fetch(this.url + 'socket.io/socket.io.js', {\n method: 'GET',\n redirect: 'manual',\n headers: {\n 'Connection': 'keep-alive',\n 'Cookie': identity.cookies,\n }\n });\n const cookies = getSetCookie(res)[0]?.split(';')[0];\n if (cookies) {\n identity.cookies = `${identity.cookies}; ${cookies}`;\n }\n return identity;\n };\n\n setIdentity(identity: Identity) {\n this.identity = identity;\n return this;\n }\n\n /**\n * Check if an HTTP error is transient (worth retrying).\n * Retries on: 5xx server errors, network errors (fetch failures), and 429 rate limiting.\n */\n private isTransientError(statusCode: number | undefined, errorMessage?: string): boolean {\n if (statusCode === undefined) {\n // Network-level error (DNS, connection refused, reset, timeout)\n return true;\n }\n // Server errors and rate limiting\n if (statusCode >= 500 || statusCode === 429) {\n return true;\n }\n // Common transient network error messages\n if (errorMessage && (\n errorMessage.includes('ECONNRESET') ||\n errorMessage.includes('ETIMEDOUT') ||\n errorMessage.includes('ECONNREFUSED') ||\n errorMessage.includes('ENOTFOUND') ||\n errorMessage.includes('socket hang up')\n )) {\n return true;\n }\n return false;\n }\n\n protected async request(type:'GET'|'POST'|'PUT'|'DELETE', route:string, body?:FormData|object, callback?: (res?:string)=>object|undefined, extraHeaders?:object ): Promise<ResponseSchema> {\n if (this.identity===undefined) { return Promise.reject(); }\n\n const MAX_HTTP_RETRIES = 2;\n let lastError: {statusCode?: number, message?: string} = {};\n\n for (let attempt = 0; attempt <= MAX_HTTP_RETRIES; attempt++) {\n try {\n let res = undefined;\n switch(type) {\n case 'GET':\n res = await this.scheduler.fetch(this.url+route, {\n method: 'GET', redirect: 'manual',\n headers: {\n 'Connection': 'keep-alive',\n 'Cookie': this.identity!.cookies,\n ...extraHeaders\n }\n });\n break;\n case 'POST':\n const content_type = body instanceof FormData ? undefined : {'Content-Type': 'application/json'};\n const raw_body = body instanceof FormData ? body : JSON.stringify({\n _csrf: this.identity!.csrfToken,\n ...body\n });\n res = await this.scheduler.fetch(this.url+route, {\n method: 'POST', redirect: 'manual',\n headers: {\n 'Connection': 'keep-alive',\n 'Cookie': this.identity!.cookies,\n ...content_type,\n ...extraHeaders\n },\n body: raw_body\n });\n break;\n case 'PUT':\n break;\n case 'DELETE':\n res = await this.scheduler.fetch(this.url+route, {\n method: 'DELETE', redirect: 'manual',\n headers: {\n 'Connection': 'keep-alive',\n 'Cookie': this.identity!.cookies,\n 'X-Csrf-Token': this.identity!.csrfToken,\n ...extraHeaders\n }\n });\n break;\n };\n\n if (res && (res.status===200 || res.status===204)) {\n const _res = res.status===200 ? await res.text() : undefined;\n const response = callback && callback(_res);\n return {\n type: 'success',\n ...response\n } as ResponseSchema;\n } else if (res && this.isTransientError(res.status) && attempt < MAX_HTTP_RETRIES) {\n // Transient error: retry with backoff\n const delayMs = res.status===429 ? this.retryAfterMs(res, attempt) : Math.min(1000 * Math.pow(2, attempt), 4000);\n log(`HTTP ${res.status} on ${route}, retrying in ${delayMs}ms (attempt ${attempt + 1}/${MAX_HTTP_RETRIES})`);\n lastError = {statusCode: res.status, message: await res.text().catch(() => '')};\n await new Promise(r => setTimeout(r, delayMs));\n continue;\n } else {\n const resOrFallback = res || { status:'undefined', text: async () => '' };\n let errorBody = '';\n try { errorBody = await resOrFallback.text(); } catch { errorBody = ''; }\n return {\n type: 'error',\n statusCode: typeof resOrFallback.status==='number' ? resOrFallback.status : undefined,\n message: `${resOrFallback.status}: ${errorBody}`\n };\n }\n } catch (err: any) {\n const errMsg = err?.message || String(err);\n if (this.isTransientError(undefined, errMsg) && attempt < MAX_HTTP_RETRIES) {\n const delayMs = Math.min(1000 * Math.pow(2, attempt), 4000);\n log(`HTTP fetch error on ${route}: ${errMsg}, retrying in ${delayMs}ms (attempt ${attempt + 1}/${MAX_HTTP_RETRIES})`);\n await new Promise(r => setTimeout(r, delayMs));\n continue;\n }\n return {\n type: 'error',\n statusCode: undefined,\n message: errMsg\n };\n }\n }\n\n // All retries exhausted\n return {\n type: 'error',\n statusCode: lastError.statusCode,\n message: lastError.message || `Request failed after ${MAX_HTTP_RETRIES + 1} attempts`\n };\n }\n\n protected async download(route:string) {\n if (this.identity===undefined) { return Promise.reject(); }\n\n let content: Buffer[] = [];\n while(true) {\n const res = await this.scheduler.fetch(this.url+route, {\n method: 'GET', redirect: 'manual',\n headers: {\n 'Connection': 'keep-alive',\n 'Cookie': this.identity.cookies,\n }\n });\n if (res.status===200) {\n content.push(Buffer.from(await res.arrayBuffer()));\n break;\n }\n else if (res.status===206) {\n content.push(Buffer.from(await res.arrayBuffer()));\n } else {\n break;\n }\n };\n\n return Buffer.concat(content);\n }\n\n async logout(identity:Identity): Promise<ResponseSchema> {\n this.setIdentity(identity);\n return this.request('POST', 'logout');\n }\n\n async userProjectsJson(identity:Identity): Promise<ResponseSchema> {\n this.setIdentity(identity);\n return this.request('GET', 'user/projects', undefined, (res) => {\n const projects = (JSON.parse(res!) as any).projects as any[];\n projects.forEach(project => {\n project.id = project._id;\n delete project._id;\n });\n return {projects};\n });\n }\n\n async getProjectsJson(identity:Identity): Promise<ResponseSchema> {\n this.setIdentity(identity);\n return this.request('POST', 'api/project', {}, (res) => {\n const projects = (JSON.parse(res!) as any).projects;\n return {projects};\n });\n }\n\n async projectEntitiesJson(identity:Identity, projectId:string): Promise<ResponseSchema> {\n this.setIdentity(identity);\n return this.request('GET', `project/${projectId}/entities`, undefined, (res) => {\n const entities = JSON.parse(res!).entities;\n return {entities};\n });\n }\n\n async newProject(identity:Identity, projectName:string, template:'none'|'example') {\n this.setIdentity(identity);\n return this.request('POST', 'project/new', {projectName, template}, (res) => {\n const message = (JSON.parse(res!) as NewProjectResponseSchema).project_id;\n return {message};\n });\n }\n\n async cloneProject(identity:Identity, projectId:string, projectName:string) {\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/clone`, {projectName}, (res) => {\n const message = (JSON.parse(res!) as NewProjectResponseSchema).project_id;\n return {message};\n });\n }\n\n async renameProject(identity:Identity, projectId:string, newProjectName:string) {\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/rename`, {newProjectName});\n }\n\n async deleteProject(identity:Identity, projectId:string) {\n this.setIdentity(identity);\n return this.request('DELETE', `project/${projectId}`);\n }\n\n async archiveProject(identity:Identity, projectId:string) {\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/archive`,\n undefined, undefined, {'X-Csrf-Token': identity.csrfToken});\n }\n\n async unarchiveProject(identity:Identity, projectId:string) {\n this.setIdentity(identity);\n return this.request('DELETE', `project/${projectId}/archive`);\n }\n\n async trashProject(identity:Identity, projectId:string) {\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/trash`,\n undefined, undefined, {'X-Csrf-Token': identity.csrfToken});\n }\n\n async untrashProject(identity:Identity, projectId:string) {\n this.setIdentity(identity);\n return this.request('DELETE', `project/${projectId}/trash`);\n }\n\n async getFile(identity:Identity, projectId:string, fileId:string) {\n this.setIdentity(identity);\n const content = await this.download(`project/${projectId}/file/${fileId}`);\n return {\n type: 'success',\n content: new Uint8Array( content )\n };\n }\n\n async addDoc(identity:Identity, projectId:string, parentFolderId:string, filename:string) {\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/doc`, {parent_folder_id:parentFolderId, name:filename}, (res) => {\n const {_id} = JSON.parse(res!) as any;\n const entity = {_type:'doc', _id, name:filename} as FileEntity;\n return {entity};\n }, {'X-Csrf-Token': identity.csrfToken});\n }\n\n async uploadFile(identity:Identity, projectId:string, parentFolderId:string, filename:string, fileContent:Uint8Array) {\n const formData = new FormData();\n const mimeType = mime.getType(filename);\n formData.append('targetFolderId', parentFolderId);\n formData.append('name', filename);\n formData.append('type', mimeType? mimeType : 'text/plain');\n formData.append('qqfile', new Blob([Buffer.from(fileContent)], {\n type: mimeType ? mimeType : 'application/octet-stream',\n }), filename);\n\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/upload?folder_id=${parentFolderId}`, formData, (res) => {\n const {success, entity_id, entity_type} = JSON.parse(res!) as any;\n const entity = {_type:entity_type, _id:entity_id, name:filename} as FileEntity;\n return {entity};\n }, {'X-Csrf-Token': identity.csrfToken});\n }\n\n async uploadProject(identity:Identity, filename:string, fileContent:Uint8Array) {\n const uuid = uuidv4();\n const formData = new FormData();\n formData.append('qqfile', new Blob([Buffer.from(fileContent)], {\n type: 'application/zip',\n }), filename);\n\n this.setIdentity(identity);\n return this.request('POST', `project/new/upload?_csrf=${identity.csrfToken}&qquuid=${uuid}&qqfilename=${filename}&qqtotalfilesize=${fileContent.length}`, formData, (res) => {\n const message = (JSON.parse(res!) as NewProjectResponseSchema).project_id;\n return {message};\n });\n }\n\n async addFolder(identity:Identity, projectId:string, folderName:string, parentFolderId:string) {\n const body = { name: folderName, parent_folder_id: parentFolderId };\n\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/folder`, body, (res) => {\n const entity = JSON.parse(res!) as FolderEntity;\n return {entity};\n }, {'X-Csrf-Token': identity.csrfToken});\n }\n\n async deleteEntity(identity:Identity, projectId:string, fileType:FileType, fileId:string) {\n this.setIdentity(identity);\n return this.request('DELETE', `project/${projectId}/${fileType}/${fileId}`);\n }\n\n async deleteAuxFiles(identity:Identity, projectId:string) {\n this.setIdentity(identity);\n return this.request('DELETE', `project/${projectId}/output`);\n }\n\n async renameEntity(identity:Identity, projectId:string, entityType:string, entityId:string, name:string) {\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/${entityType}/${entityId}/rename`,\n {name}, undefined, {'X-Csrf-Token': identity.csrfToken});\n }\n\n async moveEntity(identity:Identity, projectId:string, entityType:string, entityId:string, newParentFolderId:string) {\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/${entityType}/${entityId}/move`,\n {folder_id:newParentFolderId}, undefined, {'X-Csrf-Token': identity.csrfToken});\n }\n\n async compile(identity:Identity, projectId:string, rootResourcePath:string|null,\n draft:boolean=false, stopOnFirstError:boolean=false\n ) {\n const body = {\n check: 'silent',\n draft,\n incrementalCompilesEnabled: true,\n rootResourcePath, // file path e.g. \"main.tex\"\n stopOnFirstError\n };\n\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/compile?auto_compile=true`, body, (res) => {\n const compile = JSON.parse(res!) as CompileResponseSchema;\n return {compile};\n }, {'X-Csrf-Token': identity.csrfToken});\n }\n\n async stopCompile(identity:Identity, projectId:string) {\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/compile/stop`, undefined, undefined, {'X-Csrf-Token': identity.csrfToken});\n }\n\n async indexAll(identity:Identity, projectId:string) {\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/references/indexAll`, {shouldBroadcast: false}, undefined);\n }\n\n async getMetadata(identity:Identity, projectId:string) {\n this.setIdentity(identity);\n return this.request('GET', `project/${projectId}/metadata`, undefined, (res) => {\n const meta = JSON.parse(res!) as MetadataResponseScheme;\n return {meta};\n });\n }\n\n async proxyRequestToSpellingApi(identity:Identity, language:string, userId:string, words: string[]) {\n const body = {\n language,\n skipLearnedWords: true,\n token: userId,\n words\n };\n\n this.setIdentity(identity);\n return this.request('POST', 'spelling/check', body, (res) => {\n const misspellings = JSON.parse(res!).misspellings as MisspellingItemSchema[];\n return {misspellings};\n });\n }\n\n async spellingControllerLearn(identity:Identity, userId:string, word: string) {\n const body = {\n token: userId,\n word\n };\n\n this.setIdentity(identity);\n return this.request('POST', 'spelling/learn', body);\n }\n\n async spellingControllerUnlearn(identity:Identity, word: string) {\n this.setIdentity(identity);\n return this.request('POST', 'spelling/unlearn', {word}, undefined, {'X-Csrf-Token': identity.csrfToken});\n }\n\n async getProjectSettings(identity:Identity, projectId:string) {\n this.setIdentity(identity);\n return this.request('GET', `project/${projectId}`, undefined, (res) => {\n const body = res || '';\n // parse \"ol-learnedWords\"\n const learnedWordsMatch = /<meta\\s+name=\"ol-learnedWords\"\\s+data-type=\"json\"\\s+content=\"(\\[.*?\\])\">/.exec(body);\n const learnedWords = (learnedWordsMatch!==null) ? JSON.parse(learnedWordsMatch[1].replace(/&quot;/g, '\"')) : [];\n // parse \"ol-languages\"\n const languagesMatch = /<meta\\s+name=\"ol-languages\"\\s+data-type=\"json\"\\s+content=\"(\\[.*?\\])\">/.exec(body);\n const languages = (languagesMatch!==null) ? JSON.parse(languagesMatch[1].replace(/&quot;/g, '\"')) as {code:string,name:string}[] : [];\n languages.length && languages.unshift({name:'Off', code:''});\n // fill in compilers\n const compilers = [\n {code: 'pdflatex', name: 'pdfLaTex'},\n {code: 'latex', name: 'LaTex'},\n {code: 'xelatex', name: 'XeLaTex'},\n {code: 'lualatex', name: 'LuaLaTex'},\n ];\n // return parsed results\n const settings = {learnedWords, languages, compilers} as ProjectSettingsSchema;\n return {settings};\n });\n }\n\n async updateProjectSettings(identity:Identity, projectId:string, setting:any) {\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/settings`, setting);\n }\n\n async getFileFromClsi(identity:Identity, url:string, compileGroup:string, clsiServerId?:string, pdfDownloadDomain?:string) {\n // If we have a CDN download domain, construct the full URL with required query params.\n // The CDN is cross-origin, so we must NOT send web frontend cookies.\n if (pdfDownloadDomain && clsiServerId) {\n const cdnUrl = `${pdfDownloadDomain.replace(/\\/+$/, '')}/${url.replace(/^\\/+/g, '')}` +\n `?compileGroup=${encodeURIComponent(compileGroup)}` +\n `&clsiserverid=${encodeURIComponent(clsiServerId)}` +\n `&enable_pdf_caching=true`;\n const content = await this._downloadAbsolute(cdnUrl, false);\n return { type: 'success', content: new Uint8Array(content) };\n }\n\n // Fallback: download from web frontend (legacy path)\n url = url.replace(/^\\/+/g, '');\n this.setIdentity(identity);\n const content = await this.download(url);\n return {\n type: 'success',\n content: new Uint8Array( content )\n };\n }\n\n /** Download from an absolute URL, optionally including web frontend cookies. */\n private async _downloadAbsolute(absoluteUrl: string, includeCookies: boolean): Promise<Buffer> {\n const headers: Record<string, string> = {\n 'Connection': 'keep-alive',\n };\n if (includeCookies && this.identity) {\n headers['Cookie'] = this.identity.cookies;\n }\n let content: Buffer[] = [];\n while (true) {\n const res = await this.scheduler.fetch(absoluteUrl, {\n method: 'GET', redirect: 'manual',\n headers\n });\n if (res.status === 200) {\n content.push(Buffer.from(await res.arrayBuffer()));\n break;\n } else if (res.status === 206) {\n content.push(Buffer.from(await res.arrayBuffer()));\n } else {\n break;\n }\n }\n return Buffer.concat(content);\n }\n\n async proxySyncPdf(identity:Identity, projectId:string, page:number, h:number, v:number, buildId:string) {\n this.setIdentity(identity);\n const request = `project/${projectId}/sync/pdf?page=${page}&h=${h.toFixed(2)}&v=${v.toFixed(2)}&editorId=${uuidv4()}&buildId=${buildId}`;\n return this.request('GET', `project/${projectId}/sync/pdf?page=${page}&h=${h.toFixed(2)}&v=${v.toFixed(2)}&editorId=${uuidv4()}&buildId=${buildId}`,\n undefined, (res) => {\n const syncPdf = (JSON.parse(res!) as any).code[0] as SyncPdfResponseSchema;\n return {syncPdf};\n });\n }\n\n async proxySyncCode(identity:Identity, projectId:string, file:string, line:number, column:number, buildId:string) {\n this.setIdentity(identity);\n return this.request('GET', `project/${projectId}/sync/code?file=${file}&line=${line}&column=${column}&editorId=${uuidv4()}&buildId=${buildId}`,\n undefined, (res) => {\n const syncCode = (JSON.parse(res!) as any).pdf as SyncCodeResponseSchema;\n return {syncCode};\n });\n }\n\n async getAllTags(identity:Identity) {\n this.setIdentity(identity);\n return this.request('GET', 'tag', undefined, (res) => {\n const tags = JSON.parse(res!) as ProjectTagsResponseSchema[];\n return {tags};\n });\n }\n\n async createTag(identity:Identity, name:string) {\n this.setIdentity(identity);\n return this.request('POST', 'tag', {name}, (res) => {\n const tags = JSON.parse(res!) as ProjectTagsResponseSchema[];\n return {tags};\n });\n }\n\n async renameTag(identity:Identity, tagId:string, name:string) {\n this.setIdentity(identity);\n return this.request('POST', `tag/${tagId}/rename`, {name});\n }\n\n async deleteTag(identity:Identity, tagId:string) {\n this.setIdentity(identity);\n return this.request('DELETE', `tag/${tagId}`);\n }\n\n async addProjectToTag(identity:Identity, tagId:string, projectId:string) {\n this.setIdentity(identity);\n return this.request('POST', `tag/${tagId}/project/${projectId}`);\n }\n\n async removeProjectFromTag(identity:Identity, tagId:string, projectId:string) {\n this.setIdentity(identity);\n return this.request('DELETE', `tag/${tagId}/project/${projectId}`);\n }\n\n async proxyToHistoryApiAndGetUpdates(identity:Identity, projectId:string, before?:number) {\n const beforeQuery = before? `&before=${before}` : '';\n\n this.setIdentity(identity);\n return this.request('GET', `project/${projectId}/updates?min_count=10${beforeQuery}`, undefined, (res) => {\n const updates = JSON.parse(res!) as ProjectUpdateResponseSchema;\n return {updates};\n });\n }\n\n async proxyToHistoryApiAndGetFileDiff(identity:Identity, projectId:string, pathname:string, from:number, to:number) {\n this.setIdentity(identity);\n return this.request('GET', `project/${projectId}/diff?pathname=${pathname}&from=${from}&to=${to}`, undefined, (res) => {\n const diff = JSON.parse(res!) as ProjectFileDiffResponseSchema;\n return {diff};\n });\n }\n\n async proxyToHistoryApiAndGetFileTreeDiff(identity:Identity, projectId:string, from:number, to:number) {\n this.setIdentity(identity);\n return this.request('GET', `project/${projectId}/filetree/diff?from=${from}&to=${to}`, undefined, (res) => {\n const treeDiff = JSON.parse(res!) as ProjectFileTreeDiffResponseSchema;\n return {treeDiff};\n });\n }\n\n async downloadZipOfVersion(identity:Identity, projectId:string, version:number) {\n this.setIdentity(identity);\n const content = await this.download(`project/${projectId}/version/${version}/zip`);\n return {\n type: 'success',\n content: new Uint8Array(content)\n };\n }\n\n async getLabels(identity:Identity, projectId:string) {\n this.setIdentity(identity);\n return this.request('GET', `project/${projectId}/labels`, undefined, (res) => {\n const labels = JSON.parse(res!) as ProjectLabelResponseSchema[];\n return {labels};\n });\n }\n\n async createLabel(identity:Identity, projectId:string, comment:string, version:number) {\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/labels`, {comment, version}, (res) => {\n const labels = [JSON.parse(res!)] as ProjectLabelResponseSchema[];\n return {labels};\n });\n }\n\n async deleteLabel(identity:Identity, projectId:string, labelId:string) {\n this.setIdentity(identity);\n return this.request('DELETE', `project/${projectId}/labels/${labelId}`);\n }\n\n async getMessages(identity:Identity, projectId:string, limit:number=50) {\n this.setIdentity(identity);\n return this.request('GET', `project/${projectId}/messages?limit=${limit}`, undefined, (res) => {\n const messages = JSON.parse(res!) as ProjectMessageResponseSchema[];\n return {messages};\n }, {'X-Csrf-Token': identity.csrfToken});\n }\n\n async sendMessage(identity:Identity, projectId:string, client_id:string, content:string) {\n this.setIdentity(identity);\n return this.request('POST', `project/${projectId}/messages`, {client_id, content}, undefined, {'X-Csrf-Token': identity.csrfToken});\n }\n}\n","import {EventEmitter} from 'node:events';\n\nconst PACKET_TYPES = [\n 'disconnect',\n 'connect',\n 'heartbeat',\n 'message',\n 'json',\n 'event',\n 'ack',\n 'error',\n 'noop',\n] as const;\n\ntype PacketType = typeof PACKET_TYPES[number];\n\ninterface SocketPacket {\n type?: PacketType;\n id?: string;\n ack?: true | 'data';\n endpoint?: string;\n name?: string;\n args?: unknown[];\n data?: unknown;\n ackId?: string;\n reason?: string;\n advice?: string;\n}\n\nexport interface OverleafRealtimeSocketOptions {\n origin: string;\n cookie: string;\n reconnect?: boolean;\n reconnectionDelay?: number;\n reconnectionLimit?: number;\n maxReconnectionAttempts?: number;\n fetch?:typeof fetch;\n}\n\nfunction encodePacket(packet: SocketPacket): string {\n const type = PACKET_TYPES.indexOf(packet.type ?? 'noop');\n const id = packet.id ?? '';\n let data: string | undefined;\n\n switch (packet.type) {\n case 'event':\n data = JSON.stringify({name:packet.name, args:packet.args ?? []});\n break;\n case 'ack':\n data = `${packet.ackId ?? ''}${packet.args?.length ? `+${JSON.stringify(packet.args)}` : ''}`;\n break;\n case 'message':\n data = String(packet.data ?? '');\n break;\n case 'json':\n data = JSON.stringify(packet.data);\n break;\n default:\n break;\n }\n\n const fields = [String(type), `${id}${packet.ack==='data' ? '+' : ''}`, packet.endpoint ?? ''];\n if (data!==undefined) { fields.push(data); }\n return fields.join(':');\n}\n\nfunction decodePacket(value: string): SocketPacket {\n const match = value.match(/([^:]+):([0-9]+)?(\\+)?:([^:]+)?:?([\\s\\S]*)?/);\n if (!match) { return {}; }\n\n const packet:SocketPacket = {\n type:PACKET_TYPES[Number(match[1])],\n endpoint:match[4] || '',\n };\n if (match[2]) {\n packet.id = match[2];\n packet.ack = match[3] ? 'data' : true;\n }\n\n const data = match[5] || '';\n switch (packet.type) {\n case 'event': {\n const event = JSON.parse(data) as {name:string; args?:unknown[]};\n packet.name = event.name;\n packet.args = event.args ?? [];\n break;\n }\n case 'ack': {\n const ack = data.match(/^([0-9]+)(\\+)?([\\s\\S]*)/);\n if (ack) {\n packet.ackId = ack[1];\n packet.args = ack[3] ? JSON.parse(ack[3]) as unknown[] : [];\n }\n break;\n }\n case 'error': {\n const [reason, advice] = data.split('+');\n packet.reason = ['transport not supported', 'client not handshaken', 'unauthorized'][Number(reason)] ?? '';\n packet.advice = ['reconnect'][Number(advice)] ?? '';\n break;\n }\n case 'json':\n packet.data = JSON.parse(data);\n break;\n case 'message':\n packet.data = data;\n break;\n default:\n break;\n }\n return packet;\n}\n\nfunction decodePayload(value: string): SocketPacket[] {\n if (!value.startsWith('\\ufffd')) { return [decodePacket(value)]; }\n const packets:SocketPacket[] = [];\n let offset = 1;\n while (offset<value.length) {\n const separator = value.indexOf('\\ufffd', offset);\n if (separator===-1) { break; }\n const length = Number(value.slice(offset, separator));\n const start = separator+1;\n packets.push(decodePacket(value.slice(start, start+length)));\n offset = start+length+1;\n }\n return packets;\n}\n\nfunction mergeCookies(current: string, additions: string[]): string {\n const cookies = new Map<string, string>();\n for (const value of [current, ...additions.map(cookie => cookie.split(';', 1)[0])]) {\n for (const part of value.split(';')) {\n const separator = part.indexOf('=');\n if (separator===-1) { continue; }\n cookies.set(part.slice(0, separator).trim(), part.slice(separator+1).trim());\n }\n }\n return [...cookies].map(([name, value]) => `${name}=${value}`).join('; ');\n}\n\nexport class OverleafRealtimeSocket {\n private readonly events = new EventEmitter();\n private readonly endpoint: URL;\n private readonly origin: string;\n private cookie: string;\n private socket?: WebSocket;\n private connected = false;\n private projectJoined = false;\n private explicitlyDisconnected = false;\n private reconnectEnabled: boolean;\n private reconnectAttempts = 0;\n private reconnectTimer?: NodeJS.Timeout;\n private inactivityTimer?: NodeJS.Timeout;\n private closeTimeoutMs = 60_000;\n private acknowledgementId = 0;\n private readonly acknowledgements = new Map<string, (...args:unknown[]) => void>();\n\n readonly io = {\n reconnect:(enabled:boolean) => {\n this.reconnectEnabled = enabled;\n if (!enabled && this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n }\n },\n };\n\n constructor(url: string, private readonly options: OverleafRealtimeSocketOptions) {\n this.endpoint = new URL(url);\n this.origin = options.origin;\n this.cookie = options.cookie;\n this.reconnectEnabled = options.reconnect ?? true;\n void this.connect();\n }\n\n on(event: string, handler: (...args:any[]) => void): this {\n this.events.on(event, handler);\n return this;\n }\n\n once(event: string, handler: (...args:any[]) => void): this {\n this.events.once(event, handler);\n return this;\n }\n\n removeListener(event: string, handler: (...args:any[]) => void): this {\n this.events.removeListener(event, handler);\n return this;\n }\n\n removeAllListeners(event?: string): this {\n this.events.removeAllListeners(event);\n return this;\n }\n\n emit(event: string, ...args:any[]): this {\n const callback = typeof args.at(-1)==='function' ? args.pop() as (...values:unknown[]) => void : undefined;\n const id = callback ? String(++this.acknowledgementId) : undefined;\n if (id && callback) { this.acknowledgements.set(id, callback); }\n const packet = encodePacket({\n type:'event',\n id,\n ack:callback ? 'data' : undefined,\n name:event,\n args,\n });\n if (!this.sendApplicationEvent(packet) && callback) {\n if (id) { this.acknowledgements.delete(id); }\n queueMicrotask(() => callback(new Error('The Overleaf project session is not connected.')));\n }\n return this;\n }\n\n markProjectJoined():void {\n this.projectJoined = true;\n }\n\n disconnect(): this {\n this.explicitlyDisconnected = true;\n this.reconnectEnabled = false;\n if (this.reconnectTimer) { clearTimeout(this.reconnectTimer); }\n if (this.connected) { this.send(encodePacket({type:'disconnect'})); }\n this.closeSocket('booted');\n return this;\n }\n\n private async connect(): Promise<void> {\n try {\n this.projectJoined = false;\n const handshakeUrl = new URL('/socket.io/1/', this.endpoint.origin);\n for (const [name, value] of this.endpoint.searchParams) {\n handshakeUrl.searchParams.set(name, value);\n }\n handshakeUrl.searchParams.set('t', String(Date.now()));\n const response = await (this.options.fetch ?? fetch)(handshakeUrl, {\n headers:{origin:this.origin, cookie:this.cookie},\n redirect:'manual',\n });\n if (!response.ok) {\n throw new Error(`Socket.IO handshake failed: HTTP ${response.status} ${await response.text()}`);\n }\n const setCookies = response.headers.getSetCookie?.() ?? [];\n this.cookie = mergeCookies(this.cookie, setCookies);\n const [sessionId, heartbeatTimeout, closeTimeout, transports] = (await response.text()).split(':');\n if (!sessionId || !transports?.split(',').includes('websocket')) {\n throw new Error('Overleaf did not offer a Socket.IO WebSocket transport.');\n }\n this.closeTimeoutMs = Math.max(Number(heartbeatTimeout), Number(closeTimeout), 10)*1000;\n\n const websocketUrl = new URL(`/socket.io/1/websocket/${sessionId}`, this.endpoint.origin);\n websocketUrl.protocol = websocketUrl.protocol==='https:' ? 'wss:' : 'ws:';\n websocketUrl.search = this.endpoint.search;\n this.socket = new WebSocket(websocketUrl, {\n headers:{origin:this.origin, cookie:this.cookie},\n });\n this.socket.addEventListener('open', () => this.events.emit('connecting', 'websocket'));\n this.socket.addEventListener('message', event => void this.receive(event.data));\n this.socket.addEventListener('error', error => this.events.emit('error', error));\n this.socket.addEventListener('close', event => this.handleClose(event));\n } catch (error) {\n this.events.emit('connect_failed', error);\n this.events.emit('error', error);\n this.scheduleReconnect();\n }\n }\n\n private async receive(data: unknown) {\n this.resetInactivityTimer();\n const value = typeof data==='string'\n ? data\n : data instanceof Blob\n ? await data.text()\n : Buffer.from(data as ArrayBuffer).toString('utf8');\n for (const packet of decodePayload(value)) { this.handlePacket(packet); }\n }\n\n private handlePacket(packet: SocketPacket) {\n switch (packet.type) {\n case 'connect': {\n const wasReconnecting = this.reconnectAttempts>0;\n this.connected = true;\n this.events.emit('connect');\n if (wasReconnecting) {\n this.events.emit('reconnect', 'websocket', this.reconnectAttempts);\n this.reconnectAttempts = 0;\n }\n break;\n }\n case 'heartbeat':\n this.send(encodePacket({type:'heartbeat'}));\n break;\n case 'event': {\n const args = [...(packet.args ?? [])];\n if (packet.ack==='data' && packet.id) {\n args.push((...acknowledgement:unknown[]) => {\n this.send(encodePacket({type:'ack', ackId:packet.id, args:acknowledgement}));\n });\n }\n this.events.emit(packet.name ?? '', ...args);\n break;\n }\n case 'ack': {\n const callback = packet.ackId && this.acknowledgements.get(packet.ackId);\n if (callback && packet.ackId) {\n this.acknowledgements.delete(packet.ackId);\n callback(...(packet.args ?? []));\n }\n break;\n }\n case 'disconnect':\n this.closeSocket('booted');\n break;\n case 'error':\n this.events.emit('error', packet.reason || 'Socket.IO protocol error');\n if (packet.advice==='reconnect') { this.closeSocket('server error'); }\n break;\n case 'message':\n case 'json':\n this.events.emit('message', packet.data);\n break;\n default:\n break;\n }\n }\n\n private send(packet: string) {\n if (this.connected && this.socket?.readyState===WebSocket.OPEN) {\n this.socket.send(packet);\n }\n }\n\n private sendApplicationEvent(packet:string):boolean {\n if (!this.connected || !this.projectJoined || this.socket?.readyState!==WebSocket.OPEN) {\n return false;\n }\n this.socket.send(packet);\n return true;\n }\n\n private resetInactivityTimer() {\n if (this.inactivityTimer) { clearTimeout(this.inactivityTimer); }\n this.inactivityTimer = setTimeout(() => this.closeSocket('timeout'), this.closeTimeoutMs);\n }\n\n private handleClose(event:CloseEvent) {\n const wasConnected = this.connected;\n this.connected = false;\n this.projectJoined = false;\n if (this.inactivityTimer) { clearTimeout(this.inactivityTimer); }\n if (wasConnected) {\n const detail = event.reason ? `: ${event.reason}` : '';\n const reason = `transport close (code ${event.code})${detail}`;\n this.failAcknowledgements(reason);\n this.events.emit('disconnect', reason);\n }\n this.scheduleReconnect();\n }\n\n private closeSocket(reason: string) {\n const wasConnected = this.connected;\n this.connected = false;\n this.projectJoined = false;\n if (this.inactivityTimer) { clearTimeout(this.inactivityTimer); }\n const socket = this.socket;\n this.socket = undefined;\n socket?.close();\n if (wasConnected) {\n this.failAcknowledgements(reason);\n this.events.emit('disconnect', reason);\n }\n if (!this.explicitlyDisconnected) { this.scheduleReconnect(); }\n }\n\n private failAcknowledgements(reason:string) {\n const error = new Error(`Overleaf realtime connection closed: ${reason}`);\n for (const callback of this.acknowledgements.values()) { callback(error); }\n this.acknowledgements.clear();\n }\n\n private scheduleReconnect() {\n if (!this.reconnectEnabled || this.explicitlyDisconnected || this.reconnectTimer) { return; }\n const maxAttempts = this.options.maxReconnectionAttempts ?? 10;\n if (this.reconnectAttempts>=maxAttempts) {\n this.events.emit('reconnect_failed');\n return;\n }\n this.reconnectAttempts += 1;\n const initial = this.options.reconnectionDelay ?? 1000;\n const limit = this.options.reconnectionLimit ?? 16_000;\n const delay = Math.min(initial*2**(this.reconnectAttempts-1), limit);\n this.events.emit('reconnecting', delay, this.reconnectAttempts);\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = undefined;\n void this.connect();\n }, delay);\n }\n}\n\nexport const overleafSocketProtocol = {encodePacket, decodePacket, decodePayload};\n","export type LogLevel = 'info' | 'warn' | 'error';\n\nexport type LogSink = (level: LogLevel, args: readonly unknown[]) => void;\n\nlet sink: LogSink | undefined;\n\nexport function setLogSink(nextSink: LogSink | undefined) {\n sink = nextSink;\n}\n\nfunction write(level: LogLevel, args: readonly unknown[]) {\n if (sink!==undefined) {\n sink(level, args);\n return;\n }\n const method = level==='error' ? console.error : level==='warn' ? console.warn : console.log;\n method(...args);\n}\n\nexport function log(...args: unknown[]) {\n write('info', args);\n}\n\nexport function warn(...args: unknown[]) {\n write('warn', args);\n}\n\nexport function error(...args: unknown[]) {\n write('error', args);\n}\n","import {log} from '../core/logger';\n\nexport interface HttpRequestSchedulerOptions {\n minimumIntervalMs?:number;\n historyIntervalMs?:number;\n fetch?:typeof fetch;\n now?:() => number;\n wait?:(milliseconds:number) => Promise<void>;\n onRateLimit?:(until:number) => void;\n}\n\nfunction retryAfterMilliseconds(response:Response, now:number):number {\n const retryAfter = response.headers.get('retry-after');\n if (retryAfter) {\n const seconds = Number(retryAfter);\n if (Number.isFinite(seconds)) { return Math.max(1000, seconds*1000); }\n const retryAt = Date.parse(retryAfter);\n if (Number.isFinite(retryAt)) { return Math.max(1000, retryAt-now); }\n }\n return 5000;\n}\n\nexport class HttpRequestScheduler {\n private chain:Promise<void> = Promise.resolve();\n private nextRequestAt = 0;\n private historyNextRequestAt = 0;\n private rateLimitedUntil = 0;\n private readonly minimumIntervalMs:number;\n private readonly historyIntervalMs:number;\n private readonly fetchImplementation:typeof fetch;\n private readonly now:() => number;\n private readonly wait:(milliseconds:number) => Promise<void>;\n\n constructor(private readonly options:HttpRequestSchedulerOptions={}) {\n this.minimumIntervalMs = options.minimumIntervalMs ?? 300;\n this.historyIntervalMs = options.historyIntervalMs ?? 3000;\n this.fetchImplementation = options.fetch ?? fetch;\n this.now = options.now ?? Date.now;\n this.wait = options.wait ?? (milliseconds => new Promise(resolveWait => setTimeout(resolveWait, milliseconds)));\n }\n\n fetch(input:string|URL|Request, init?:RequestInit):Promise<Response> {\n const url = input instanceof Request ? input.url : String(input);\n const history = url.includes('/updates?') || url.includes('/filetree/diff?') || url.includes('/diff?');\n return this.enqueue(async () => {\n const now = this.now();\n const readyAt = Math.max(this.nextRequestAt, this.rateLimitedUntil, history ? this.historyNextRequestAt : 0);\n if (readyAt>now) { await this.wait(readyAt-now); }\n const requestAt = this.now();\n this.nextRequestAt = requestAt+this.minimumIntervalMs;\n if (history) { this.historyNextRequestAt = requestAt+this.historyIntervalMs; }\n const response = await this.fetchImplementation(input, init);\n if (response.status===429) {\n this.rateLimitedUntil = Math.max(\n this.rateLimitedUntil,\n this.now()+retryAfterMilliseconds(response, this.now()),\n );\n this.options.onRateLimit?.(this.rateLimitedUntil);\n log(`HTTP request scheduler entered rate-limit cooldown until ${new Date(this.rateLimitedUntil).toISOString()}.`);\n }\n return response;\n });\n }\n\n private enqueue<T>(operation:() => Promise<T>):Promise<T> {\n const result = this.chain.then(operation);\n this.chain = result.then(() => undefined, () => undefined);\n return result;\n }\n}\n\nexport const sharedHttpRequestScheduler = new HttpRequestScheduler();\n","/* eslint-disable @typescript-eslint/naming-convention */\nimport { BaseAPI, Identity } from \"./base\";\nexport type { ProjectLinkedFileProvider, UrlLinkedFileProvider } from '../core/projectTypes';\n\nexport class ExtendedBaseAPI extends BaseAPI {\n async refreshLinkedFile(identity:Identity, project_id:string, file_id:string) {\n this.setIdentity(identity);\n return await this.request('POST', `project/${project_id}/linked_file/${file_id}/refresh`, {shouldReindexReferences: false}, (res) => {\n const message = JSON.parse(res!).new_file_id;\n return {message};\n }, {'X-Csrf-Token': identity.csrfToken});\n }\n\n async createLinkedFile(identity:Identity, project_id:string, parent_folder_id:string, name:string, provider:string, data:any) {\n this.setIdentity(identity);\n return await this.request('POST', `project/${project_id}/linked_file`, {name, parent_folder_id, provider, data}, (res) => {\n const message = JSON.parse(res!).new_file_id;\n return {message};\n }, {'X-Csrf-Token': identity.csrfToken});\n }\n}\n","/* eslint-disable @typescript-eslint/naming-convention */\nimport { Identity, BaseAPI, ProjectMessageResponseSchema } from './base';\nimport { FileEntity, DocumentEntity, FileRefEntity, FileType, FolderEntity, ProjectEntity } from '../core/projectTypes';\nimport { error as logError, log } from '../core/logger';\nimport { promisify } from 'node:util';\n\nconst SOCKET_OPERATION_TIMEOUT_MS = 15000;\n\nfunction decodePackedUtf8(text: string): string {\n return Buffer.from(text, 'latin1').toString('utf-8');\n}\n\nexport interface UpdateUserSchema {\n id: string,\n user_id: string,\n name: string,\n email: string,\n doc_id: string,\n row: number,\n column: number,\n last_updated_at?: number, //unix timestamp\n}\n\nexport interface OnlineUserSchema {\n client_age: number,\n client_id: string,\n connected: boolean,\n cursorData?: {\n column: number,\n doc_id: string,\n row: number,\n },\n email: string,\n first_name: string,\n last_name?: string,\n last_updated_at: string, //unix timestamp\n user_id: string,\n}\n\nexport interface UpdateSchema {\n doc: string, //doc id\n op?: {\n p: number, //position\n i?: string, //insert\n d?: string, //delete\n u?: boolean, //isUndo\n }[],\n v: number, //doc version number\n lastV?: number, //last version number\n hash?: string, //(not needed if lastV is provided)\n meta?: {\n source: string, //socketio client id\n ts: number, //unix timestamp\n user_id: string,\n }\n}\n\nexport interface EventsHandler {\n onFileCreated?: (parentFolderId:string, type:FileType, entity:FileEntity) => void,\n onFileRenamed?: (entityId:string, newName:string) => void,\n onFileRemoved?: (entityId:string) => void,\n onFileMoved?: (entityId:string, newParentFolderId:string) => void,\n onFileChanged?: (update:UpdateSchema) => void,\n //\n onDisconnected?: (reason?:unknown) => void,\n onProjectJoined?: (project:ProjectEntity) => void,\n onConnectionAccepted?: (publicId:string) => void,\n onClientUpdated?: (user:UpdateUserSchema) => void,\n onClientDisconnected?: (id:string) => void,\n //\n onReceivedMessage?: (message:ProjectMessageResponseSchema) => void,\n //\n onSpellCheckLanguageUpdated?: (language:string) => void,\n onCompilerUpdated?: (compiler:string) => void,\n onRootDocUpdated?: (rootDocId:string) => void,\n}\n\nexport interface ProjectSocket {\n readonly needsReinit:boolean;\n readonly connectionScheme:'Alt'|'realtime';\n init():void;\n disconnect():void;\n updateEventHandlers(handlers:EventsHandler):void;\n joinProject(projectId:string):Promise<ProjectEntity>;\n joinDoc(docId:string):Promise<{docLines:string[]; version:number; updates:unknown[]; ranges:unknown}>;\n leaveDoc(docId:string):Promise<void>;\n applyOtUpdate(docId:string, update:UpdateSchema):Promise<void>;\n getConnectedUsers():Promise<OnlineUserSchema[]>;\n updatePosition(docId:string, row:number, column:number):Promise<void>;\n}\n\ntype ConnectionScheme = 'Alt' | 'realtime';\ntype AlternativeSocketFactory = (\n url:string,\n api:BaseAPI,\n identity:Identity,\n projectId:string,\n record:Promise<ProjectEntity>,\n) => any;\n\nexport class SocketIOAPI implements ProjectSocket {\n private static alternativeSocketFactory?: AlternativeSocketFactory;\n private scheme: ConnectionScheme;\n private record?: Promise<ProjectEntity>;\n private joinedProject?: ProjectEntity;\n private pendingProjectJoin?: {\n promise:Promise<ProjectEntity>;\n resolve:(project:ProjectEntity) => void;\n reject:(reason?:unknown) => void;\n };\n private _handlers: Array<EventsHandler> = [];\n private connectedPublicId?: string;\n\n private socket?: any;\n private emit: any;\n /** Track the scheme used when the socket was last initialized */\n private _socketInitScheme?: ConnectionScheme;\n\n constructor(private url:string,\n private readonly api:BaseAPI,\n private readonly identity:Identity,\n private readonly projectId:string)\n {\n this.scheme = 'realtime';\n this.init();\n }\n\n static setAlternativeSocketFactory(factory: AlternativeSocketFactory) {\n SocketIOAPI.alternativeSocketFactory = factory;\n }\n\n init() {\n // CRITICAL: Properly disconnect old socket before creating a new one.\n // Without this, the old TCP connection is abandoned but still alive. When the\n // server later sends data on it (out-of-order/late packets), the OS TCP stack\n // responds with RST, which can cause the server to drop ALL connections from\n // this client — explaining the \"connection lost\" loop reported in issue #309.\n if (this.socket) {\n try {\n // Remove all listeners to prevent stale event handlers from firing\n if (typeof this.socket.removeAllListeners === 'function') {\n this.socket.removeAllListeners();\n }\n // Gracefully close the connection (sends FIN, not RST)\n if (typeof this.socket.disconnect === 'function') {\n this.socket.disconnect();\n }\n } catch {\n // Best-effort cleanup; socket may already be in a bad state\n }\n }\n\n // connect\n switch(this.scheme) {\n case 'Alt':\n if (!SocketIOAPI.alternativeSocketFactory) {\n throw new Error('The alternative Overleaf connection is not available in this runtime.');\n }\n this.socket = SocketIOAPI.alternativeSocketFactory(\n this.url, this.api, this.identity, this.projectId, this.record!,\n );\n break;\n case 'realtime':\n this.record = undefined;\n this.joinedProject = undefined;\n this.resetProjectJoin(new Error('The realtime connection was replaced.'));\n const query = `?projectId=${this.projectId}&t=${Date.now()}`;\n this.socket = this.api._initSocketV0(this.identity, query);\n break;\n }\n // create emit\n (this.socket.emit)[promisify.custom] = (event:string, ...args:any[]) => {\n const timeoutPromise = new Promise((_, reject) => {\n setTimeout(() => {\n reject('timeout');\n }, SOCKET_OPERATION_TIMEOUT_MS);\n });\n const waitPromise = new Promise((resolve, reject) => {\n this.socket.emit(event, ...args, (err:any, ...data:any[]) => {\n if (err) {\n reject(err);\n } else {\n resolve(data);\n }\n });\n });\n return Promise.race([waitPromise, timeoutPromise]);\n };\n this.emit = promisify(this.socket.emit).bind(this.socket);\n // resume handlers\n this.initInternalHandlers();\n // Re-register existing event handlers on the new socket\n this.resumeEventHandlers(this._handlers);\n // Track which scheme this socket was created with\n this._socketInitScheme = this.scheme;\n }\n\n /** Returns true if the socket needs re-initialization (scheme changed, or socket was never init'd) */\n get needsReinit(): boolean {\n return this._socketInitScheme !== this.scheme || !this.socket;\n }\n\n get connectionScheme(): ConnectionScheme {\n return this.scheme;\n }\n\n private initInternalHandlers() {\n this.socket.on('connect', () => {\n log('SocketIOAPI: connected', {scheme: this.scheme, projectId: this.projectId});\n });\n this.socket.on('connect_failed', (connectionError:any) => {\n log('SocketIOAPI: connect_failed', {scheme: this.scheme, projectId: this.projectId, error: connectionError});\n });\n this.socket.on('disconnect', (reason:any) => {\n log('SocketIOAPI: disconnect event', {scheme: this.scheme, projectId: this.projectId, reason});\n if (this.scheme==='realtime') {\n this.joinedProject = undefined;\n this.connectedPublicId = undefined;\n this.resetProjectJoin(new Error(`Overleaf realtime connection closed: ${String(reason ?? 'unknown')}`));\n }\n });\n this.socket.on('reconnecting', (delay:any, attempt:any) => {\n log('SocketIOAPI: reconnecting', {scheme: this.scheme, projectId: this.projectId, delay, attempt});\n });\n this.socket.on('reconnect', (transport:any, attempts:any) => {\n log('SocketIOAPI: reconnected', {scheme: this.scheme, projectId: this.projectId, transport, attempts});\n });\n this.socket.on('reconnect_failed', (error:any) => {\n log('SocketIOAPI: reconnect_failed', {scheme: this.scheme, projectId: this.projectId, error});\n });\n this.socket.on('forceDisconnect', (message:string, delay=10) => {\n log('SocketIOAPI: forceDisconnect', {message, delay, projectId: this.projectId});\n });\n this.socket.on('connectionRejected', (err:any) => {\n log('SocketIOAPI: connectionRejected', {scheme: this.scheme, projectId: this.projectId, error: err});\n // Disable auto-reconnect on this socket: the server explicitly rejected\n // our connection parameters. Reconnecting would just get rejected again,\n // creating unnecessary TCP connection churn (and RST packets).\n if (this.socket.io && typeof this.socket.io.reconnect === 'function') {\n this.socket.io.reconnect(false);\n }\n });\n this.socket.on('error', (err:any) => {\n // Log error instead of throwing to avoid crashing the extension\n const message = err?.message || String(err);\n logError(`Overleaf connection error: ${message}`);\n });\n\n if (this.scheme==='realtime') {\n this.pendingProjectJoin ??= this.createProjectJoin();\n this.socket.on('joinProjectResponse', (res:any) => {\n const publicId = res.publicId as string;\n const project = res.project as ProjectEntity;\n this.socket.markProjectJoined?.();\n log('SocketIOAPI: project joined', {scheme:this.scheme, projectId:this.projectId, publicId});\n this.connectedPublicId = publicId;\n this.joinedProject = project;\n this.pendingProjectJoin?.resolve(project);\n for (const handler of this._handlers) {\n handler.onProjectJoined?.(project);\n handler.onConnectionAccepted?.(publicId);\n }\n });\n this.socket.on('connectionRejected', (err:any) => {\n this.pendingProjectJoin?.reject(err?.message || err);\n });\n }\n }\n\n private createProjectJoin() {\n let resolve!:(project:ProjectEntity) => void;\n let reject!:(reason?:unknown) => void;\n const promise = new Promise<ProjectEntity>((resolveProject, rejectProject) => {\n resolve = resolveProject;\n reject = rejectProject;\n });\n void promise.catch(() => undefined);\n return {promise, resolve, reject};\n }\n\n private resetProjectJoin(reason?:unknown) {\n if (reason!==undefined) { this.pendingProjectJoin?.reject(reason); }\n this.pendingProjectJoin = this.createProjectJoin();\n }\n\n private waitForRealtimeProject():Promise<ProjectEntity> {\n return this.joinedProject\n ? Promise.resolve(this.joinedProject)\n : this.pendingProjectJoin!.promise;\n }\n\n private async emitProjectEvent(event:string, ...args:any[]) {\n if (this.scheme==='realtime') { await this.waitForRealtimeProject(); }\n return this.emit(event, ...args);\n }\n\n disconnect() {\n this.socket.disconnect();\n }\n\n get handlers() {\n return this._handlers;\n }\n\n get isUsingAlternativeConnectionScheme() {\n return this.scheme==='Alt';\n }\n\n toggleAlternativeConnectionScheme(url: string, updatedRecord?: ProjectEntity) {\n this.scheme = this.scheme==='Alt' ? 'realtime' : 'Alt';\n if (updatedRecord) {\n this.url = url;\n this.record = Promise.resolve(updatedRecord);\n }\n }\n\n resumeEventHandlers(handlers: Array<EventsHandler>) {\n this._handlers = [];\n handlers.forEach((handler) => {\n this.updateEventHandlers(handler);\n });\n }\n\n updateEventHandlers(handlers: EventsHandler) {\n this._handlers.push(handlers);\n Object.values(handlers).forEach((handler) => {\n switch (handler) {\n case handlers.onFileCreated:\n this.socket.on('reciveNewDoc', (parentFolderId:string, doc:DocumentEntity) => {\n handler(parentFolderId, 'doc', doc);\n });\n this.socket.on('reciveNewFile', (parentFolderId:string, file:FileRefEntity) => {\n handler(parentFolderId, 'file', file);\n });\n this.socket.on('reciveNewFolder', (parentFolderId:string, folder:FolderEntity) => {\n handler(parentFolderId, 'folder', folder);\n });\n break;\n case handlers.onFileRenamed:\n this.socket.on('reciveEntityRename', (entityId:string, newName:string) => {\n handler(entityId, newName);\n });\n break;\n case handlers.onFileRemoved:\n this.socket.on('removeEntity', (entityId:string) => {\n handler(entityId);\n });\n break;\n case handlers.onFileMoved:\n this.socket.on('reciveEntityMove', (entityId:string, folderId:string) => {\n handler(entityId, folderId);\n });\n break;\n case handlers.onFileChanged:\n this.socket.on('otUpdateApplied', (update: UpdateSchema) => {\n handler(update);\n });\n break;\n case handlers.onDisconnected:\n this.socket.on('disconnect', (reason:unknown) => {\n handler(reason);\n });\n break;\n case handlers.onProjectJoined:\n break;\n case handlers.onConnectionAccepted:\n this.socket.on('connectionAccepted', (_:any, publicId:any) => {\n handler(publicId);\n });\n if (this.connectedPublicId!==undefined) {\n queueMicrotask(() => handler(this.connectedPublicId!));\n }\n break;\n case handlers.onClientUpdated:\n this.socket.on('clientTracking.clientUpdated', (user:UpdateUserSchema) => {\n handler(user);\n });\n break;\n case handlers.onClientDisconnected:\n this.socket.on('clientTracking.clientDisconnected', (id:string) => {\n handler(id);\n });\n break;\n case handlers.onReceivedMessage:\n this.socket.on('new-chat-message', (message:ProjectMessageResponseSchema) => {\n handler(message);\n });\n break;\n case handlers.onSpellCheckLanguageUpdated:\n this.socket.on('spellCheckLanguageUpdated', (language:string) => {\n handler(language);\n });\n break;\n case handlers.onCompilerUpdated:\n this.socket.on('compilerUpdated', (compiler:string) => {\n handler(compiler);\n });\n break;\n case handlers.onRootDocUpdated:\n this.socket.on('rootDocUpdated', (rootDocId:string) => {\n handler(rootDocId);\n });\n break;\n default:\n break;\n }\n });\n }\n\n get unSyncFileChanges(): number {\n return this.scheme==='Alt' ? this.socket.unSyncedChanges : 0;\n }\n\n async syncFileChanges() {\n if (this.scheme==='Alt') {\n return await this.socket.uploadToVFS();\n }\n }\n\n /**\n * Reference: services/web/frontend/js/ide/connection/ConnectionManager.js#L427\n * @param {string} projectId - The project id.\n * @returns {Promise}\n */\n async joinProject(project_id:string): Promise<ProjectEntity> {\n const timeoutPromise: Promise<ProjectEntity> = new Promise((_, reject) => {\n setTimeout(() => {\n reject('timeout');\n }, SOCKET_OPERATION_TIMEOUT_MS);\n });\n\n switch(this.scheme) {\n case 'Alt':\n return Promise.race([\n this.emit('joinProject', {project_id}).then((returns:[ProjectEntity]) => returns[0]),\n timeoutPromise,\n ]);\n case 'realtime':\n return Promise.race([this.waitForRealtimeProject(), timeoutPromise]);\n }\n }\n\n /**\n * Reference: services/web/frontend/js/ide/editor/Document.js#L500\n * @param {string} docId - The document id.\n * @returns {Promise}\n */\n async joinDoc(docId:string) {\n return this.emitProjectEvent('joinDoc', docId, { encodeRanges: true })\n .then((returns: [Array<string>, number, Array<any>, any]) => {\n const [docLinesAscii, version, updates, ranges] = returns;\n const docLines = docLinesAscii.map((line) => decodePackedUtf8(line));\n return {docLines, version, updates, ranges};\n });\n }\n\n /**\n * Reference: services/web/frontend/js/ide/editor/Document.js#L591\n * @param {string} docId - The document id.\n * @returns {Promise}\n */\n async leaveDoc(docId:string) {\n return this.emitProjectEvent('leaveDoc', docId)\n .then(() => {\n return;\n });\n }\n\n /**\n * Reference: services/web/frontend/js/ide/editor/ShareJsDocs.js#L78\n * @param {string} docId - The document id.\n * @param {any} update - The changes.\n * @returns {Promise}\n */\n async applyOtUpdate(docId:string, update:UpdateSchema) {\n try {\n await this.emitProjectEvent('applyOtUpdate', docId, update);\n } catch (error) {\n let detail: string;\n if (error instanceof Error) {\n detail = error.message;\n } else if (typeof error==='string') {\n detail = error;\n } else {\n try { detail = JSON.stringify(error); } catch { detail = String(error); }\n }\n throw new Error(`Overleaf document update rejected: ${detail}`);\n }\n }\n\n /**\n * Reference: services/web/frontend/js/ide/online-users/OnlineUserManager.js#L42\n * @returns {Promise}\n */\n async getConnectedUsers(): Promise<OnlineUserSchema[]> {\n return this.emitProjectEvent('clientTracking.getConnectedUsers')\n .then((returns:[OnlineUserSchema[]]) => {\n const [connectedUsers] = returns;\n return connectedUsers;\n });\n }\n\n /**\n * Reference: services/web/frontend/js/ide/online-users/OnlineUserManager.js#L150\n * @param {string} docId - The document id.\n * @returns {Promise}\n */\n async updatePosition(doc_id:string, row:number, column:number) {\n return this.emitProjectEvent('clientTracking.updatePosition', {row, column, doc_id})\n .then(() => {\n return;\n });\n }\n}\n","/* eslint-disable @typescript-eslint/naming-convention */\n\nexport type FileType = 'doc' | 'file' | 'folder' | 'outputs';\nexport type FolderKey = 'docs' | 'fileRefs' | 'folders' | 'outputs';\n\nexport const FolderKeys: Readonly<Record<string, FolderKey>> = {\n folder: 'folders',\n doc: 'docs',\n file: 'fileRefs',\n outputs: 'outputs',\n};\n\nexport interface ProjectLinkedFileProvider {\n provider: 'project_file';\n source_project_id: string;\n source_entity_path: string;\n}\n\nexport interface UrlLinkedFileProvider {\n provider: 'url';\n url: string;\n}\n\nexport interface FileEntity {\n _id: string;\n name: string;\n _type?: FileType;\n readonly?: boolean;\n}\n\nexport interface DocumentEntity extends FileEntity {\n version?: number;\n mtime?: number;\n lastVersion?: number;\n localCache?: string;\n remoteCache?: string;\n}\n\nexport interface FileRefEntity extends FileEntity {\n linkedFileData: ProjectLinkedFileProvider | UrlLinkedFileProvider | null;\n created: string;\n}\n\nexport interface OutputFileEntity extends FileEntity {\n path: string;\n url: string;\n type: string;\n build: string;\n}\n\nexport interface FolderEntity extends FileEntity {\n docs: DocumentEntity[];\n fileRefs: FileRefEntity[];\n folders: FolderEntity[];\n outputs?: OutputFileEntity[];\n}\n\nexport interface MemberEntity {\n _id: string;\n first_name: string;\n last_name?: string;\n email: string;\n privileges?: string;\n signUpDate?: string;\n}\n\nexport interface ProjectSettingsSchema {\n learnedWords: string[];\n languages: Array<{code:string; name:string}>;\n compilers: Array<{code:string; name:string}>;\n}\n\nexport interface ProjectEntity {\n _id: string;\n name: string;\n rootDoc_id: string;\n rootFolder: FolderEntity[];\n publicAccessLevel: string;\n compiler: string;\n spellCheckLanguage: string;\n deletedDocs: Array<{\n _id: string;\n name: string;\n deletedAt: string;\n }>;\n members: MemberEntity[];\n invites: MemberEntity[];\n owner: MemberEntity;\n features: Record<string, unknown>;\n settings: ProjectSettingsSchema;\n}\n","import {mkdir, readFile, writeFile, chmod} from 'node:fs/promises';\nimport {homedir} from 'node:os';\nimport {dirname, join, resolve} from 'node:path';\nimport type {Identity} from '../api/base';\n\nexport interface ServerSession {\n url: string;\n userId: string;\n userEmail: string;\n identity: Identity;\n updatedAt: string;\n}\n\nexport interface LeafRelayConfig {\n version: 1;\n servers: Record<string, ServerSession>;\n knownServers?:Record<string,{name:string; url:string}>;\n}\n\nexport function configPath(environment: NodeJS.ProcessEnv = process.env): string {\n return environment.LEAFRELAY_CONFIG\n ? resolve(environment.LEAFRELAY_CONFIG)\n : join(environment.LEAFRELAY_HOME ? resolve(environment.LEAFRELAY_HOME) : join(homedir(), '.leafrelay'), 'config.json');\n}\n\nexport function normalizeServerUrl(value: string): string {\n const url = new URL(value.includes('://') ? value : `https://${value}`);\n url.pathname = '/';\n url.search = '';\n url.hash = '';\n return url.href;\n}\n\nexport function serverKey(value: string): string {\n return new URL(normalizeServerUrl(value)).host;\n}\n\nexport async function readConfig(path = configPath()): Promise<LeafRelayConfig> {\n try {\n const parsed = JSON.parse(await readFile(path, 'utf8')) as Partial<LeafRelayConfig>;\n if (parsed.version!==1 || typeof parsed.servers!=='object' || parsed.servers===null) {\n throw new Error(`Unsupported LeafRelay configuration in ${path}`);\n }\n return parsed as LeafRelayConfig;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code==='ENOENT') {\n return {version:1, servers:{}, knownServers:{}};\n }\n throw error;\n }\n}\n\nexport async function writeConfig(config: LeafRelayConfig, path = configPath()): Promise<void> {\n await mkdir(dirname(path), {recursive:true, mode:0o700});\n await writeFile(path, `${JSON.stringify(config, null, 2)}\\n`, {encoding:'utf8', mode:0o600});\n await chmod(path, 0o600);\n}\n\nexport async function saveServerSession(session: ServerSession, path = configPath()): Promise<void> {\n const config = await readConfig(path);\n const key = serverKey(session.url);\n config.servers[key] = session;\n config.knownServers ??= {};\n config.knownServers[key] ??= {name:key, url:session.url};\n await writeConfig(config, path);\n}\n\nexport async function saveKnownServer(name:string, url:string, path=configPath()):Promise<void> {\n const config = await readConfig(path);\n const key = serverKey(url);\n config.knownServers ??= {};\n config.knownServers[key] = {name, url:normalizeServerUrl(url)};\n await writeConfig(config, path);\n}\n\nexport async function removeKnownServer(server:string, path=configPath()):Promise<void> {\n const config = await readConfig(path);\n const key = serverKey(server);\n delete config.servers[key];\n delete config.knownServers?.[key];\n await writeConfig(config, path);\n}\n\nexport async function removeServerSession(server:string, path=configPath()):Promise<void> {\n const config = await readConfig(path);\n delete config.servers[serverKey(server)];\n await writeConfig(config, path);\n}\n\nexport async function getServerSession(\n server: string,\n environment: NodeJS.ProcessEnv = process.env,\n path = configPath(environment),\n): Promise<ServerSession | undefined> {\n const key = serverKey(server);\n const config = await readConfig(path);\n const stored = config.servers[key];\n const cookie = environment.LEAFRELAY_COOKIE;\n if (!cookie) { return stored; }\n return {\n url: stored?.url ?? normalizeServerUrl(server),\n userId: stored?.userId ?? '',\n userEmail: stored?.userEmail ?? '',\n identity: {cookies:cookie, csrfToken:stored?.identity.csrfToken ?? ''},\n updatedAt: stored?.updatedAt ?? new Date(0).toISOString(),\n };\n}\n","import {lstat, mkdir, readFile, readdir, rm, writeFile} from 'node:fs/promises';\nimport {dirname, relative, resolve, sep} from 'node:path';\nimport {watch, type FSWatcher} from 'chokidar';\nimport type {ReplicaFileSystem} from '../sync/syncEngine';\n\nfunction projectPath(root:string, path:string):string {\n const target = resolve(root, path.replace(/^\\/+/, ''));\n const relativePath = relative(root, target);\n if (relativePath.startsWith('..') || relativePath=== '..') {\n throw new Error(`Path escapes the local project: ${path}`);\n }\n return target;\n}\n\nfunction syncPath(root:string, path:string):string {\n return `/${relative(root, path).split(sep).join('/')}`;\n}\n\nexport class NodeReplicaFileSystem implements ReplicaFileSystem {\n private watcher?:FSWatcher;\n\n constructor(\n private readonly root:string,\n private readonly ignore:(path:string)=>boolean,\n ) {}\n\n async listFiles():Promise<string[]> {\n const files:string[] = [];\n const visit = async (directory:string) => {\n for (const entry of await readdir(directory, {withFileTypes:true})) {\n const absolute = resolve(directory, entry.name);\n const path = syncPath(this.root, absolute);\n if (this.ignore(path) || entry.name.startsWith('.') || entry.isSymbolicLink()) { continue; }\n if (entry.isDirectory()) { await visit(absolute); }\n else if (entry.isFile()) { files.push(path); }\n }\n };\n await visit(this.root);\n return files.sort();\n }\n\n async read(path:string):Promise<Uint8Array|undefined> {\n const target = projectPath(this.root, path);\n try {\n const stat = await lstat(target);\n if (!stat.isFile() || stat.isSymbolicLink()) { return undefined; }\n return new Uint8Array(await readFile(target));\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code==='ENOENT') { return undefined; }\n throw error;\n }\n }\n\n async write(path:string, content:Uint8Array):Promise<void> {\n const target = projectPath(this.root, path);\n await mkdir(dirname(target), {recursive:true});\n await writeFile(target, content);\n }\n\n async remove(path:string):Promise<void> {\n await rm(projectPath(this.root, path), {force:true, recursive:true});\n }\n\n async watch(onChange:(path:string)=>void):Promise<() => Promise<void>> {\n this.watcher = watch(this.root, {\n ignoreInitial:true,\n followSymlinks:false,\n ignored:path => {\n const relativePath = relative(this.root, path);\n if (!relativePath) { return false; }\n const normalized = `/${relativePath.split(sep).join('/')}`;\n return this.ignore(normalized) || normalized.split('/').some(part => part.startsWith('.'));\n },\n awaitWriteFinish:{stabilityThreshold:200, pollInterval:50},\n });\n const handler = (path:string) => onChange(syncPath(this.root, path));\n this.watcher.on('add', handler).on('change', handler).on('unlink', handler);\n await new Promise<void>((resolveReady, reject) => {\n this.watcher!.once('ready', resolveReady).once('error', reject);\n });\n return async () => { await this.watcher?.close(); };\n }\n}\n","import {readFile} from 'node:fs/promises';\nimport {resolve} from 'node:path';\n\nexport interface LocalProjectSettings {\n uri: string;\n serverName: string;\n serverUrl: string;\n projectId: string;\n projectName: string;\n userId?: string;\n localReplica: {\n settings: Record<string, unknown>;\n };\n}\n\nfunction parseProjectUri(value: string) {\n const uri = new URL(value);\n const decodedQuery = decodeURIComponent(uri.search.slice(1));\n const query = new URLSearchParams(decodedQuery);\n const projectId = query.get('project');\n if (!projectId) {\n throw new Error('The project URI in .overleaf/settings.json does not contain a project ID.');\n }\n return {\n serverName:uri.host,\n projectId,\n projectName:decodeURIComponent(uri.pathname.split('/').filter(Boolean)[0] ?? ''),\n userId:query.get('user') ?? undefined,\n };\n}\n\nexport async function readProjectSettings(directory: string): Promise<LocalProjectSettings> {\n const settingsPath = resolve(directory, '.overleaf', 'settings.json');\n const raw = JSON.parse(await readFile(settingsPath, 'utf8')) as Record<string, unknown>;\n if (typeof raw.uri!=='string') {\n throw new Error(`${settingsPath} does not contain a valid project URI.`);\n }\n const parsed = parseProjectUri(raw.uri);\n const serverName = typeof raw.serverName==='string' ? raw.serverName : parsed.serverName;\n const localReplica = raw.localReplica as {settings?:Record<string, unknown>} | undefined;\n return {\n uri:raw.uri,\n serverName,\n serverUrl:typeof raw.serverUrl==='string' ? raw.serverUrl : `https://${serverName}/`,\n projectId:parsed.projectId,\n projectName:typeof raw.projectName==='string' ? raw.projectName : parsed.projectName,\n userId:parsed.userId,\n localReplica:{settings:localReplica?.settings ?? {}},\n };\n}\n","import {resolve} from 'node:path';\nimport {log} from '../core/logger';\nimport {createIgnoreMatcher} from '../sync/ignore';\nimport {RemoteProject} from '../sync/remoteProject';\nimport {SyncEngine, type RemoteReplica} from '../sync/syncEngine';\nimport {getServerSession} from './config';\nimport {NodeReplicaFileSystem} from './localFileSystem';\nimport {readProjectSettings} from './projectSettings';\nimport {FileSyncStateStore} from './syncStateStore';\n\nexport interface RunningServe {\n readonly root:string;\n readonly serverName:string;\n readonly projectId:string;\n readonly projectName:string;\n conflicts():string[];\n resolveConflict(path:string, winner:'local'|'remote'):Promise<void>;\n retry(path:string):Promise<void>;\n stop():Promise<void>;\n}\n\nexport interface StartServeOptions {\n cookie?:string;\n log?:(message:string) => void;\n onConflict?:(path:string, reason:string) => void;\n remote?:ServeRemoteProject;\n}\n\nexport interface ServeRemoteProject extends RemoteReplica {\n connect():Promise<void>;\n disconnect():void;\n}\n\nexport async function startServe(directory=process.cwd(), options:StartServeOptions={}):Promise<RunningServe> {\n const root = resolve(directory);\n const settings = await readProjectSettings(root);\n const session = await getServerSession(settings.serverName);\n if (!session) {\n throw new Error(`No login is stored for ${settings.serverName}. Run: leafrelay login ${settings.serverName}`);\n }\n const cookie = options.cookie || process.env.LEAFRELAY_COOKIE || session.identity.cookies;\n const remote = options.remote ?? new RemoteProject(session.url || settings.serverUrl, settings.projectId, cookie);\n await remote.connect();\n\n const configuredPatterns = settings.localReplica.settings['ignore-patterns'];\n const ignore = createIgnoreMatcher(configuredPatterns);\n const local = new NodeReplicaFileSystem(root, ignore);\n const engine = new SyncEngine({\n projectUri:settings.uri,\n local,\n remote,\n stateStore:new FileSyncStateStore(root, settings.uri),\n ignore,\n log:options.log ?? log,\n onConflict:options.onConflict ?? ((path, reason) => {\n (options.log ?? log)(`Conflict paused for ${path}: ${reason}`);\n }),\n });\n try {\n await engine.start();\n } catch (error) {\n remote.disconnect();\n throw error;\n }\n (options.log ?? log)(`LeafRelay is serving ${root} (${settings.projectName}).`);\n return {\n root,\n serverName:settings.serverName,\n projectId:settings.projectId,\n projectName:settings.projectName,\n conflicts:() => engine.getConflicts(),\n resolveConflict:(path, winner) => engine.resolveConflict(path, winner),\n retry:path => engine.retry(path),\n stop:async () => {\n await engine.stop();\n remote.disconnect();\n },\n };\n}\n","import {minimatch} from 'minimatch';\n\nexport const DEFAULT_IGNORE_PATTERNS = [\n '**/.*',\n '**/.*/**',\n '**/*.aux',\n '**/__latexindent*',\n '**/*.bbl',\n '**/*.bcf',\n '**/*.blg',\n '**/*.fdb_latexmk',\n '**/*.fls',\n '**/*.lof',\n '**/*.log',\n '**/*.lot',\n '**/*.out',\n '**/*.run.xml',\n '**/*.synctex(busy)',\n '**/*.synctex.gz',\n '**/*.toc',\n '**/*.xdv',\n '**/main.pdf',\n '**/output.pdf',\n];\n\nexport function createIgnoreMatcher(patterns:unknown): (path:string)=>boolean {\n const configured = Array.isArray(patterns)\n ? patterns.filter((pattern):pattern is string => typeof pattern==='string')\n : [];\n const allPatterns = [...DEFAULT_IGNORE_PATTERNS, ...configured];\n return path => {\n const normalized = path.replace(/^\\/+/, '');\n return normalized.split('/').some(part => part.startsWith('.')) ||\n allPatterns.some(pattern => minimatch(normalized, pattern, {dot:true}));\n };\n}\n","import {createHash} from 'node:crypto';\nimport {posix} from 'node:path';\nimport DiffMatchPatch from 'diff-match-patch';\nimport {BaseAPI, type Identity, type ProjectFileTreeDiffResponseSchema} from '../api/base';\nimport {SocketIOAPI, type UpdateSchema} from '../api/socketio';\nimport type {\n DocumentEntity,\n FileEntity,\n FileRefEntity,\n FileType,\n FolderEntity,\n ProjectEntity,\n} from '../core/projectTypes';\n\nexport interface RemoteEntry {\n path: string;\n type: FileType;\n entity: FileEntity;\n parent?: FolderEntity;\n}\n\nexport type RemoteChange = {path:string; previousPath?:string};\n\nexport interface RemoteProjectTransport {\n api:BaseAPI;\n identity:Identity;\n socket:SocketIOAPI;\n}\n\nfunction normalizePath(path: string): string {\n const normalized = `/${posix.normalize(path).replace(/^\\/+/, '')}`;\n if (normalized.includes('/../') || normalized.endsWith('/..')) {\n throw new Error(`Invalid project path: ${path}`);\n }\n return normalized;\n}\n\nfunction textContent(content: Uint8Array): string | undefined {\n if (content.includes(0)) { return undefined; }\n try {\n return new TextDecoder('utf-8', {fatal:true}).decode(content);\n } catch {\n return undefined;\n }\n}\n\nexport class RemoteProject {\n private readonly api: BaseAPI;\n private identity!: Identity;\n private socket!: SocketIOAPI;\n private project!: ProjectEntity;\n private readonly entries = new Map<string, RemoteEntry>();\n private readonly idToPath = new Map<string, string>();\n private changeHandler?: (change:RemoteChange) => void;\n private reconnectHandler?: () => void;\n private readonly externalTransport?:RemoteProjectTransport;\n\n constructor(\n private readonly url:string,\n private readonly projectId:string,\n private readonly cookies:string,\n transport?:RemoteProjectTransport,\n ) {\n this.externalTransport = transport;\n this.api = transport?.api ?? new BaseAPI(url);\n }\n\n async connect(): Promise<void> {\n if (this.externalTransport) {\n this.identity = this.externalTransport.identity;\n this.socket = this.externalTransport.socket;\n } else {\n const login = await this.api.cookiesLogin(this.cookies);\n if (login.type!=='success' || !login.identity) {\n throw new Error(login.message || `Authentication to ${this.url} failed.`);\n }\n this.identity = login.identity;\n this.socket = new SocketIOAPI(this.url, this.api, this.identity, this.projectId);\n }\n this.project = await this.socket.joinProject(this.projectId);\n this.reindex();\n this.registerEvents();\n }\n\n disconnect() {\n if (!this.externalTransport) { this.socket?.disconnect(); }\n }\n\n onChange(handler: (change:RemoteChange) => void) {\n this.changeHandler = handler;\n }\n\n onReconnect(handler:() => void) {\n this.reconnectHandler = handler;\n }\n\n listEntries(): RemoteEntry[] {\n return [...this.entries.values()];\n }\n\n entry(path: string): RemoteEntry | undefined {\n return this.entries.get(normalizePath(path));\n }\n\n async read(path: string): Promise<Uint8Array> {\n const entry = this.requireEntry(path);\n if (entry.type==='doc') {\n const result = await this.socket.joinDoc(entry.entity._id);\n return new TextEncoder().encode(result.docLines.join('\\n'));\n }\n if (entry.type==='file') {\n const result = await this.api.getFile(this.identity, this.projectId, entry.entity._id);\n if (result.type==='success' && result.content) { return result.content; }\n throw new Error(`Could not download ${path}.`);\n }\n throw new Error(`${path} is not a file.`);\n }\n\n async mkdir(path: string): Promise<void> {\n const normalized = normalizePath(path);\n if (this.entries.has(normalized)) { return; }\n const {parent, name} = await this.ensureParent(normalized);\n const result = await this.api.addFolder(this.identity, this.projectId, name, parent._id);\n if (result.type!=='success' || !result.entity) {\n throw new Error(result.message || `Could not create ${normalized}.`);\n }\n const folder = result.entity as FolderEntity;\n folder._type = 'folder';\n folder.docs ??= [];\n folder.fileRefs ??= [];\n folder.folders ??= [];\n parent.folders.push(folder);\n this.reindex();\n }\n\n async write(path: string, content: Uint8Array): Promise<void> {\n const normalized = normalizePath(path);\n const existing = this.entries.get(normalized);\n if (existing?.type==='folder') {\n throw new Error(`${normalized} is a directory.`);\n }\n if (existing?.type==='doc') {\n await this.writeDocument(existing.entity as DocumentEntity, content);\n return;\n }\n if (existing) {\n await this.remove(normalized);\n }\n const {parent, name} = await this.ensureParent(normalized);\n const text = textContent(content);\n if (text!==undefined) {\n const created = await this.api.addDoc(this.identity, this.projectId, parent._id, name);\n if (created.type!=='success' || !created.entity) {\n throw new Error(created.message || `Could not create ${normalized}.`);\n }\n const entity = created.entity as DocumentEntity;\n entity._type = 'doc';\n parent.docs.push(entity);\n this.reindex();\n if (content.length!==0) { await this.writeDocument(entity, content); }\n return;\n }\n const uploaded = await this.api.uploadFile(this.identity, this.projectId, parent._id, name, content);\n if (uploaded.type!=='success' || !uploaded.entity) {\n throw new Error(uploaded.message || `Could not upload ${normalized}.`);\n }\n const entity = uploaded.entity as FileRefEntity;\n entity._type = 'file';\n parent.fileRefs.push(entity);\n this.reindex();\n }\n\n async remove(path: string): Promise<void> {\n const normalized = normalizePath(path);\n const entry = this.requireEntry(normalized);\n if (!entry.parent) { throw new Error('The project root cannot be removed.'); }\n const result = await this.api.deleteEntity(this.identity, this.projectId, entry.type, entry.entity._id);\n if (result.type!=='success') {\n throw new Error(result.message || `Could not remove ${normalized}.`);\n }\n this.removeFromParent(entry);\n this.reindex();\n }\n\n async getCurrentVersion(): Promise<number> {\n const response = await this.api.proxyToHistoryApiAndGetUpdates(this.identity, this.projectId);\n const version = response.updates?.updates.at(0)?.toV ?? 0;\n if (response.type!=='success' || !Number.isInteger(version)) {\n throw new Error(response.message || 'Could not determine the current Overleaf project version.');\n }\n return version;\n }\n\n async getFileTreeDiff(from:number, to:number): Promise<ProjectFileTreeDiffResponseSchema | undefined> {\n if (from>=to) { return {diff:[]}; }\n const response = await this.api.proxyToHistoryApiAndGetFileTreeDiff(\n this.identity, this.projectId, from, to,\n );\n if (response.type==='success') { return response.treeDiff; }\n if (response.statusCode===404) { return undefined; }\n throw new Error(response.message || 'Could not load the Overleaf file-tree history.');\n }\n\n private async writeDocument(entity: DocumentEntity, content: Uint8Array): Promise<void> {\n const text = textContent(content);\n if (text===undefined) {\n const path = this.idToPath.get(entity._id)!;\n await this.remove(path);\n await this.write(path, content);\n return;\n }\n const remote = await this.socket.joinDoc(entity._id);\n const previous = remote.docLines.join('\\n');\n if (previous===text) { return; }\n let position = 0;\n const operations:NonNullable<UpdateSchema['op']> = [];\n for (const part of new DiffMatchPatch().diff_main(previous, text)) {\n const start = position;\n if (part[0]!==-1) { position += part[1].length; }\n if (part[0]===1) { operations.push({p:start, i:part[1]}); }\n if (part[0]===-1) { operations.push({p:start, d:part[1]}); }\n }\n const update: UpdateSchema = {\n doc:entity._id,\n v:remote.version,\n hash:createHash('sha1').update(`blob ${text.length}\\x00${text}`).digest('hex'),\n op:operations,\n };\n await this.socket.applyOtUpdate(entity._id, update);\n }\n\n private async ensureParent(path: string): Promise<{parent:FolderEntity; name:string}> {\n const name = posix.basename(path);\n const parentPath = posix.dirname(path);\n if (parentPath!=='/' && !this.entries.has(parentPath)) {\n await this.mkdir(parentPath);\n }\n const parentEntry = parentPath==='/' ? this.entries.get('/') : this.entries.get(parentPath);\n if (!parentEntry || parentEntry.type!=='folder') {\n throw new Error(`Parent directory ${parentPath} does not exist.`);\n }\n return {parent:parentEntry.entity as FolderEntity, name};\n }\n\n private requireEntry(path: string): RemoteEntry {\n const normalized = normalizePath(path);\n const entry = this.entries.get(normalized);\n if (!entry) { throw new Error(`Remote path not found: ${normalized}`); }\n return entry;\n }\n\n private reindex() {\n this.entries.clear();\n this.idToPath.clear();\n const root = this.project.rootFolder[0];\n root._type = 'folder';\n this.indexFolder(root, '/');\n }\n\n private indexFolder(folder: FolderEntity, path: string, parent?:FolderEntity) {\n this.entries.set(path, {path, type:'folder', entity:folder, parent});\n this.idToPath.set(folder._id, path);\n for (const child of folder.folders ?? []) {\n child._type = 'folder';\n this.indexFolder(child, normalizePath(posix.join(path, child.name)), folder);\n }\n for (const child of folder.docs ?? []) {\n child._type = 'doc';\n const childPath = normalizePath(posix.join(path, child.name));\n this.entries.set(childPath, {path:childPath, type:'doc', entity:child, parent:folder});\n this.idToPath.set(child._id, childPath);\n }\n for (const child of folder.fileRefs ?? []) {\n child._type = 'file';\n const childPath = normalizePath(posix.join(path, child.name));\n this.entries.set(childPath, {path:childPath, type:'file', entity:child, parent:folder});\n this.idToPath.set(child._id, childPath);\n }\n }\n\n private folderById(id:string): FolderEntity | undefined {\n const path = this.idToPath.get(id);\n const entry = path ? this.entries.get(path) : undefined;\n return entry?.type==='folder' ? entry.entity as FolderEntity : undefined;\n }\n\n private removeFromParent(entry: RemoteEntry) {\n if (!entry.parent) { return; }\n const collection = entry.type==='folder'\n ? entry.parent.folders\n : entry.type==='doc' ? entry.parent.docs : entry.parent.fileRefs;\n const index = collection.findIndex(item => item._id===entry.entity._id);\n if (index!==-1) { collection.splice(index, 1); }\n }\n\n private emitChange(path:string, previousPath?:string) {\n this.changeHandler?.({path:normalizePath(path), previousPath});\n }\n\n private registerEvents() {\n this.socket.updateEventHandlers({\n onProjectJoined:project => {\n this.project = project;\n this.reindex();\n this.reconnectHandler?.();\n },\n onFileCreated:(parentId, type, entity) => {\n const parent = this.folderById(parentId);\n if (!parent || type==='outputs') { return; }\n if (this.idToPath.has(entity._id)) { return; }\n entity._type = type;\n if (type==='folder') {\n const folder = entity as FolderEntity;\n folder.docs ??= [];\n folder.fileRefs ??= [];\n folder.folders ??= [];\n parent.folders.push(folder);\n } else if (type==='doc') {\n parent.docs.push(entity as DocumentEntity);\n } else {\n parent.fileRefs.push(entity as FileRefEntity);\n }\n const parentPath = this.idToPath.get(parentId) ?? '/';\n this.reindex();\n this.emitChange(posix.join(parentPath, entity.name));\n },\n onFileRenamed:(entityId, newName) => {\n const previousPath = this.idToPath.get(entityId);\n if (!previousPath) { return; }\n this.entries.get(previousPath)!.entity.name = newName;\n this.reindex();\n this.emitChange(this.idToPath.get(entityId)!, previousPath);\n },\n onFileRemoved:(entityId) => {\n const previousPath = this.idToPath.get(entityId);\n if (!previousPath) { return; }\n const entry = this.entries.get(previousPath)!;\n this.removeFromParent(entry);\n this.reindex();\n this.emitChange(previousPath);\n },\n onFileMoved:(entityId, parentId) => {\n const previousPath = this.idToPath.get(entityId);\n const nextParent = this.folderById(parentId);\n if (!previousPath || !nextParent) { return; }\n const entry = this.entries.get(previousPath)!;\n this.removeFromParent(entry);\n if (entry.type==='folder') { nextParent.folders.push(entry.entity as FolderEntity); }\n else if (entry.type==='doc') { nextParent.docs.push(entry.entity as DocumentEntity); }\n else { nextParent.fileRefs.push(entry.entity as FileRefEntity); }\n this.reindex();\n this.emitChange(this.idToPath.get(entityId)!, previousPath);\n },\n onFileChanged:update => {\n const path = this.idToPath.get(update.doc);\n if (path) { this.emitChange(path); }\n },\n });\n }\n}\n","import {posix} from 'node:path';\nimport type {ProjectFileTreeDiffResponseSchema} from '../api/base';\nimport type {RemoteEntry} from './remoteProject';\nimport {\n createSyncState,\n type LocalReplicaSyncState,\n readTextBase,\n removeSyncCheckpoint,\n sha256,\n updateSyncCheckpoint,\n} from './checkpoint';\nimport {mergeText} from './threeWayMerge';\n\nexport interface ReplicaFileSystem {\n listFiles(): Promise<string[]>;\n read(path:string): Promise<Uint8Array | undefined>;\n write(path:string, content:Uint8Array): Promise<void>;\n remove(path:string): Promise<void>;\n watch(onChange:(path:string) => void): Promise<() => Promise<void>>;\n}\n\nexport interface RemoteReplica {\n listEntries(): RemoteEntry[];\n entry(path:string): RemoteEntry | undefined;\n read(path:string): Promise<Uint8Array>;\n write(path:string, content:Uint8Array): Promise<void>;\n remove(path:string): Promise<void>;\n getCurrentVersion(): Promise<number>;\n getFileTreeDiff(from:number, to:number): Promise<ProjectFileTreeDiffResponseSchema | undefined>;\n onChange(handler:(change:{path:string; previousPath?:string}) => void): void;\n onReconnect?(handler:() => void): void;\n}\n\nexport interface SyncStateStore {\n load(): Promise<LocalReplicaSyncState | undefined>;\n save(state:LocalReplicaSyncState): Promise<void>;\n}\n\nexport interface SyncEngineOptions {\n projectUri:string;\n local:ReplicaFileSystem;\n remote:RemoteReplica;\n stateStore:SyncStateStore;\n ignore(path:string):boolean;\n log(message:string):void;\n onConflict(path:string, reason:string):void;\n}\n\ntype ChangeSource = 'local' | 'remote';\n\nfunction normalizePath(path:string):string {\n return `/${posix.normalize(path).replace(/^\\/+/, '')}`;\n}\n\nfunction isRemoteFile(entry:RemoteEntry|undefined):boolean {\n return entry?.type==='doc' || entry?.type==='file';\n}\n\nexport class SyncEngine {\n private state?: LocalReplicaSyncState;\n private queue:Promise<void> = Promise.resolve();\n private conflicts = new Set<string>();\n private stopLocalWatch?: () => Promise<void>;\n private eventTimers = new Map<string, NodeJS.Timeout>();\n\n constructor(private readonly options:SyncEngineOptions) {}\n\n async start():Promise<void> {\n this.state = await this.options.stateStore.load();\n const currentVersion = await this.options.remote.getCurrentVersion();\n const localFiles = await this.options.local.listFiles();\n const remoteFiles = this.remoteFilePaths();\n\n if (!this.state) {\n this.state = createSyncState(this.options.projectUri, currentVersion);\n if (localFiles.length!==0 && remoteFiles.length!==0) {\n throw new Error('Synchronization paused: both the local and Overleaf projects contain files, but no common checkpoint exists.');\n }\n const source:ChangeSource = localFiles.length===0 ? 'remote' : 'local';\n for (const path of source==='remote' ? remoteFiles : localFiles) {\n await this.reconcilePath(path, source);\n }\n this.state.remoteVersion = currentVersion;\n await this.options.stateStore.save(this.state);\n } else {\n await this.startupReconcile(currentVersion, localFiles, remoteFiles);\n }\n\n this.stopLocalWatch = await this.options.local.watch(path => this.schedule(path, 'local'));\n this.options.remote.onChange(change => {\n if (change.previousPath) { this.schedule(change.previousPath, 'remote'); }\n this.schedule(change.path, 'remote');\n });\n this.options.remote.onReconnect?.(() => {\n this.queue = this.queue.then(() => this.reconcileAfterReconnect()).catch(error => {\n this.options.log(`Failed to reconcile after reconnecting: ${error instanceof Error ? error.message : String(error)}`);\n });\n });\n this.options.log(`Synchronization active at Overleaf version ${this.state.remoteVersion}.`);\n }\n\n async stop():Promise<void> {\n for (const timer of this.eventTimers.values()) { clearTimeout(timer); }\n this.eventTimers.clear();\n await this.stopLocalWatch?.();\n await this.queue;\n }\n\n getConflicts():string[] {\n return [...this.conflicts].sort();\n }\n\n async resolveConflict(path:string, winner:'local'|'remote'):Promise<void> {\n const normalized = normalizePath(path);\n if (!this.conflicts.has(normalized)) {\n throw new Error(`No unresolved conflict exists for ${normalized}.`);\n }\n await this.enqueue(async () => {\n const remoteEntry = this.options.remote.entry(normalized);\n if (winner==='local') {\n const localContent = await this.options.local.read(normalized);\n if (localContent) {\n await this.options.remote.write(normalized, localContent);\n const synchronized = await this.options.remote.read(normalized);\n if (sha256(synchronized)!==sha256(localContent)) {\n await this.options.local.write(normalized, synchronized);\n }\n updateSyncCheckpoint(this.state!, normalized, synchronized);\n } else {\n if (remoteEntry) { await this.options.remote.remove(normalized); }\n removeSyncCheckpoint(this.state!, normalized);\n }\n } else if (isRemoteFile(remoteEntry)) {\n const remoteContent = await this.options.remote.read(normalized);\n await this.options.local.write(normalized, remoteContent);\n updateSyncCheckpoint(this.state!, normalized, remoteContent);\n } else {\n await this.options.local.remove(normalized);\n removeSyncCheckpoint(this.state!, normalized);\n }\n await this.options.stateStore.save(this.state!);\n this.conflicts.delete(normalized);\n this.options.log(`Resolved ${normalized} using ${winner==='local' ? 'local' : 'Overleaf'} content.`);\n });\n }\n\n async retry(path:string):Promise<void> {\n const normalized = normalizePath(path);\n this.conflicts.delete(normalized);\n await this.enqueue(() => this.reconcilePath(normalized, 'local'));\n }\n\n private async startupReconcile(currentVersion:number, localFiles:string[], remoteFiles:string[]) {\n const state = this.state!;\n if (state.remoteVersion>currentVersion) {\n throw new Error('Synchronization paused: the local checkpoint is newer than the Overleaf project history.');\n }\n const localHashes = new Map<string,string>();\n for (const path of localFiles) {\n const content = await this.options.local.read(path);\n if (content) { localHashes.set(path, sha256(content)); }\n }\n const localChanged = new Set<string>();\n for (const path of new Set([...Object.keys(state.files), ...localFiles])) {\n if (state.files[path]!==localHashes.get(path)) { localChanged.add(path); }\n }\n\n let remoteDiff:ProjectFileTreeDiffResponseSchema|undefined = {diff:[]};\n if (state.remoteVersion<currentVersion) {\n remoteDiff = await this.options.remote.getFileTreeDiff(state.remoteVersion, currentVersion);\n if (!remoteDiff) {\n throw new Error('Synchronization paused: Overleaf history is unavailable, so remote changes cannot be distinguished safely.');\n }\n }\n const candidates = new Set<string>(localChanged);\n const knownFiles = new Set([...Object.keys(state.files), ...localFiles, ...remoteFiles]);\n for (const change of remoteDiff.diff) {\n const paths = [change.pathname, change.newPathname].filter((path):path is string => Boolean(path));\n for (const changedPath of paths.map(normalizePath)) {\n let matched = false;\n for (const filePath of knownFiles) {\n if (filePath===changedPath || filePath.startsWith(`${changedPath}/`)) {\n candidates.add(filePath);\n matched = true;\n }\n }\n if (!matched) { candidates.add(changedPath); }\n }\n }\n\n let failed = false;\n for (const path of [...candidates].sort()) {\n try {\n await this.reconcilePath(path, localChanged.has(path) ? 'local' : 'remote');\n } catch (error) {\n failed = true;\n this.options.log(`Failed to synchronize ${path}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n if (failed) {\n throw new Error('Synchronization paused for failed paths; successful paths were checkpointed.');\n }\n state.remoteVersion = currentVersion;\n await this.options.stateStore.save(state);\n if (this.conflicts.size!==0) {\n this.options.log(`Synchronization remains active; ${this.conflicts.size} conflicting path(s) are paused.`);\n }\n }\n\n private async reconcileAfterReconnect() {\n const currentVersion = await this.options.remote.getCurrentVersion();\n await this.startupReconcile(\n currentVersion,\n await this.options.local.listFiles(),\n this.remoteFilePaths(),\n );\n this.options.log(`Realtime connection restored at Overleaf version ${currentVersion}.`);\n }\n\n private schedule(path:string, source:ChangeSource) {\n const normalized = normalizePath(path);\n if (this.shouldIgnore(normalized) || this.conflicts.has(normalized)) { return; }\n const previous = this.eventTimers.get(normalized);\n if (previous) { clearTimeout(previous); }\n this.eventTimers.set(normalized, setTimeout(() => {\n this.eventTimers.delete(normalized);\n this.queue = this.queue.then(() => this.reconcilePath(normalized, source)).catch(error => {\n this.options.log(`Failed to synchronize ${normalized}: ${error instanceof Error ? error.message : String(error)}`);\n });\n }, 250));\n }\n\n private enqueue<T>(operation:() => Promise<T>):Promise<T> {\n const result = this.queue.then(operation);\n this.queue = result.then(() => undefined, () => undefined);\n return result;\n }\n\n private async reconcilePath(path:string, source:ChangeSource):Promise<void> {\n const normalized = normalizePath(path);\n if (this.shouldIgnore(normalized) || this.conflicts.has(normalized)) { return; }\n const remoteEntry = this.options.remote.entry(normalized);\n if (remoteEntry?.type==='folder') { return; }\n const localContent = await this.options.local.read(normalized);\n const remoteContent = isRemoteFile(remoteEntry) ? await this.options.remote.read(normalized) : undefined;\n const baseHash = this.state!.files[normalized];\n const localHash = localContent && sha256(localContent);\n const remoteHash = remoteContent && sha256(remoteContent);\n\n if (localHash===remoteHash) {\n if (localContent) { updateSyncCheckpoint(this.state!, normalized, localContent); }\n else { removeSyncCheckpoint(this.state!, normalized); }\n await this.options.stateStore.save(this.state!);\n return;\n }\n\n const localChanged = localHash!==baseHash;\n const remoteChanged = remoteHash!==baseHash;\n if (localChanged && remoteChanged) {\n const base = readTextBase(this.state, normalized);\n if (base && localContent && remoteContent) {\n const merged = mergeText(base, localContent, remoteContent);\n if (merged.status==='merged' && merged.content) {\n await this.options.local.write(normalized, merged.content);\n await this.options.remote.write(normalized, merged.content);\n updateSyncCheckpoint(this.state!, normalized, merged.content);\n await this.options.stateStore.save(this.state!);\n this.logChange('merge', 'update', normalized);\n return;\n }\n }\n this.conflicts.add(normalized);\n const reason = 'Both local and Overleaf content changed since the last synchronized checkpoint.';\n this.options.onConflict(normalized, reason);\n return;\n }\n\n if (localChanged || (!remoteChanged && source==='local')) {\n if (!localContent) {\n if (remoteEntry) {\n await this.options.remote.remove(normalized);\n }\n removeSyncCheckpoint(this.state!, normalized);\n } else {\n await this.options.remote.write(normalized, localContent);\n const synchronized = await this.options.remote.read(normalized);\n if (sha256(synchronized)!==sha256(localContent)) {\n await this.options.local.write(normalized, synchronized);\n }\n updateSyncCheckpoint(this.state!, normalized, synchronized);\n }\n await this.options.stateStore.save(this.state!);\n if (!localContent && remoteEntry) {\n this.logChange('push', 'delete', normalized);\n } else if (localContent) {\n this.logChange('push', remoteEntry ? 'update' : 'add', normalized);\n }\n return;\n }\n\n if (!remoteContent) {\n if (localContent) {\n await this.options.local.remove(normalized);\n }\n removeSyncCheckpoint(this.state!, normalized);\n } else {\n await this.options.local.write(normalized, remoteContent);\n updateSyncCheckpoint(this.state!, normalized, remoteContent);\n }\n await this.options.stateStore.save(this.state!);\n if (!remoteContent && localContent) {\n this.logChange('pull', 'delete', normalized);\n } else if (remoteContent) {\n this.logChange('pull', localContent ? 'update' : 'add', normalized);\n }\n }\n\n private logChange(direction:'push'|'pull'|'merge', operation:'add'|'update'|'delete', path:string):void {\n this.options.log(`[${direction}] ${operation} ${JSON.stringify(path)}`);\n }\n\n private remoteFilePaths():string[] {\n return this.options.remote.listEntries()\n .filter(entry => isRemoteFile(entry) && !this.shouldIgnore(entry.path))\n .map(entry => entry.path);\n }\n\n private shouldIgnore(path:string):boolean {\n return this.options.ignore(path) || path.split('/').some(part => part.startsWith('.'));\n }\n}\n","import {createHash} from 'node:crypto';\nimport {encodeTextBase} from './threeWayMerge';\n\nexport const SYNC_STATE_SCHEMA_VERSION = 2;\n\nexport interface LocalReplicaSyncState {\n schemaVersion: number;\n projectUri: string;\n remoteVersion: number;\n files: {[path:string]: string};\n textBases: {[path:string]: string};\n}\n\nexport function sha256(content: Uint8Array): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\nexport function parseSyncState(serialized: string, projectUri: string): LocalReplicaSyncState | undefined {\n try {\n const state = JSON.parse(serialized) as LocalReplicaSyncState;\n if ((state.schemaVersion!==1 && state.schemaVersion!==SYNC_STATE_SCHEMA_VERSION) ||\n state.projectUri!==projectUri ||\n !Number.isInteger(state.remoteVersion) ||\n typeof state.files!=='object' || state.files===null) {\n return undefined;\n }\n return {\n ...state,\n schemaVersion:SYNC_STATE_SCHEMA_VERSION,\n textBases:typeof state.textBases==='object' && state.textBases!==null ? state.textBases : {},\n };\n } catch {\n return undefined;\n }\n}\n\nexport function createSyncState(projectUri: string, remoteVersion: number): LocalReplicaSyncState {\n return {\n schemaVersion:SYNC_STATE_SCHEMA_VERSION,\n projectUri,\n remoteVersion,\n files:{},\n textBases:{},\n };\n}\n\nexport function updateSyncCheckpoint(state: LocalReplicaSyncState, path: string, content: Uint8Array) {\n state.files[path] = sha256(content);\n const textBase = encodeTextBase(content);\n if (textBase===undefined) {\n delete state.textBases[path];\n } else {\n state.textBases[path] = textBase;\n }\n}\n\nexport function removeSyncCheckpoint(state: LocalReplicaSyncState, path: string) {\n for (const checkpointPath of Object.keys(state.files)) {\n if (checkpointPath===path || checkpointPath.startsWith(`${path}/`)) {\n delete state.files[checkpointPath];\n delete state.textBases[checkpointPath];\n }\n }\n}\n\nexport function readTextBase(state: LocalReplicaSyncState | undefined, path: string): Uint8Array | undefined {\n const textBase = state?.textBases[path];\n return textBase===undefined ? undefined : new TextEncoder().encode(textBase);\n}\n","import {diff3Merge} from 'node-diff3';\n\nconst textDecoder = new TextDecoder('utf-8', {fatal:true});\nconst textEncoder = new TextEncoder();\n\nexport interface TextMergeResult {\n status: 'merged'|'conflict'|'binary';\n content?: Uint8Array;\n}\n\nfunction decodeText(content: Uint8Array): string | undefined {\n if (content.includes(0)) { return undefined; }\n try {\n return textDecoder.decode(content);\n } catch {\n return undefined;\n }\n}\n\nfunction splitLines(content: string): string[] {\n return content.match(/[^\\n]*\\n|[^\\n]+$/g) ?? [];\n}\n\nexport function encodeTextBase(content: Uint8Array): string | undefined {\n return decodeText(content);\n}\n\nexport function mergeText(\n baseContent: Uint8Array,\n localContent: Uint8Array,\n remoteContent: Uint8Array,\n): TextMergeResult {\n const base = decodeText(baseContent);\n const local = decodeText(localContent);\n const remote = decodeText(remoteContent);\n if (base===undefined || local===undefined || remote===undefined) {\n return {status:'binary'};\n }\n\n const regions = diff3Merge(\n splitLines(local),\n splitLines(base),\n splitLines(remote),\n {excludeFalseConflicts:true},\n );\n if (regions.some(region => region.conflict!==undefined)) {\n return {status:'conflict'};\n }\n return {\n status:'merged',\n content:textEncoder.encode(regions.flatMap(region => region.ok ?? []).join('')),\n };\n}\n","import {mkdir, readFile, writeFile} from 'node:fs/promises';\nimport {dirname, resolve} from 'node:path';\nimport {parseSyncState, type LocalReplicaSyncState} from '../sync/checkpoint';\nimport type {SyncStateStore} from '../sync/syncEngine';\n\nexport class FileSyncStateStore implements SyncStateStore {\n private readonly path:string;\n private serialized?:string;\n\n constructor(directory:string, private readonly projectUri:string) {\n this.path = resolve(directory, '.overleaf', 'sync-state.json');\n }\n\n async load():Promise<LocalReplicaSyncState|undefined> {\n try {\n const content = await readFile(this.path, 'utf8');\n const state = parseSyncState(content, this.projectUri);\n if (state) { this.serialized = `${JSON.stringify(state, null, 2)}\\n`; }\n return state;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code==='ENOENT') { return undefined; }\n throw error;\n }\n }\n\n async save(state:LocalReplicaSyncState):Promise<void> {\n const serialized = `${JSON.stringify(state, null, 2)}\\n`;\n if (serialized===this.serialized) { return; }\n await mkdir(dirname(this.path), {recursive:true});\n await writeFile(this.path, serialized, 'utf8');\n this.serialized = serialized;\n }\n}\n","const types = {\n 'application/prs.cww': ['cww'],\n 'application/prs.xsf+xml': ['xsf'],\n 'application/vnd.1000minds.decision-model+xml': ['1km'],\n 'application/vnd.3gpp.pic-bw-large': ['plb'],\n 'application/vnd.3gpp.pic-bw-small': ['psb'],\n 'application/vnd.3gpp.pic-bw-var': ['pvb'],\n 'application/vnd.3gpp2.tcap': ['tcap'],\n 'application/vnd.3m.post-it-notes': ['pwn'],\n 'application/vnd.accpac.simply.aso': ['aso'],\n 'application/vnd.accpac.simply.imp': ['imp'],\n 'application/vnd.acucobol': ['acu'],\n 'application/vnd.acucorp': ['atc', 'acutc'],\n 'application/vnd.adobe.air-application-installer-package+zip': ['air'],\n 'application/vnd.adobe.formscentral.fcdt': ['fcdt'],\n 'application/vnd.adobe.fxp': ['fxp', 'fxpl'],\n 'application/vnd.adobe.xdp+xml': ['xdp'],\n 'application/vnd.adobe.xfdf': ['*xfdf'],\n 'application/vnd.age': ['age'],\n 'application/vnd.ahead.space': ['ahead'],\n 'application/vnd.airzip.filesecure.azf': ['azf'],\n 'application/vnd.airzip.filesecure.azs': ['azs'],\n 'application/vnd.amazon.ebook': ['azw'],\n 'application/vnd.americandynamics.acc': ['acc'],\n 'application/vnd.amiga.ami': ['ami'],\n 'application/vnd.android.package-archive': ['apk'],\n 'application/vnd.anser-web-certificate-issue-initiation': ['cii'],\n 'application/vnd.anser-web-funds-transfer-initiation': ['fti'],\n 'application/vnd.antix.game-component': ['atx'],\n 'application/vnd.apple.installer+xml': ['mpkg'],\n 'application/vnd.apple.keynote': ['key'],\n 'application/vnd.apple.mpegurl': ['m3u8'],\n 'application/vnd.apple.numbers': ['numbers'],\n 'application/vnd.apple.pages': ['pages'],\n 'application/vnd.apple.pkpass': ['pkpass'],\n 'application/vnd.aristanetworks.swi': ['swi'],\n 'application/vnd.astraea-software.iota': ['iota'],\n 'application/vnd.audiograph': ['aep'],\n 'application/vnd.autodesk.fbx': ['fbx'],\n 'application/vnd.balsamiq.bmml+xml': ['bmml'],\n 'application/vnd.blueice.multipass': ['mpm'],\n 'application/vnd.bmi': ['bmi'],\n 'application/vnd.businessobjects': ['rep'],\n 'application/vnd.chemdraw+xml': ['cdxml'],\n 'application/vnd.chipnuts.karaoke-mmd': ['mmd'],\n 'application/vnd.cinderella': ['cdy'],\n 'application/vnd.citationstyles.style+xml': ['csl'],\n 'application/vnd.claymore': ['cla'],\n 'application/vnd.cloanto.rp9': ['rp9'],\n 'application/vnd.clonk.c4group': ['c4g', 'c4d', 'c4f', 'c4p', 'c4u'],\n 'application/vnd.cluetrust.cartomobile-config': ['c11amc'],\n 'application/vnd.cluetrust.cartomobile-config-pkg': ['c11amz'],\n 'application/vnd.commonspace': ['csp'],\n 'application/vnd.contact.cmsg': ['cdbcmsg'],\n 'application/vnd.cosmocaller': ['cmc'],\n 'application/vnd.crick.clicker': ['clkx'],\n 'application/vnd.crick.clicker.keyboard': ['clkk'],\n 'application/vnd.crick.clicker.palette': ['clkp'],\n 'application/vnd.crick.clicker.template': ['clkt'],\n 'application/vnd.crick.clicker.wordbank': ['clkw'],\n 'application/vnd.criticaltools.wbs+xml': ['wbs'],\n 'application/vnd.ctc-posml': ['pml'],\n 'application/vnd.cups-ppd': ['ppd'],\n 'application/vnd.curl.car': ['car'],\n 'application/vnd.curl.pcurl': ['pcurl'],\n 'application/vnd.dart': ['dart'],\n 'application/vnd.data-vision.rdz': ['rdz'],\n 'application/vnd.dbf': ['dbf'],\n 'application/vnd.dcmp+xml': ['dcmp'],\n 'application/vnd.dece.data': ['uvf', 'uvvf', 'uvd', 'uvvd'],\n 'application/vnd.dece.ttml+xml': ['uvt', 'uvvt'],\n 'application/vnd.dece.unspecified': ['uvx', 'uvvx'],\n 'application/vnd.dece.zip': ['uvz', 'uvvz'],\n 'application/vnd.denovo.fcselayout-link': ['fe_launch'],\n 'application/vnd.dna': ['dna'],\n 'application/vnd.dolby.mlp': ['mlp'],\n 'application/vnd.dpgraph': ['dpg'],\n 'application/vnd.dreamfactory': ['dfac'],\n 'application/vnd.ds-keypoint': ['kpxx'],\n 'application/vnd.dvb.ait': ['ait'],\n 'application/vnd.dvb.service': ['svc'],\n 'application/vnd.dynageo': ['geo'],\n 'application/vnd.ecowin.chart': ['mag'],\n 'application/vnd.enliven': ['nml'],\n 'application/vnd.epson.esf': ['esf'],\n 'application/vnd.epson.msf': ['msf'],\n 'application/vnd.epson.quickanime': ['qam'],\n 'application/vnd.epson.salt': ['slt'],\n 'application/vnd.epson.ssf': ['ssf'],\n 'application/vnd.eszigno3+xml': ['es3', 'et3'],\n 'application/vnd.ezpix-album': ['ez2'],\n 'application/vnd.ezpix-package': ['ez3'],\n 'application/vnd.fdf': ['*fdf'],\n 'application/vnd.fdsn.mseed': ['mseed'],\n 'application/vnd.fdsn.seed': ['seed', 'dataless'],\n 'application/vnd.flographit': ['gph'],\n 'application/vnd.fluxtime.clip': ['ftc'],\n 'application/vnd.framemaker': ['fm', 'frame', 'maker', 'book'],\n 'application/vnd.frogans.fnc': ['fnc'],\n 'application/vnd.frogans.ltf': ['ltf'],\n 'application/vnd.fsc.weblaunch': ['fsc'],\n 'application/vnd.fujitsu.oasys': ['oas'],\n 'application/vnd.fujitsu.oasys2': ['oa2'],\n 'application/vnd.fujitsu.oasys3': ['oa3'],\n 'application/vnd.fujitsu.oasysgp': ['fg5'],\n 'application/vnd.fujitsu.oasysprs': ['bh2'],\n 'application/vnd.fujixerox.ddd': ['ddd'],\n 'application/vnd.fujixerox.docuworks': ['xdw'],\n 'application/vnd.fujixerox.docuworks.binder': ['xbd'],\n 'application/vnd.fuzzysheet': ['fzs'],\n 'application/vnd.genomatix.tuxedo': ['txd'],\n 'application/vnd.geogebra.file': ['ggb'],\n 'application/vnd.geogebra.slides': ['ggs'],\n 'application/vnd.geogebra.tool': ['ggt'],\n 'application/vnd.geometry-explorer': ['gex', 'gre'],\n 'application/vnd.geonext': ['gxt'],\n 'application/vnd.geoplan': ['g2w'],\n 'application/vnd.geospace': ['g3w'],\n 'application/vnd.gmx': ['gmx'],\n 'application/vnd.google-apps.document': ['gdoc'],\n 'application/vnd.google-apps.drawing': ['gdraw'],\n 'application/vnd.google-apps.form': ['gform'],\n 'application/vnd.google-apps.jam': ['gjam'],\n 'application/vnd.google-apps.map': ['gmap'],\n 'application/vnd.google-apps.presentation': ['gslides'],\n 'application/vnd.google-apps.script': ['gscript'],\n 'application/vnd.google-apps.site': ['gsite'],\n 'application/vnd.google-apps.spreadsheet': ['gsheet'],\n 'application/vnd.google-earth.kml+xml': ['kml'],\n 'application/vnd.google-earth.kmz': ['kmz'],\n 'application/vnd.gov.sk.xmldatacontainer+xml': ['xdcf'],\n 'application/vnd.grafeq': ['gqf', 'gqs'],\n 'application/vnd.groove-account': ['gac'],\n 'application/vnd.groove-help': ['ghf'],\n 'application/vnd.groove-identity-message': ['gim'],\n 'application/vnd.groove-injector': ['grv'],\n 'application/vnd.groove-tool-message': ['gtm'],\n 'application/vnd.groove-tool-template': ['tpl'],\n 'application/vnd.groove-vcard': ['vcg'],\n 'application/vnd.hal+xml': ['hal'],\n 'application/vnd.handheld-entertainment+xml': ['zmm'],\n 'application/vnd.hbci': ['hbci'],\n 'application/vnd.hhe.lesson-player': ['les'],\n 'application/vnd.hp-hpgl': ['hpgl'],\n 'application/vnd.hp-hpid': ['hpid'],\n 'application/vnd.hp-hps': ['hps'],\n 'application/vnd.hp-jlyt': ['jlt'],\n 'application/vnd.hp-pcl': ['pcl'],\n 'application/vnd.hp-pclxl': ['pclxl'],\n 'application/vnd.hydrostatix.sof-data': ['sfd-hdstx'],\n 'application/vnd.ibm.minipay': ['mpy'],\n 'application/vnd.ibm.modcap': ['afp', 'listafp', 'list3820'],\n 'application/vnd.ibm.rights-management': ['irm'],\n 'application/vnd.ibm.secure-container': ['sc'],\n 'application/vnd.iccprofile': ['icc', 'icm'],\n 'application/vnd.igloader': ['igl'],\n 'application/vnd.immervision-ivp': ['ivp'],\n 'application/vnd.immervision-ivu': ['ivu'],\n 'application/vnd.insors.igm': ['igm'],\n 'application/vnd.intercon.formnet': ['xpw', 'xpx'],\n 'application/vnd.intergeo': ['i2g'],\n 'application/vnd.intu.qbo': ['qbo'],\n 'application/vnd.intu.qfx': ['qfx'],\n 'application/vnd.ipunplugged.rcprofile': ['rcprofile'],\n 'application/vnd.irepository.package+xml': ['irp'],\n 'application/vnd.is-xpr': ['xpr'],\n 'application/vnd.isac.fcs': ['fcs'],\n 'application/vnd.jam': ['jam'],\n 'application/vnd.jcp.javame.midlet-rms': ['rms'],\n 'application/vnd.jisp': ['jisp'],\n 'application/vnd.joost.joda-archive': ['joda'],\n 'application/vnd.kahootz': ['ktz', 'ktr'],\n 'application/vnd.kde.karbon': ['karbon'],\n 'application/vnd.kde.kchart': ['chrt'],\n 'application/vnd.kde.kformula': ['kfo'],\n 'application/vnd.kde.kivio': ['flw'],\n 'application/vnd.kde.kontour': ['kon'],\n 'application/vnd.kde.kpresenter': ['kpr', 'kpt'],\n 'application/vnd.kde.kspread': ['ksp'],\n 'application/vnd.kde.kword': ['kwd', 'kwt'],\n 'application/vnd.kenameaapp': ['htke'],\n 'application/vnd.kidspiration': ['kia'],\n 'application/vnd.kinar': ['kne', 'knp'],\n 'application/vnd.koan': ['skp', 'skd', 'skt', 'skm'],\n 'application/vnd.kodak-descriptor': ['sse'],\n 'application/vnd.las.las+xml': ['lasxml'],\n 'application/vnd.llamagraphics.life-balance.desktop': ['lbd'],\n 'application/vnd.llamagraphics.life-balance.exchange+xml': ['lbe'],\n 'application/vnd.lotus-1-2-3': ['123'],\n 'application/vnd.lotus-approach': ['apr'],\n 'application/vnd.lotus-freelance': ['pre'],\n 'application/vnd.lotus-notes': ['nsf'],\n 'application/vnd.lotus-organizer': ['org'],\n 'application/vnd.lotus-screencam': ['scm'],\n 'application/vnd.lotus-wordpro': ['lwp'],\n 'application/vnd.macports.portpkg': ['portpkg'],\n 'application/vnd.mapbox-vector-tile': ['mvt'],\n 'application/vnd.mcd': ['mcd'],\n 'application/vnd.medcalcdata': ['mc1'],\n 'application/vnd.mediastation.cdkey': ['cdkey'],\n 'application/vnd.mfer': ['mwf'],\n 'application/vnd.mfmp': ['mfm'],\n 'application/vnd.micrografx.flo': ['flo'],\n 'application/vnd.micrografx.igx': ['igx'],\n 'application/vnd.mif': ['mif'],\n 'application/vnd.mobius.daf': ['daf'],\n 'application/vnd.mobius.dis': ['dis'],\n 'application/vnd.mobius.mbk': ['mbk'],\n 'application/vnd.mobius.mqy': ['mqy'],\n 'application/vnd.mobius.msl': ['msl'],\n 'application/vnd.mobius.plc': ['plc'],\n 'application/vnd.mobius.txf': ['txf'],\n 'application/vnd.mophun.application': ['mpn'],\n 'application/vnd.mophun.certificate': ['mpc'],\n 'application/vnd.mozilla.xul+xml': ['xul'],\n 'application/vnd.ms-artgalry': ['cil'],\n 'application/vnd.ms-cab-compressed': ['cab'],\n 'application/vnd.ms-excel': ['xls', 'xlm', 'xla', 'xlc', 'xlt', 'xlw'],\n 'application/vnd.ms-excel.addin.macroenabled.12': ['xlam'],\n 'application/vnd.ms-excel.sheet.binary.macroenabled.12': ['xlsb'],\n 'application/vnd.ms-excel.sheet.macroenabled.12': ['xlsm'],\n 'application/vnd.ms-excel.template.macroenabled.12': ['xltm'],\n 'application/vnd.ms-fontobject': ['eot'],\n 'application/vnd.ms-htmlhelp': ['chm'],\n 'application/vnd.ms-ims': ['ims'],\n 'application/vnd.ms-lrm': ['lrm'],\n 'application/vnd.ms-officetheme': ['thmx'],\n 'application/vnd.ms-outlook': ['msg'],\n 'application/vnd.ms-pki.seccat': ['cat'],\n 'application/vnd.ms-pki.stl': ['*stl'],\n 'application/vnd.ms-powerpoint': ['ppt', 'pps', 'pot'],\n 'application/vnd.ms-powerpoint.addin.macroenabled.12': ['ppam'],\n 'application/vnd.ms-powerpoint.presentation.macroenabled.12': ['pptm'],\n 'application/vnd.ms-powerpoint.slide.macroenabled.12': ['sldm'],\n 'application/vnd.ms-powerpoint.slideshow.macroenabled.12': ['ppsm'],\n 'application/vnd.ms-powerpoint.template.macroenabled.12': ['potm'],\n 'application/vnd.ms-project': ['*mpp', 'mpt'],\n 'application/vnd.ms-visio.viewer': ['vdx'],\n 'application/vnd.ms-word.document.macroenabled.12': ['docm'],\n 'application/vnd.ms-word.template.macroenabled.12': ['dotm'],\n 'application/vnd.ms-works': ['wps', 'wks', 'wcm', 'wdb'],\n 'application/vnd.ms-wpl': ['wpl'],\n 'application/vnd.ms-xpsdocument': ['xps'],\n 'application/vnd.mseq': ['mseq'],\n 'application/vnd.musician': ['mus'],\n 'application/vnd.muvee.style': ['msty'],\n 'application/vnd.mynfc': ['taglet'],\n 'application/vnd.nato.bindingdataobject+xml': ['bdo'],\n 'application/vnd.neurolanguage.nlu': ['nlu'],\n 'application/vnd.nitf': ['ntf', 'nitf'],\n 'application/vnd.noblenet-directory': ['nnd'],\n 'application/vnd.noblenet-sealer': ['nns'],\n 'application/vnd.noblenet-web': ['nnw'],\n 'application/vnd.nokia.n-gage.ac+xml': ['*ac'],\n 'application/vnd.nokia.n-gage.data': ['ngdat'],\n 'application/vnd.nokia.n-gage.symbian.install': ['n-gage'],\n 'application/vnd.nokia.radio-preset': ['rpst'],\n 'application/vnd.nokia.radio-presets': ['rpss'],\n 'application/vnd.novadigm.edm': ['edm'],\n 'application/vnd.novadigm.edx': ['edx'],\n 'application/vnd.novadigm.ext': ['ext'],\n 'application/vnd.oasis.opendocument.chart': ['odc'],\n 'application/vnd.oasis.opendocument.chart-template': ['otc'],\n 'application/vnd.oasis.opendocument.database': ['odb'],\n 'application/vnd.oasis.opendocument.formula': ['odf'],\n 'application/vnd.oasis.opendocument.formula-template': ['odft'],\n 'application/vnd.oasis.opendocument.graphics': ['odg'],\n 'application/vnd.oasis.opendocument.graphics-template': ['otg'],\n 'application/vnd.oasis.opendocument.image': ['odi'],\n 'application/vnd.oasis.opendocument.image-template': ['oti'],\n 'application/vnd.oasis.opendocument.presentation': ['odp'],\n 'application/vnd.oasis.opendocument.presentation-template': ['otp'],\n 'application/vnd.oasis.opendocument.spreadsheet': ['ods'],\n 'application/vnd.oasis.opendocument.spreadsheet-template': ['ots'],\n 'application/vnd.oasis.opendocument.text': ['odt'],\n 'application/vnd.oasis.opendocument.text-master': ['odm'],\n 'application/vnd.oasis.opendocument.text-template': ['ott'],\n 'application/vnd.oasis.opendocument.text-web': ['oth'],\n 'application/vnd.olpc-sugar': ['xo'],\n 'application/vnd.oma.dd2+xml': ['dd2'],\n 'application/vnd.openblox.game+xml': ['obgx'],\n 'application/vnd.openofficeorg.extension': ['oxt'],\n 'application/vnd.openstreetmap.data+xml': ['osm'],\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation': [\n 'pptx',\n ],\n 'application/vnd.openxmlformats-officedocument.presentationml.slide': [\n 'sldx',\n ],\n 'application/vnd.openxmlformats-officedocument.presentationml.slideshow': [\n 'ppsx',\n ],\n 'application/vnd.openxmlformats-officedocument.presentationml.template': [\n 'potx',\n ],\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['xlsx'],\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.template': [\n 'xltx',\n ],\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': [\n 'docx',\n ],\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.template': [\n 'dotx',\n ],\n 'application/vnd.osgeo.mapguide.package': ['mgp'],\n 'application/vnd.osgi.dp': ['dp'],\n 'application/vnd.osgi.subsystem': ['esa'],\n 'application/vnd.palm': ['pdb', 'pqa', 'oprc'],\n 'application/vnd.pawaafile': ['paw'],\n 'application/vnd.pg.format': ['str'],\n 'application/vnd.pg.osasli': ['ei6'],\n 'application/vnd.picsel': ['efif'],\n 'application/vnd.pmi.widget': ['wg'],\n 'application/vnd.pocketlearn': ['plf'],\n 'application/vnd.powerbuilder6': ['pbd'],\n 'application/vnd.previewsystems.box': ['box'],\n 'application/vnd.procrate.brushset': ['brushset'],\n 'application/vnd.procreate.brush': ['brush'],\n 'application/vnd.procreate.dream': ['drm'],\n 'application/vnd.proteus.magazine': ['mgz'],\n 'application/vnd.publishare-delta-tree': ['qps'],\n 'application/vnd.pvi.ptid1': ['ptid'],\n 'application/vnd.pwg-xhtml-print+xml': ['xhtm'],\n 'application/vnd.quark.quarkxpress': [\n 'qxd',\n 'qxt',\n 'qwd',\n 'qwt',\n 'qxl',\n 'qxb',\n ],\n 'application/vnd.rar': ['rar'],\n 'application/vnd.realvnc.bed': ['bed'],\n 'application/vnd.recordare.musicxml': ['mxl'],\n 'application/vnd.recordare.musicxml+xml': ['musicxml'],\n 'application/vnd.rig.cryptonote': ['cryptonote'],\n 'application/vnd.rim.cod': ['cod'],\n 'application/vnd.rn-realmedia': ['rm'],\n 'application/vnd.rn-realmedia-vbr': ['rmvb'],\n 'application/vnd.route66.link66+xml': ['link66'],\n 'application/vnd.sailingtracker.track': ['st'],\n 'application/vnd.seemail': ['see'],\n 'application/vnd.sema': ['sema'],\n 'application/vnd.semd': ['semd'],\n 'application/vnd.semf': ['semf'],\n 'application/vnd.shana.informed.formdata': ['ifm'],\n 'application/vnd.shana.informed.formtemplate': ['itp'],\n 'application/vnd.shana.informed.interchange': ['iif'],\n 'application/vnd.shana.informed.package': ['ipk'],\n 'application/vnd.simtech-mindmapper': ['twd', 'twds'],\n 'application/vnd.smaf': ['mmf'],\n 'application/vnd.smart.teacher': ['teacher'],\n 'application/vnd.software602.filler.form+xml': ['fo'],\n 'application/vnd.solent.sdkm+xml': ['sdkm', 'sdkd'],\n 'application/vnd.spotfire.dxp': ['dxp'],\n 'application/vnd.spotfire.sfs': ['sfs'],\n 'application/vnd.stardivision.calc': ['sdc'],\n 'application/vnd.stardivision.draw': ['sda'],\n 'application/vnd.stardivision.impress': ['sdd'],\n 'application/vnd.stardivision.math': ['smf'],\n 'application/vnd.stardivision.writer': ['sdw', 'vor'],\n 'application/vnd.stardivision.writer-global': ['sgl'],\n 'application/vnd.stepmania.package': ['smzip'],\n 'application/vnd.stepmania.stepchart': ['sm'],\n 'application/vnd.sun.wadl+xml': ['wadl'],\n 'application/vnd.sun.xml.calc': ['sxc'],\n 'application/vnd.sun.xml.calc.template': ['stc'],\n 'application/vnd.sun.xml.draw': ['sxd'],\n 'application/vnd.sun.xml.draw.template': ['std'],\n 'application/vnd.sun.xml.impress': ['sxi'],\n 'application/vnd.sun.xml.impress.template': ['sti'],\n 'application/vnd.sun.xml.math': ['sxm'],\n 'application/vnd.sun.xml.writer': ['sxw'],\n 'application/vnd.sun.xml.writer.global': ['sxg'],\n 'application/vnd.sun.xml.writer.template': ['stw'],\n 'application/vnd.sus-calendar': ['sus', 'susp'],\n 'application/vnd.svd': ['svd'],\n 'application/vnd.symbian.install': ['sis', 'sisx'],\n 'application/vnd.syncml+xml': ['xsm'],\n 'application/vnd.syncml.dm+wbxml': ['bdm'],\n 'application/vnd.syncml.dm+xml': ['xdm'],\n 'application/vnd.syncml.dmddf+xml': ['ddf'],\n 'application/vnd.tao.intent-module-archive': ['tao'],\n 'application/vnd.tcpdump.pcap': ['pcap', 'cap', 'dmp'],\n 'application/vnd.tmobile-livetv': ['tmo'],\n 'application/vnd.trid.tpt': ['tpt'],\n 'application/vnd.triscape.mxs': ['mxs'],\n 'application/vnd.trueapp': ['tra'],\n 'application/vnd.ufdl': ['ufd', 'ufdl'],\n 'application/vnd.uiq.theme': ['utz'],\n 'application/vnd.umajin': ['umj'],\n 'application/vnd.unity': ['unityweb'],\n 'application/vnd.uoml+xml': ['uoml', 'uo'],\n 'application/vnd.vcx': ['vcx'],\n 'application/vnd.visio': ['vsd', 'vst', 'vss', 'vsw', 'vsdx', 'vtx'],\n 'application/vnd.visionary': ['vis'],\n 'application/vnd.vsf': ['vsf'],\n 'application/vnd.wap.wbxml': ['wbxml'],\n 'application/vnd.wap.wmlc': ['wmlc'],\n 'application/vnd.wap.wmlscriptc': ['wmlsc'],\n 'application/vnd.webturbo': ['wtb'],\n 'application/vnd.wolfram.player': ['nbp'],\n 'application/vnd.wordperfect': ['wpd'],\n 'application/vnd.wqd': ['wqd'],\n 'application/vnd.wt.stf': ['stf'],\n 'application/vnd.xara': ['xar'],\n 'application/vnd.xfdl': ['xfdl'],\n 'application/vnd.yamaha.hv-dic': ['hvd'],\n 'application/vnd.yamaha.hv-script': ['hvs'],\n 'application/vnd.yamaha.hv-voice': ['hvp'],\n 'application/vnd.yamaha.openscoreformat': ['osf'],\n 'application/vnd.yamaha.openscoreformat.osfpvg+xml': ['osfpvg'],\n 'application/vnd.yamaha.smaf-audio': ['saf'],\n 'application/vnd.yamaha.smaf-phrase': ['spf'],\n 'application/vnd.yellowriver-custom-menu': ['cmp'],\n 'application/vnd.zul': ['zir', 'zirz'],\n 'application/vnd.zzazz.deck+xml': ['zaz'],\n 'application/x-7z-compressed': ['7z'],\n 'application/x-abiword': ['abw'],\n 'application/x-ace-compressed': ['ace'],\n 'application/x-apple-diskimage': ['*dmg'],\n 'application/x-arj': ['arj'],\n 'application/x-authorware-bin': ['aab', 'x32', 'u32', 'vox'],\n 'application/x-authorware-map': ['aam'],\n 'application/x-authorware-seg': ['aas'],\n 'application/x-bcpio': ['bcpio'],\n 'application/x-bdoc': ['*bdoc'],\n 'application/x-bittorrent': ['torrent'],\n 'application/x-blender': ['blend'],\n 'application/x-blorb': ['blb', 'blorb'],\n 'application/x-bzip': ['bz'],\n 'application/x-bzip2': ['bz2', 'boz'],\n 'application/x-cbr': ['cbr', 'cba', 'cbt', 'cbz', 'cb7'],\n 'application/x-cdlink': ['vcd'],\n 'application/x-cfs-compressed': ['cfs'],\n 'application/x-chat': ['chat'],\n 'application/x-chess-pgn': ['pgn'],\n 'application/x-chrome-extension': ['crx'],\n 'application/x-cocoa': ['cco'],\n 'application/x-compressed': ['*rar'],\n 'application/x-conference': ['nsc'],\n 'application/x-cpio': ['cpio'],\n 'application/x-csh': ['csh'],\n 'application/x-debian-package': ['*deb', 'udeb'],\n 'application/x-dgc-compressed': ['dgc'],\n 'application/x-director': [\n 'dir',\n 'dcr',\n 'dxr',\n 'cst',\n 'cct',\n 'cxt',\n 'w3d',\n 'fgd',\n 'swa',\n ],\n 'application/x-doom': ['wad'],\n 'application/x-dtbncx+xml': ['ncx'],\n 'application/x-dtbook+xml': ['dtb'],\n 'application/x-dtbresource+xml': ['res'],\n 'application/x-dvi': ['dvi'],\n 'application/x-envoy': ['evy'],\n 'application/x-eva': ['eva'],\n 'application/x-font-bdf': ['bdf'],\n 'application/x-font-ghostscript': ['gsf'],\n 'application/x-font-linux-psf': ['psf'],\n 'application/x-font-pcf': ['pcf'],\n 'application/x-font-snf': ['snf'],\n 'application/x-font-type1': ['pfa', 'pfb', 'pfm', 'afm'],\n 'application/x-freearc': ['arc'],\n 'application/x-futuresplash': ['spl'],\n 'application/x-gca-compressed': ['gca'],\n 'application/x-glulx': ['ulx'],\n 'application/x-gnumeric': ['gnumeric'],\n 'application/x-gramps-xml': ['gramps'],\n 'application/x-gtar': ['gtar'],\n 'application/x-hdf': ['hdf'],\n 'application/x-httpd-php': ['php'],\n 'application/x-install-instructions': ['install'],\n 'application/x-ipynb+json': ['ipynb'],\n 'application/x-iso9660-image': ['*iso'],\n 'application/x-iwork-keynote-sffkey': ['*key'],\n 'application/x-iwork-numbers-sffnumbers': ['*numbers'],\n 'application/x-iwork-pages-sffpages': ['*pages'],\n 'application/x-java-archive-diff': ['jardiff'],\n 'application/x-java-jnlp-file': ['jnlp'],\n 'application/x-keepass2': ['kdbx'],\n 'application/x-latex': ['latex'],\n 'application/x-lua-bytecode': ['luac'],\n 'application/x-lzh-compressed': ['lzh', 'lha'],\n 'application/x-makeself': ['run'],\n 'application/x-mie': ['mie'],\n 'application/x-mobipocket-ebook': ['*prc', 'mobi'],\n 'application/x-ms-application': ['application'],\n 'application/x-ms-shortcut': ['lnk'],\n 'application/x-ms-wmd': ['wmd'],\n 'application/x-ms-wmz': ['wmz'],\n 'application/x-ms-xbap': ['xbap'],\n 'application/x-msaccess': ['mdb'],\n 'application/x-msbinder': ['obd'],\n 'application/x-mscardfile': ['crd'],\n 'application/x-msclip': ['clp'],\n 'application/x-msdos-program': ['*exe'],\n 'application/x-msdownload': ['*exe', '*dll', 'com', 'bat', '*msi'],\n 'application/x-msmediaview': ['mvb', 'm13', 'm14'],\n 'application/x-msmetafile': ['*wmf', '*wmz', '*emf', 'emz'],\n 'application/x-msmoney': ['mny'],\n 'application/x-mspublisher': ['pub'],\n 'application/x-msschedule': ['scd'],\n 'application/x-msterminal': ['trm'],\n 'application/x-mswrite': ['wri'],\n 'application/x-netcdf': ['nc', 'cdf'],\n 'application/x-ns-proxy-autoconfig': ['pac'],\n 'application/x-nzb': ['nzb'],\n 'application/x-perl': ['pl', 'pm'],\n 'application/x-pilot': ['*prc', '*pdb'],\n 'application/x-pkcs12': ['p12', 'pfx'],\n 'application/x-pkcs7-certificates': ['p7b', 'spc'],\n 'application/x-pkcs7-certreqresp': ['p7r'],\n 'application/x-rar-compressed': ['*rar'],\n 'application/x-redhat-package-manager': ['rpm'],\n 'application/x-research-info-systems': ['ris'],\n 'application/x-sea': ['sea'],\n 'application/x-sh': ['sh'],\n 'application/x-shar': ['shar'],\n 'application/x-shockwave-flash': ['swf'],\n 'application/x-silverlight-app': ['xap'],\n 'application/x-sql': ['*sql'],\n 'application/x-stuffit': ['sit'],\n 'application/x-stuffitx': ['sitx'],\n 'application/x-subrip': ['srt'],\n 'application/x-sv4cpio': ['sv4cpio'],\n 'application/x-sv4crc': ['sv4crc'],\n 'application/x-t3vm-image': ['t3'],\n 'application/x-tads': ['gam'],\n 'application/x-tar': ['tar'],\n 'application/x-tcl': ['tcl', 'tk'],\n 'application/x-tex': ['tex'],\n 'application/x-tex-tfm': ['tfm'],\n 'application/x-texinfo': ['texinfo', 'texi'],\n 'application/x-tgif': ['*obj'],\n 'application/x-ustar': ['ustar'],\n 'application/x-virtualbox-hdd': ['hdd'],\n 'application/x-virtualbox-ova': ['ova'],\n 'application/x-virtualbox-ovf': ['ovf'],\n 'application/x-virtualbox-vbox': ['vbox'],\n 'application/x-virtualbox-vbox-extpack': ['vbox-extpack'],\n 'application/x-virtualbox-vdi': ['vdi'],\n 'application/x-virtualbox-vhd': ['vhd'],\n 'application/x-virtualbox-vmdk': ['vmdk'],\n 'application/x-wais-source': ['src'],\n 'application/x-web-app-manifest+json': ['webapp'],\n 'application/x-x509-ca-cert': ['der', 'crt', 'pem'],\n 'application/x-xfig': ['fig'],\n 'application/x-xliff+xml': ['*xlf'],\n 'application/x-xpinstall': ['xpi'],\n 'application/x-xz': ['xz'],\n 'application/x-zip-compressed': ['*zip'],\n 'application/x-zmachine': ['z1', 'z2', 'z3', 'z4', 'z5', 'z6', 'z7', 'z8'],\n 'audio/vnd.dece.audio': ['uva', 'uvva'],\n 'audio/vnd.digital-winds': ['eol'],\n 'audio/vnd.dra': ['dra'],\n 'audio/vnd.dts': ['dts'],\n 'audio/vnd.dts.hd': ['dtshd'],\n 'audio/vnd.lucent.voice': ['lvp'],\n 'audio/vnd.ms-playready.media.pya': ['pya'],\n 'audio/vnd.nuera.ecelp4800': ['ecelp4800'],\n 'audio/vnd.nuera.ecelp7470': ['ecelp7470'],\n 'audio/vnd.nuera.ecelp9600': ['ecelp9600'],\n 'audio/vnd.rip': ['rip'],\n 'audio/x-aac': ['*aac'],\n 'audio/x-aiff': ['aif', 'aiff', 'aifc'],\n 'audio/x-caf': ['caf'],\n 'audio/x-flac': ['flac'],\n 'audio/x-m4a': ['*m4a'],\n 'audio/x-matroska': ['mka'],\n 'audio/x-mpegurl': ['m3u'],\n 'audio/x-ms-wax': ['wax'],\n 'audio/x-ms-wma': ['wma'],\n 'audio/x-pn-realaudio': ['ram', 'ra'],\n 'audio/x-pn-realaudio-plugin': ['rmp'],\n 'audio/x-realaudio': ['*ra'],\n 'audio/x-wav': ['*wav'],\n 'chemical/x-cdx': ['cdx'],\n 'chemical/x-cif': ['cif'],\n 'chemical/x-cmdf': ['cmdf'],\n 'chemical/x-cml': ['cml'],\n 'chemical/x-csml': ['csml'],\n 'chemical/x-xyz': ['xyz'],\n 'image/prs.btif': ['btif', 'btf'],\n 'image/prs.pti': ['pti'],\n 'image/vnd.adobe.photoshop': ['psd'],\n 'image/vnd.airzip.accelerator.azv': ['azv'],\n 'image/vnd.blockfact.facti': ['facti'],\n 'image/vnd.dece.graphic': ['uvi', 'uvvi', 'uvg', 'uvvg'],\n 'image/vnd.djvu': ['djvu', 'djv'],\n 'image/vnd.dvb.subtitle': ['*sub'],\n 'image/vnd.dwg': ['dwg'],\n 'image/vnd.dxf': ['dxf'],\n 'image/vnd.fastbidsheet': ['fbs'],\n 'image/vnd.fpx': ['fpx'],\n 'image/vnd.fst': ['fst'],\n 'image/vnd.fujixerox.edmics-mmr': ['mmr'],\n 'image/vnd.fujixerox.edmics-rlc': ['rlc'],\n 'image/vnd.microsoft.icon': ['ico'],\n 'image/vnd.ms-dds': ['dds'],\n 'image/vnd.ms-modi': ['mdi'],\n 'image/vnd.ms-photo': ['wdp'],\n 'image/vnd.net-fpx': ['npx'],\n 'image/vnd.pco.b16': ['b16'],\n 'image/vnd.tencent.tap': ['tap'],\n 'image/vnd.valve.source.texture': ['vtf'],\n 'image/vnd.wap.wbmp': ['wbmp'],\n 'image/vnd.xiff': ['xif'],\n 'image/vnd.zbrush.pcx': ['pcx'],\n 'image/x-3ds': ['3ds'],\n 'image/x-adobe-dng': ['dng'],\n 'image/x-cmu-raster': ['ras'],\n 'image/x-cmx': ['cmx'],\n 'image/x-freehand': ['fh', 'fhc', 'fh4', 'fh5', 'fh7'],\n 'image/x-icon': ['*ico'],\n 'image/x-jng': ['jng'],\n 'image/x-mrsid-image': ['sid'],\n 'image/x-ms-bmp': ['*bmp'],\n 'image/x-pcx': ['*pcx'],\n 'image/x-pict': ['pic', 'pct'],\n 'image/x-portable-anymap': ['pnm'],\n 'image/x-portable-bitmap': ['pbm'],\n 'image/x-portable-graymap': ['pgm'],\n 'image/x-portable-pixmap': ['ppm'],\n 'image/x-rgb': ['rgb'],\n 'image/x-tga': ['tga'],\n 'image/x-xbitmap': ['xbm'],\n 'image/x-xpixmap': ['xpm'],\n 'image/x-xwindowdump': ['xwd'],\n 'message/vnd.wfa.wsc': ['wsc'],\n 'model/vnd.bary': ['bary'],\n 'model/vnd.cld': ['cld'],\n 'model/vnd.collada+xml': ['dae'],\n 'model/vnd.dwf': ['dwf'],\n 'model/vnd.gdl': ['gdl'],\n 'model/vnd.gtw': ['gtw'],\n 'model/vnd.mts': ['*mts'],\n 'model/vnd.opengex': ['ogex'],\n 'model/vnd.parasolid.transmit.binary': ['x_b'],\n 'model/vnd.parasolid.transmit.text': ['x_t'],\n 'model/vnd.pytha.pyox': ['pyo', 'pyox'],\n 'model/vnd.sap.vds': ['vds'],\n 'model/vnd.usda': ['usda'],\n 'model/vnd.usdz+zip': ['usdz'],\n 'model/vnd.valve.source.compiled-map': ['bsp'],\n 'model/vnd.vtu': ['vtu'],\n 'text/prs.lines.tag': ['dsc'],\n 'text/vnd.curl': ['curl'],\n 'text/vnd.curl.dcurl': ['dcurl'],\n 'text/vnd.curl.mcurl': ['mcurl'],\n 'text/vnd.curl.scurl': ['scurl'],\n 'text/vnd.dvb.subtitle': ['sub'],\n 'text/vnd.familysearch.gedcom': ['ged'],\n 'text/vnd.fly': ['fly'],\n 'text/vnd.fmi.flexstor': ['flx'],\n 'text/vnd.graphviz': ['gv'],\n 'text/vnd.in3d.3dml': ['3dml'],\n 'text/vnd.in3d.spot': ['spot'],\n 'text/vnd.sun.j2me.app-descriptor': ['jad'],\n 'text/vnd.wap.wml': ['wml'],\n 'text/vnd.wap.wmlscript': ['wmls'],\n 'text/x-asm': ['s', 'asm'],\n 'text/x-c': ['c', 'cc', 'cxx', 'cpp', 'h', 'hh', 'dic'],\n 'text/x-component': ['htc'],\n 'text/x-fortran': ['f', 'for', 'f77', 'f90'],\n 'text/x-handlebars-template': ['hbs'],\n 'text/x-java-source': ['java'],\n 'text/x-lua': ['lua'],\n 'text/x-markdown': ['mkd'],\n 'text/x-nfo': ['nfo'],\n 'text/x-opml': ['opml'],\n 'text/x-org': ['*org'],\n 'text/x-pascal': ['p', 'pas'],\n 'text/x-processing': ['pde'],\n 'text/x-sass': ['sass'],\n 'text/x-scss': ['scss'],\n 'text/x-setext': ['etx'],\n 'text/x-sfv': ['sfv'],\n 'text/x-suse-ymp': ['ymp'],\n 'text/x-uuencode': ['uu'],\n 'text/x-vcalendar': ['vcs'],\n 'text/x-vcard': ['vcf'],\n 'video/vnd.dece.hd': ['uvh', 'uvvh'],\n 'video/vnd.dece.mobile': ['uvm', 'uvvm'],\n 'video/vnd.dece.pd': ['uvp', 'uvvp'],\n 'video/vnd.dece.sd': ['uvs', 'uvvs'],\n 'video/vnd.dece.video': ['uvv', 'uvvv'],\n 'video/vnd.dvb.file': ['dvb'],\n 'video/vnd.fvt': ['fvt'],\n 'video/vnd.mpegurl': ['mxu', 'm4u'],\n 'video/vnd.ms-playready.media.pyv': ['pyv'],\n 'video/vnd.uvvu.mp4': ['uvu', 'uvvu'],\n 'video/vnd.vivo': ['viv'],\n 'video/x-f4v': ['f4v'],\n 'video/x-fli': ['fli'],\n 'video/x-flv': ['flv'],\n 'video/x-m4v': ['m4v'],\n 'video/x-matroska': ['mkv', 'mk3d', 'mks'],\n 'video/x-mng': ['mng'],\n 'video/x-ms-asf': ['asf', 'asx'],\n 'video/x-ms-vob': ['vob'],\n 'video/x-ms-wm': ['wm'],\n 'video/x-ms-wmv': ['wmv'],\n 'video/x-ms-wmx': ['wmx'],\n 'video/x-ms-wvx': ['wvx'],\n 'video/x-msvideo': ['avi'],\n 'video/x-sgi-movie': ['movie'],\n 'video/x-smv': ['smv'],\n 'x-conference/x-cooltalk': ['ice'],\n};\nObject.freeze(types);\nexport default types;\n","const types = {\n 'application/andrew-inset': ['ez'],\n 'application/appinstaller': ['appinstaller'],\n 'application/applixware': ['aw'],\n 'application/appx': ['appx'],\n 'application/appxbundle': ['appxbundle'],\n 'application/atom+xml': ['atom'],\n 'application/atomcat+xml': ['atomcat'],\n 'application/atomdeleted+xml': ['atomdeleted'],\n 'application/atomsvc+xml': ['atomsvc'],\n 'application/atsc-dwd+xml': ['dwd'],\n 'application/atsc-held+xml': ['held'],\n 'application/atsc-rsat+xml': ['rsat'],\n 'application/automationml-aml+xml': ['aml'],\n 'application/automationml-amlx+zip': ['amlx'],\n 'application/bdoc': ['bdoc'],\n 'application/calendar+xml': ['xcs'],\n 'application/ccxml+xml': ['ccxml'],\n 'application/cdfx+xml': ['cdfx'],\n 'application/cdmi-capability': ['cdmia'],\n 'application/cdmi-container': ['cdmic'],\n 'application/cdmi-domain': ['cdmid'],\n 'application/cdmi-object': ['cdmio'],\n 'application/cdmi-queue': ['cdmiq'],\n 'application/cpl+xml': ['cpl'],\n 'application/cu-seeme': ['cu'],\n 'application/cwl': ['cwl'],\n 'application/dash+xml': ['mpd'],\n 'application/dash-patch+xml': ['mpp'],\n 'application/davmount+xml': ['davmount'],\n 'application/dicom': ['dcm'],\n 'application/docbook+xml': ['dbk'],\n 'application/dssc+der': ['dssc'],\n 'application/dssc+xml': ['xdssc'],\n 'application/ecmascript': ['ecma'],\n 'application/emma+xml': ['emma'],\n 'application/emotionml+xml': ['emotionml'],\n 'application/epub+zip': ['epub'],\n 'application/exi': ['exi'],\n 'application/express': ['exp'],\n 'application/fdf': ['fdf'],\n 'application/fdt+xml': ['fdt'],\n 'application/font-tdpfr': ['pfr'],\n 'application/geo+json': ['geojson'],\n 'application/gml+xml': ['gml'],\n 'application/gpx+xml': ['gpx'],\n 'application/gxf': ['gxf'],\n 'application/gzip': ['gz'],\n 'application/hjson': ['hjson'],\n 'application/hyperstudio': ['stk'],\n 'application/inkml+xml': ['ink', 'inkml'],\n 'application/ipfix': ['ipfix'],\n 'application/its+xml': ['its'],\n 'application/java-archive': ['jar', 'war', 'ear'],\n 'application/java-serialized-object': ['ser'],\n 'application/java-vm': ['class'],\n 'application/javascript': ['*js'],\n 'application/json': ['json', 'map'],\n 'application/json5': ['json5'],\n 'application/jsonml+json': ['jsonml'],\n 'application/ld+json': ['jsonld'],\n 'application/lgr+xml': ['lgr'],\n 'application/lost+xml': ['lostxml'],\n 'application/mac-binhex40': ['hqx'],\n 'application/mac-compactpro': ['cpt'],\n 'application/mads+xml': ['mads'],\n 'application/manifest+json': ['webmanifest'],\n 'application/marc': ['mrc'],\n 'application/marcxml+xml': ['mrcx'],\n 'application/mathematica': ['ma', 'nb', 'mb'],\n 'application/mathml+xml': ['mathml'],\n 'application/mbox': ['mbox'],\n 'application/media-policy-dataset+xml': ['mpf'],\n 'application/mediaservercontrol+xml': ['mscml'],\n 'application/metalink+xml': ['metalink'],\n 'application/metalink4+xml': ['meta4'],\n 'application/mets+xml': ['mets'],\n 'application/mmt-aei+xml': ['maei'],\n 'application/mmt-usd+xml': ['musd'],\n 'application/mods+xml': ['mods'],\n 'application/mp21': ['m21', 'mp21'],\n 'application/mp4': ['*mp4', '*mpg4', 'mp4s', 'm4p'],\n 'application/msix': ['msix'],\n 'application/msixbundle': ['msixbundle'],\n 'application/msword': ['doc', 'dot'],\n 'application/mxf': ['mxf'],\n 'application/n-quads': ['nq'],\n 'application/n-triples': ['nt'],\n 'application/node': ['cjs'],\n 'application/octet-stream': [\n 'bin',\n 'dms',\n 'lrf',\n 'mar',\n 'so',\n 'dist',\n 'distz',\n 'pkg',\n 'bpk',\n 'dump',\n 'elc',\n 'deploy',\n 'exe',\n 'dll',\n 'deb',\n 'dmg',\n 'iso',\n 'img',\n 'msi',\n 'msp',\n 'msm',\n 'buffer',\n ],\n 'application/oda': ['oda'],\n 'application/oebps-package+xml': ['opf'],\n 'application/ogg': ['ogx'],\n 'application/omdoc+xml': ['omdoc'],\n 'application/onenote': [\n 'onetoc',\n 'onetoc2',\n 'onetmp',\n 'onepkg',\n 'one',\n 'onea',\n ],\n 'application/oxps': ['oxps'],\n 'application/p2p-overlay+xml': ['relo'],\n 'application/patch-ops-error+xml': ['xer'],\n 'application/pdf': ['pdf'],\n 'application/pgp-encrypted': ['pgp'],\n 'application/pgp-keys': ['asc'],\n 'application/pgp-signature': ['sig', '*asc'],\n 'application/pics-rules': ['prf'],\n 'application/pkcs10': ['p10'],\n 'application/pkcs7-mime': ['p7m', 'p7c'],\n 'application/pkcs7-signature': ['p7s'],\n 'application/pkcs8': ['p8'],\n 'application/pkix-attr-cert': ['ac'],\n 'application/pkix-cert': ['cer'],\n 'application/pkix-crl': ['crl'],\n 'application/pkix-pkipath': ['pkipath'],\n 'application/pkixcmp': ['pki'],\n 'application/pls+xml': ['pls'],\n 'application/postscript': ['ai', 'eps', 'ps'],\n 'application/provenance+xml': ['provx'],\n 'application/pskc+xml': ['pskcxml'],\n 'application/raml+yaml': ['raml'],\n 'application/rdf+xml': ['rdf', 'owl'],\n 'application/reginfo+xml': ['rif'],\n 'application/relax-ng-compact-syntax': ['rnc'],\n 'application/resource-lists+xml': ['rl'],\n 'application/resource-lists-diff+xml': ['rld'],\n 'application/rls-services+xml': ['rs'],\n 'application/route-apd+xml': ['rapd'],\n 'application/route-s-tsid+xml': ['sls'],\n 'application/route-usd+xml': ['rusd'],\n 'application/rpki-ghostbusters': ['gbr'],\n 'application/rpki-manifest': ['mft'],\n 'application/rpki-roa': ['roa'],\n 'application/rsd+xml': ['rsd'],\n 'application/rss+xml': ['rss'],\n 'application/rtf': ['rtf'],\n 'application/sbml+xml': ['sbml'],\n 'application/scvp-cv-request': ['scq'],\n 'application/scvp-cv-response': ['scs'],\n 'application/scvp-vp-request': ['spq'],\n 'application/scvp-vp-response': ['spp'],\n 'application/sdp': ['sdp'],\n 'application/senml+xml': ['senmlx'],\n 'application/sensml+xml': ['sensmlx'],\n 'application/set-payment-initiation': ['setpay'],\n 'application/set-registration-initiation': ['setreg'],\n 'application/shf+xml': ['shf'],\n 'application/sieve': ['siv', 'sieve'],\n 'application/smil+xml': ['smi', 'smil'],\n 'application/sparql-query': ['rq'],\n 'application/sparql-results+xml': ['srx'],\n 'application/sql': ['sql'],\n 'application/srgs': ['gram'],\n 'application/srgs+xml': ['grxml'],\n 'application/sru+xml': ['sru'],\n 'application/ssdl+xml': ['ssdl'],\n 'application/ssml+xml': ['ssml'],\n 'application/swid+xml': ['swidtag'],\n 'application/tei+xml': ['tei', 'teicorpus'],\n 'application/thraud+xml': ['tfi'],\n 'application/timestamped-data': ['tsd'],\n 'application/toml': ['toml'],\n 'application/trig': ['trig'],\n 'application/ttml+xml': ['ttml'],\n 'application/ubjson': ['ubj'],\n 'application/urc-ressheet+xml': ['rsheet'],\n 'application/urc-targetdesc+xml': ['td'],\n 'application/voicexml+xml': ['vxml'],\n 'application/wasm': ['wasm'],\n 'application/watcherinfo+xml': ['wif'],\n 'application/widget': ['wgt'],\n 'application/winhlp': ['hlp'],\n 'application/wsdl+xml': ['wsdl'],\n 'application/wspolicy+xml': ['wspolicy'],\n 'application/xaml+xml': ['xaml'],\n 'application/xcap-att+xml': ['xav'],\n 'application/xcap-caps+xml': ['xca'],\n 'application/xcap-diff+xml': ['xdf'],\n 'application/xcap-el+xml': ['xel'],\n 'application/xcap-ns+xml': ['xns'],\n 'application/xenc+xml': ['xenc'],\n 'application/xfdf': ['xfdf'],\n 'application/xhtml+xml': ['xhtml', 'xht'],\n 'application/xliff+xml': ['xlf'],\n 'application/xml': ['xml', 'xsl', 'xsd', 'rng'],\n 'application/xml-dtd': ['dtd'],\n 'application/xop+xml': ['xop'],\n 'application/xproc+xml': ['xpl'],\n 'application/xslt+xml': ['*xsl', 'xslt'],\n 'application/xspf+xml': ['xspf'],\n 'application/xv+xml': ['mxml', 'xhvml', 'xvml', 'xvm'],\n 'application/yang': ['yang'],\n 'application/yin+xml': ['yin'],\n 'application/zip': ['zip'],\n 'application/zip+dotlottie': ['lottie'],\n 'audio/3gpp': ['*3gpp'],\n 'audio/aac': ['adts', 'aac'],\n 'audio/adpcm': ['adp'],\n 'audio/amr': ['amr'],\n 'audio/basic': ['au', 'snd'],\n 'audio/midi': ['mid', 'midi', 'kar', 'rmi'],\n 'audio/mobile-xmf': ['mxmf'],\n 'audio/mp3': ['*mp3'],\n 'audio/mp4': ['m4a', 'mp4a', 'm4b'],\n 'audio/mpeg': ['mpga', 'mp2', 'mp2a', 'mp3', 'm2a', 'm3a'],\n 'audio/ogg': ['oga', 'ogg', 'spx', 'opus'],\n 'audio/s3m': ['s3m'],\n 'audio/silk': ['sil'],\n 'audio/wav': ['wav'],\n 'audio/wave': ['*wav'],\n 'audio/webm': ['weba'],\n 'audio/xm': ['xm'],\n 'font/collection': ['ttc'],\n 'font/otf': ['otf'],\n 'font/ttf': ['ttf'],\n 'font/woff': ['woff'],\n 'font/woff2': ['woff2'],\n 'image/aces': ['exr'],\n 'image/apng': ['apng'],\n 'image/avci': ['avci'],\n 'image/avcs': ['avcs'],\n 'image/avif': ['avif'],\n 'image/bmp': ['bmp', 'dib'],\n 'image/cgm': ['cgm'],\n 'image/dicom-rle': ['drle'],\n 'image/dpx': ['dpx'],\n 'image/emf': ['emf'],\n 'image/fits': ['fits'],\n 'image/g3fax': ['g3'],\n 'image/gif': ['gif'],\n 'image/heic': ['heic'],\n 'image/heic-sequence': ['heics'],\n 'image/heif': ['heif'],\n 'image/heif-sequence': ['heifs'],\n 'image/hej2k': ['hej2'],\n 'image/ief': ['ief'],\n 'image/jaii': ['jaii'],\n 'image/jais': ['jais'],\n 'image/jls': ['jls'],\n 'image/jp2': ['jp2', 'jpg2'],\n 'image/jpeg': ['jpg', 'jpeg', 'jpe'],\n 'image/jph': ['jph'],\n 'image/jphc': ['jhc'],\n 'image/jpm': ['jpm', 'jpgm'],\n 'image/jpx': ['jpx', 'jpf'],\n 'image/jxl': ['jxl'],\n 'image/jxr': ['jxr'],\n 'image/jxra': ['jxra'],\n 'image/jxrs': ['jxrs'],\n 'image/jxs': ['jxs'],\n 'image/jxsc': ['jxsc'],\n 'image/jxsi': ['jxsi'],\n 'image/jxss': ['jxss'],\n 'image/ktx': ['ktx'],\n 'image/ktx2': ['ktx2'],\n 'image/pjpeg': ['jfif'],\n 'image/png': ['png'],\n 'image/sgi': ['sgi'],\n 'image/svg+xml': ['svg', 'svgz'],\n 'image/t38': ['t38'],\n 'image/tiff': ['tif', 'tiff'],\n 'image/tiff-fx': ['tfx'],\n 'image/webp': ['webp'],\n 'image/wmf': ['wmf'],\n 'message/disposition-notification': ['disposition-notification'],\n 'message/global': ['u8msg'],\n 'message/global-delivery-status': ['u8dsn'],\n 'message/global-disposition-notification': ['u8mdn'],\n 'message/global-headers': ['u8hdr'],\n 'message/rfc822': ['eml', 'mime', 'mht', 'mhtml'],\n 'model/3mf': ['3mf'],\n 'model/gltf+json': ['gltf'],\n 'model/gltf-binary': ['glb'],\n 'model/iges': ['igs', 'iges'],\n 'model/jt': ['jt'],\n 'model/mesh': ['msh', 'mesh', 'silo'],\n 'model/mtl': ['mtl'],\n 'model/obj': ['obj'],\n 'model/prc': ['prc'],\n 'model/step': ['step', 'stp', 'stpnc', 'p21', '210'],\n 'model/step+xml': ['stpx'],\n 'model/step+zip': ['stpz'],\n 'model/step-xml+zip': ['stpxz'],\n 'model/stl': ['stl'],\n 'model/u3d': ['u3d'],\n 'model/vrml': ['wrl', 'vrml'],\n 'model/x3d+binary': ['*x3db', 'x3dbz'],\n 'model/x3d+fastinfoset': ['x3db'],\n 'model/x3d+vrml': ['*x3dv', 'x3dvz'],\n 'model/x3d+xml': ['x3d', 'x3dz'],\n 'model/x3d-vrml': ['x3dv'],\n 'text/cache-manifest': ['appcache', 'manifest'],\n 'text/calendar': ['ics', 'ifb'],\n 'text/coffeescript': ['coffee', 'litcoffee'],\n 'text/css': ['css'],\n 'text/csv': ['csv'],\n 'text/html': ['html', 'htm', 'shtml'],\n 'text/jade': ['jade'],\n 'text/javascript': ['js', 'mjs'],\n 'text/jsx': ['jsx'],\n 'text/less': ['less'],\n 'text/markdown': ['md', 'markdown'],\n 'text/mathml': ['mml'],\n 'text/mdx': ['mdx'],\n 'text/n3': ['n3'],\n 'text/plain': ['txt', 'text', 'conf', 'def', 'list', 'log', 'in', 'ini'],\n 'text/richtext': ['rtx'],\n 'text/rtf': ['*rtf'],\n 'text/sgml': ['sgml', 'sgm'],\n 'text/shex': ['shex'],\n 'text/slim': ['slim', 'slm'],\n 'text/spdx': ['spdx'],\n 'text/stylus': ['stylus', 'styl'],\n 'text/tab-separated-values': ['tsv'],\n 'text/troff': ['t', 'tr', 'roff', 'man', 'me', 'ms'],\n 'text/turtle': ['ttl'],\n 'text/uri-list': ['uri', 'uris', 'urls'],\n 'text/vcard': ['vcard'],\n 'text/vtt': ['vtt'],\n 'text/wgsl': ['wgsl'],\n 'text/xml': ['*xml'],\n 'text/yaml': ['yaml', 'yml'],\n 'video/3gpp': ['3gp', '3gpp'],\n 'video/3gpp2': ['3g2'],\n 'video/h261': ['h261'],\n 'video/h263': ['h263'],\n 'video/h264': ['h264'],\n 'video/iso.segment': ['m4s'],\n 'video/jpeg': ['jpgv'],\n 'video/jpm': ['*jpm', '*jpgm'],\n 'video/mj2': ['mj2', 'mjp2'],\n 'video/mp2t': ['ts', 'm2t', 'm2ts', 'mts'],\n 'video/mp4': ['mp4', 'mp4v', 'mpg4'],\n 'video/mpeg': ['mpeg', 'mpg', 'mpe', 'm1v', 'm2v'],\n 'video/ogg': ['ogv'],\n 'video/quicktime': ['qt', 'mov'],\n 'video/webm': ['webm'],\n};\nObject.freeze(types);\nexport default types;\n","var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\n};\nvar _Mime_extensionToType, _Mime_typeToExtension, _Mime_typeToExtensions;\nclass Mime {\n constructor(...args) {\n _Mime_extensionToType.set(this, new Map());\n _Mime_typeToExtension.set(this, new Map());\n _Mime_typeToExtensions.set(this, new Map());\n for (const arg of args) {\n this.define(arg);\n }\n }\n define(typeMap, force = false) {\n for (let [type, extensions] of Object.entries(typeMap)) {\n type = type.toLowerCase();\n extensions = extensions.map((ext) => ext.toLowerCase());\n if (!__classPrivateFieldGet(this, _Mime_typeToExtensions, \"f\").has(type)) {\n __classPrivateFieldGet(this, _Mime_typeToExtensions, \"f\").set(type, new Set());\n }\n const allExtensions = __classPrivateFieldGet(this, _Mime_typeToExtensions, \"f\").get(type);\n let first = true;\n for (let extension of extensions) {\n const starred = extension.startsWith('*');\n extension = starred ? extension.slice(1) : extension;\n allExtensions?.add(extension);\n if (first) {\n __classPrivateFieldGet(this, _Mime_typeToExtension, \"f\").set(type, extension);\n }\n first = false;\n if (starred)\n continue;\n const currentType = __classPrivateFieldGet(this, _Mime_extensionToType, \"f\").get(extension);\n if (currentType && currentType != type && !force) {\n throw new Error(`\"${type} -> ${extension}\" conflicts with \"${currentType} -> ${extension}\". Pass \\`force=true\\` to override this definition.`);\n }\n __classPrivateFieldGet(this, _Mime_extensionToType, \"f\").set(extension, type);\n }\n }\n return this;\n }\n getType(path) {\n if (typeof path !== 'string')\n return null;\n const last = path.replace(/^.*[/\\\\]/s, '').toLowerCase();\n const ext = last.replace(/^.*\\./s, '').toLowerCase();\n const hasPath = last.length < path.length;\n const hasDot = ext.length < last.length - 1;\n if (!hasDot && hasPath)\n return null;\n return __classPrivateFieldGet(this, _Mime_extensionToType, \"f\").get(ext) ?? null;\n }\n getExtension(type) {\n if (typeof type !== 'string')\n return null;\n type = type?.split?.(';')[0];\n return ((type && __classPrivateFieldGet(this, _Mime_typeToExtension, \"f\").get(type.trim().toLowerCase())) ?? null);\n }\n getAllExtensions(type) {\n if (typeof type !== 'string')\n return null;\n return __classPrivateFieldGet(this, _Mime_typeToExtensions, \"f\").get(type.toLowerCase()) ?? null;\n }\n _freeze() {\n this.define = () => {\n throw new Error('define() not allowed for built-in Mime objects. See https://github.com/broofa/mime/blob/main/README.md#custom-mime-instances');\n };\n Object.freeze(this);\n for (const extensions of __classPrivateFieldGet(this, _Mime_typeToExtensions, \"f\").values()) {\n Object.freeze(extensions);\n }\n return this;\n }\n _getTestState() {\n return {\n types: __classPrivateFieldGet(this, _Mime_extensionToType, \"f\"),\n extensions: __classPrivateFieldGet(this, _Mime_typeToExtension, \"f\"),\n };\n }\n}\n_Mime_extensionToType = new WeakMap(), _Mime_typeToExtension = new WeakMap(), _Mime_typeToExtensions = new WeakMap();\nexport default Mime;\n","import otherTypes from '../types/other.js';\nimport standardTypes from '../types/standard.js';\nimport Mime from './Mime.js';\nexport { default as Mime } from './Mime.js';\nexport default new Mime(standardTypes, otherTypes)._freeze();\n","import validate from './validate.js';\nconst byteToHex = [];\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\nexport function unsafeStringify(arr, offset = 0) {\n return (byteToHex[arr[offset + 0]] +\n byteToHex[arr[offset + 1]] +\n byteToHex[arr[offset + 2]] +\n byteToHex[arr[offset + 3]] +\n '-' +\n byteToHex[arr[offset + 4]] +\n byteToHex[arr[offset + 5]] +\n '-' +\n byteToHex[arr[offset + 6]] +\n byteToHex[arr[offset + 7]] +\n '-' +\n byteToHex[arr[offset + 8]] +\n byteToHex[arr[offset + 9]] +\n '-' +\n byteToHex[arr[offset + 10]] +\n byteToHex[arr[offset + 11]] +\n byteToHex[arr[offset + 12]] +\n byteToHex[arr[offset + 13]] +\n byteToHex[arr[offset + 14]] +\n byteToHex[arr[offset + 15]]).toLowerCase();\n}\nfunction stringify(arr, offset = 0) {\n const uuid = unsafeStringify(arr, offset);\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n return uuid;\n}\nexport default stringify;\n","const rnds8 = new Uint8Array(16);\nexport default function rng() {\n return crypto.getRandomValues(rnds8);\n}\n","import rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\nfunction v4(options, buf, offset) {\n if (!buf && !options && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return _v4(options, buf, offset);\n}\nfunction _v4(options, buf, offset) {\n options = options || {};\n const rnds = options.random ?? options.rng?.() ?? rng();\n if (rnds.length < 16) {\n throw new Error('Random bytes length must be >= 16');\n }\n rnds[6] = (rnds[6] & 0x0f) | 0x40;\n rnds[8] = (rnds[8] & 0x3f) | 0x80;\n if (buf) {\n offset = offset || 0;\n if (offset < 0 || offset + 16 > buf.length) {\n throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);\n }\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n return buf;\n }\n return unsafeStringify(rnds);\n}\nexport default v4;\n","/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */\nimport { EventEmitter } from 'node:events';\nimport { stat as statcb, Stats } from 'node:fs';\nimport { readdir, stat } from 'node:fs/promises';\nimport * as sp from 'node:path';\nimport { readdirp, ReaddirpStream } from 'readdirp';\nimport { EMPTY_FN, EVENTS as EV, isIBMi, isWindows, NodeFsHandler, STR_CLOSE, STR_END, } from './handler.js';\nconst SLASH = '/';\nconst SLASH_SLASH = '//';\nconst ONE_DOT = '.';\nconst TWO_DOTS = '..';\nconst STRING_TYPE = 'string';\nconst BACK_SLASH_RE = /\\\\/g;\nconst DOUBLE_SLASH_RE = /\\/\\//g;\nconst DOT_RE = /\\..*\\.(sw[px])$|~$|\\.subl.*\\.tmp/;\nconst REPLACER_RE = /^\\.[/\\\\]/;\nfunction arrify(item) {\n return Array.isArray(item) ? item : [item];\n}\nconst isMatcherObject = (matcher) => typeof matcher === 'object' && matcher !== null && !(matcher instanceof RegExp);\nfunction createPattern(matcher) {\n if (typeof matcher === 'function')\n return matcher;\n if (typeof matcher === 'string')\n return (string) => matcher === string;\n if (matcher instanceof RegExp)\n return (string) => matcher.test(string);\n if (typeof matcher === 'object' && matcher !== null) {\n return (string) => {\n if (matcher.path === string)\n return true;\n if (matcher.recursive) {\n const relative = sp.relative(matcher.path, string);\n if (!relative) {\n return false;\n }\n return !relative.startsWith('..') && !sp.isAbsolute(relative);\n }\n return false;\n };\n }\n return () => false;\n}\nfunction normalizePath(path) {\n if (typeof path !== 'string')\n throw new Error('string expected');\n path = sp.normalize(path);\n path = path.replace(/\\\\/g, '/');\n let prepend = false;\n if (path.startsWith('//'))\n prepend = true;\n path = path.replace(DOUBLE_SLASH_RE, '/');\n if (prepend)\n path = '/' + path;\n return path;\n}\nfunction matchPatterns(patterns, testString, stats) {\n const path = normalizePath(testString);\n for (let index = 0; index < patterns.length; index++) {\n const pattern = patterns[index];\n if (pattern(path, stats)) {\n return true;\n }\n }\n return false;\n}\nfunction anymatch(matchers, testString) {\n if (matchers == null) {\n throw new TypeError('anymatch: specify first argument');\n }\n // Early cache for matchers.\n const matchersArray = arrify(matchers);\n const patterns = matchersArray.map((matcher) => createPattern(matcher));\n if (testString == null) {\n return (testString, stats) => {\n return matchPatterns(patterns, testString, stats);\n };\n }\n return matchPatterns(patterns, testString);\n}\nconst unifyPaths = (paths_) => {\n const paths = arrify(paths_).flat();\n if (!paths.every((p) => typeof p === STRING_TYPE)) {\n throw new TypeError(`Non-string provided as watch path: ${paths}`);\n }\n return paths.map(normalizePathToUnix);\n};\n// If SLASH_SLASH occurs at the beginning of path, it is not replaced\n// because \"//StoragePC/DrivePool/Movies\" is a valid network path\nconst toUnix = (string) => {\n let str = string.replace(BACK_SLASH_RE, SLASH);\n let prepend = false;\n if (str.startsWith(SLASH_SLASH)) {\n prepend = true;\n }\n str = str.replace(DOUBLE_SLASH_RE, SLASH);\n if (prepend) {\n str = SLASH + str;\n }\n return str;\n};\n// Our version of upath.normalize\n// TODO: this is not equal to path-normalize module - investigate why\nconst normalizePathToUnix = (path) => toUnix(sp.normalize(toUnix(path)));\n// TODO: refactor\nconst normalizeIgnored = (cwd = '') => (path) => {\n if (typeof path === 'string') {\n return normalizePathToUnix(sp.isAbsolute(path) ? path : sp.join(cwd, path));\n }\n else {\n return path;\n }\n};\nconst getAbsolutePath = (path, cwd) => {\n if (sp.isAbsolute(path)) {\n return path;\n }\n return sp.join(cwd, path);\n};\nconst EMPTY_SET = Object.freeze(new Set());\n/**\n * Directory entry.\n */\nclass DirEntry {\n path;\n _removeWatcher;\n items;\n constructor(dir, removeWatcher) {\n this.path = dir;\n this._removeWatcher = removeWatcher;\n this.items = new Set();\n }\n add(item) {\n const { items } = this;\n if (!items)\n return;\n if (item !== ONE_DOT && item !== TWO_DOTS)\n items.add(item);\n }\n async remove(item) {\n const { items } = this;\n if (!items)\n return;\n items.delete(item);\n if (items.size > 0)\n return;\n const dir = this.path;\n try {\n await readdir(dir);\n }\n catch (err) {\n if (this._removeWatcher) {\n this._removeWatcher(sp.dirname(dir), sp.basename(dir));\n }\n }\n }\n has(item) {\n const { items } = this;\n if (!items)\n return;\n return items.has(item);\n }\n getChildren() {\n const { items } = this;\n if (!items)\n return [];\n return [...items.values()];\n }\n dispose() {\n this.items.clear();\n this.path = '';\n this._removeWatcher = EMPTY_FN;\n this.items = EMPTY_SET;\n Object.freeze(this);\n }\n}\nconst STAT_METHOD_F = 'stat';\nconst STAT_METHOD_L = 'lstat';\nexport class WatchHelper {\n fsw;\n path;\n watchPath;\n fullWatchPath;\n dirParts;\n followSymlinks;\n statMethod;\n constructor(path, follow, fsw) {\n this.fsw = fsw;\n const watchPath = path;\n this.path = path = path.replace(REPLACER_RE, '');\n this.watchPath = watchPath;\n this.fullWatchPath = sp.resolve(watchPath);\n this.dirParts = [];\n this.dirParts.forEach((parts) => {\n if (parts.length > 1)\n parts.pop();\n });\n this.followSymlinks = follow;\n this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;\n }\n entryPath(entry) {\n return sp.join(this.watchPath, sp.relative(this.watchPath, entry.fullPath));\n }\n filterPath(entry) {\n const { stats } = entry;\n if (stats && stats.isSymbolicLink())\n return this.filterDir(entry);\n const resolvedPath = this.entryPath(entry);\n // TODO: what if stats is undefined? remove !\n return this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);\n }\n filterDir(entry) {\n return this.fsw._isntIgnored(this.entryPath(entry), entry.stats);\n }\n}\n/**\n * Watches files & directories for changes. Emitted events:\n * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`\n *\n * new FSWatcher()\n * .add(directories)\n * .on('add', path => log('File', path, 'was added'))\n */\nexport class FSWatcher extends EventEmitter {\n closed;\n options;\n _closers;\n _ignoredPaths;\n _throttled;\n _streams;\n _symlinkPaths;\n _watched;\n _pendingWrites;\n _pendingUnlinks;\n _readyCount;\n _emitReady;\n _closePromise;\n _userIgnored;\n _readyEmitted;\n _emitRaw;\n _boundRemove;\n _nodeFsHandler;\n // Not indenting methods for history sake; for now.\n constructor(_opts = {}) {\n super();\n this.closed = false;\n this._closers = new Map();\n this._ignoredPaths = new Set();\n this._throttled = new Map();\n this._streams = new Set();\n this._symlinkPaths = new Map();\n this._watched = new Map();\n this._pendingWrites = new Map();\n this._pendingUnlinks = new Map();\n this._readyCount = 0;\n this._readyEmitted = false;\n const awf = _opts.awaitWriteFinish;\n const DEF_AWF = { stabilityThreshold: 2000, pollInterval: 100 };\n const opts = {\n // Defaults\n persistent: true,\n ignoreInitial: false,\n ignorePermissionErrors: false,\n interval: 100,\n binaryInterval: 300,\n followSymlinks: true,\n usePolling: false,\n // useAsync: false,\n atomic: true, // NOTE: overwritten later (depends on usePolling)\n ..._opts,\n // Change format\n ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),\n awaitWriteFinish: awf === true ? DEF_AWF : typeof awf === 'object' ? { ...DEF_AWF, ...awf } : false,\n };\n // Always default to polling on IBM i because fs.watch() is not available on IBM i.\n if (isIBMi)\n opts.usePolling = true;\n // Editor atomic write normalization enabled by default with fs.watch\n if (opts.atomic === undefined)\n opts.atomic = !opts.usePolling;\n // opts.atomic = typeof _opts.atomic === 'number' ? _opts.atomic : 100;\n // Global override. Useful for developers, who need to force polling for all\n // instances of chokidar, regardless of usage / dependency depth\n const envPoll = process.env.CHOKIDAR_USEPOLLING;\n if (envPoll !== undefined) {\n const envLower = envPoll.toLowerCase();\n if (envLower === 'false' || envLower === '0')\n opts.usePolling = false;\n else if (envLower === 'true' || envLower === '1')\n opts.usePolling = true;\n else\n opts.usePolling = !!envLower;\n }\n const envInterval = process.env.CHOKIDAR_INTERVAL;\n if (envInterval)\n opts.interval = Number.parseInt(envInterval, 10);\n // This is done to emit ready only once, but each 'add' will increase that?\n let readyCalls = 0;\n this._emitReady = () => {\n readyCalls++;\n if (readyCalls >= this._readyCount) {\n this._emitReady = EMPTY_FN;\n this._readyEmitted = true;\n // use process.nextTick to allow time for listener to be bound\n process.nextTick(() => this.emit(EV.READY));\n }\n };\n this._emitRaw = (...args) => this.emit(EV.RAW, ...args);\n this._boundRemove = this._remove.bind(this);\n this.options = opts;\n this._nodeFsHandler = new NodeFsHandler(this);\n // You’re frozen when your heart’s not open.\n Object.freeze(opts);\n }\n _addIgnoredPath(matcher) {\n if (isMatcherObject(matcher)) {\n // return early if we already have a deeply equal matcher object\n for (const ignored of this._ignoredPaths) {\n if (isMatcherObject(ignored) &&\n ignored.path === matcher.path &&\n ignored.recursive === matcher.recursive) {\n return;\n }\n }\n }\n this._ignoredPaths.add(matcher);\n }\n _removeIgnoredPath(matcher) {\n this._ignoredPaths.delete(matcher);\n // now find any matcher objects with the matcher as path\n if (typeof matcher === 'string') {\n for (const ignored of this._ignoredPaths) {\n // TODO (43081j): make this more efficient.\n // probably just make a `this._ignoredDirectories` or some\n // such thing.\n if (isMatcherObject(ignored) && ignored.path === matcher) {\n this._ignoredPaths.delete(ignored);\n }\n }\n }\n }\n // Public methods\n /**\n * Adds paths to be watched on an existing FSWatcher instance.\n * @param paths_ file or file list. Other arguments are unused\n */\n add(paths_, _origAdd, _internal) {\n const { cwd } = this.options;\n this.closed = false;\n this._closePromise = undefined;\n let paths = unifyPaths(paths_);\n if (cwd) {\n paths = paths.map((path) => {\n const absPath = getAbsolutePath(path, cwd);\n // Check `path` instead of `absPath` because the cwd portion can't be a glob\n return absPath;\n });\n }\n paths.forEach((path) => {\n this._removeIgnoredPath(path);\n });\n this._userIgnored = undefined;\n if (!this._readyCount)\n this._readyCount = 0;\n this._readyCount += paths.length;\n Promise.all(paths.map(async (path) => {\n const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, undefined, 0, _origAdd);\n if (res)\n this._emitReady();\n return res;\n })).then((results) => {\n if (this.closed)\n return;\n results.forEach((item) => {\n if (item)\n this.add(sp.dirname(item), sp.basename(_origAdd || item));\n });\n });\n return this;\n }\n /**\n * Close watchers or start ignoring events from specified paths.\n */\n unwatch(paths_) {\n if (this.closed)\n return this;\n const paths = unifyPaths(paths_);\n const { cwd } = this.options;\n paths.forEach((path) => {\n // convert to absolute path unless relative path already matches\n if (!sp.isAbsolute(path) && !this._closers.has(path)) {\n if (cwd)\n path = sp.join(cwd, path);\n path = sp.resolve(path);\n }\n this._closePath(path);\n this._addIgnoredPath(path);\n if (this._watched.has(path)) {\n this._addIgnoredPath({\n path,\n recursive: true,\n });\n }\n // reset the cached userIgnored anymatch fn\n // to make ignoredPaths changes effective\n this._userIgnored = undefined;\n });\n return this;\n }\n /**\n * Close watchers and remove all listeners from watched paths.\n */\n close() {\n if (this._closePromise) {\n return this._closePromise;\n }\n this.closed = true;\n // Memory management.\n this.removeAllListeners();\n const closers = [];\n this._closers.forEach((closerList) => closerList.forEach((closer) => {\n const promise = closer();\n if (promise instanceof Promise)\n closers.push(promise);\n }));\n this._streams.forEach((stream) => stream.destroy());\n this._userIgnored = undefined;\n this._readyCount = 0;\n this._readyEmitted = false;\n this._watched.forEach((dirent) => dirent.dispose());\n this._closers.clear();\n this._watched.clear();\n this._streams.clear();\n this._symlinkPaths.clear();\n this._throttled.clear();\n this._closePromise = closers.length\n ? Promise.all(closers).then(() => undefined)\n : Promise.resolve();\n return this._closePromise;\n }\n /**\n * Expose list of watched paths\n * @returns for chaining\n */\n getWatched() {\n const watchList = {};\n this._watched.forEach((entry, dir) => {\n const key = this.options.cwd ? sp.relative(this.options.cwd, dir) : dir;\n const index = key || ONE_DOT;\n watchList[index] = entry.getChildren().sort();\n });\n return watchList;\n }\n emitWithAll(event, args) {\n this.emit(event, ...args);\n if (event !== EV.ERROR)\n this.emit(EV.ALL, event, ...args);\n }\n // Common helpers\n // --------------\n /**\n * Normalize and emit events.\n * Calling _emit DOES NOT MEAN emit() would be called!\n * @param event Type of event\n * @param path File or directory path\n * @param stats arguments to be passed with event\n * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag\n */\n async _emit(event, path, stats) {\n if (this.closed)\n return;\n const opts = this.options;\n if (isWindows)\n path = sp.normalize(path);\n if (opts.cwd)\n path = sp.relative(opts.cwd, path);\n const args = [path];\n if (stats != null)\n args.push(stats);\n const awf = opts.awaitWriteFinish;\n let pw;\n if (awf && (pw = this._pendingWrites.get(path))) {\n pw.lastChange = new Date();\n return this;\n }\n if (opts.atomic) {\n if (event === EV.UNLINK) {\n this._pendingUnlinks.set(path, [event, ...args]);\n setTimeout(() => {\n this._pendingUnlinks.forEach((entry, path) => {\n this.emit(...entry);\n this.emit(EV.ALL, ...entry);\n this._pendingUnlinks.delete(path);\n });\n }, typeof opts.atomic === 'number' ? opts.atomic : 100);\n return this;\n }\n if (event === EV.ADD && this._pendingUnlinks.has(path)) {\n event = EV.CHANGE;\n this._pendingUnlinks.delete(path);\n }\n }\n if (awf && (event === EV.ADD || event === EV.CHANGE) && this._readyEmitted) {\n const awfEmit = (err, stats) => {\n if (err) {\n event = EV.ERROR;\n args[0] = err;\n this.emitWithAll(event, args);\n }\n else if (stats) {\n // if stats doesn't exist the file must have been deleted\n if (args.length > 1) {\n args[1] = stats;\n }\n else {\n args.push(stats);\n }\n this.emitWithAll(event, args);\n }\n };\n this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);\n return this;\n }\n if (event === EV.CHANGE) {\n const isThrottled = !this._throttle(EV.CHANGE, path, 50);\n if (isThrottled)\n return this;\n }\n if (opts.alwaysStat &&\n stats === undefined &&\n (event === EV.ADD || event === EV.ADD_DIR || event === EV.CHANGE)) {\n const fullPath = opts.cwd ? sp.join(opts.cwd, path) : path;\n let stats;\n try {\n stats = await stat(fullPath);\n }\n catch (err) {\n // do nothing\n }\n // Suppress event when fs_stat fails, to avoid sending undefined 'stat'\n if (!stats || this.closed)\n return;\n args.push(stats);\n }\n this.emitWithAll(event, args);\n return this;\n }\n /**\n * Common handler for errors\n * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag\n */\n _handleError(error) {\n const code = error && error.code;\n if (error &&\n code !== 'ENOENT' &&\n code !== 'ENOTDIR' &&\n (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES'))) {\n this.emit(EV.ERROR, error);\n }\n return error || this.closed;\n }\n /**\n * Helper utility for throttling\n * @param actionType type being throttled\n * @param path being acted upon\n * @param timeout duration of time to suppress duplicate actions\n * @returns tracking object or false if action should be suppressed\n */\n _throttle(actionType, path, timeout) {\n if (!this._throttled.has(actionType)) {\n this._throttled.set(actionType, new Map());\n }\n const action = this._throttled.get(actionType);\n if (!action)\n throw new Error('invalid throttle');\n const actionPath = action.get(path);\n if (actionPath) {\n actionPath.count++;\n return false;\n }\n // eslint-disable-next-line prefer-const\n let timeoutObject;\n const clear = () => {\n const item = action.get(path);\n const count = item ? item.count : 0;\n action.delete(path);\n clearTimeout(timeoutObject);\n if (item)\n clearTimeout(item.timeoutObject);\n return count;\n };\n timeoutObject = setTimeout(clear, timeout);\n const thr = { timeoutObject, clear, count: 0 };\n action.set(path, thr);\n return thr;\n }\n _incrReadyCount() {\n return this._readyCount++;\n }\n /**\n * Awaits write operation to finish.\n * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.\n * @param path being acted upon\n * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished\n * @param event\n * @param awfEmit Callback to be called when ready for event to be emitted.\n */\n _awaitWriteFinish(path, threshold, event, awfEmit) {\n const awf = this.options.awaitWriteFinish;\n if (typeof awf !== 'object')\n return;\n const pollInterval = awf.pollInterval;\n let timeoutHandler;\n let fullPath = path;\n if (this.options.cwd && !sp.isAbsolute(path)) {\n fullPath = sp.join(this.options.cwd, path);\n }\n const now = new Date();\n const writes = this._pendingWrites;\n function awaitWriteFinishFn(prevStat) {\n statcb(fullPath, (err, curStat) => {\n if (err || !writes.has(path)) {\n if (err && err.code !== 'ENOENT')\n awfEmit(err);\n return;\n }\n const now = Number(new Date());\n if (prevStat && curStat.size !== prevStat.size) {\n writes.get(path).lastChange = now;\n }\n const pw = writes.get(path);\n const df = now - pw.lastChange;\n if (df >= threshold) {\n writes.delete(path);\n awfEmit(undefined, curStat);\n }\n else {\n timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);\n }\n });\n }\n if (!writes.has(path)) {\n writes.set(path, {\n lastChange: now,\n cancelWait: () => {\n writes.delete(path);\n clearTimeout(timeoutHandler);\n return event;\n },\n });\n timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);\n }\n }\n /**\n * Determines whether user has asked to ignore this path.\n */\n _isIgnored(path, stats) {\n if (this.options.atomic && DOT_RE.test(path))\n return true;\n if (!this._userIgnored) {\n const { cwd } = this.options;\n const ign = this.options.ignored;\n const ignored = (ign || []).map(normalizeIgnored(cwd));\n const ignoredPaths = [...this._ignoredPaths];\n const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];\n this._userIgnored = anymatch(list, undefined);\n }\n return this._userIgnored(path, stats);\n }\n _isntIgnored(path, stat) {\n return !this._isIgnored(path, stat);\n }\n /**\n * Provides a set of common helpers and properties relating to symlink handling.\n * @param path file or directory pattern being watched\n */\n _getWatchHelpers(path) {\n return new WatchHelper(path, this.options.followSymlinks, this);\n }\n // Directory helpers\n // -----------------\n /**\n * Provides directory tracking objects\n * @param directory path of the directory\n */\n _getWatchedDir(directory) {\n const dir = sp.resolve(directory);\n if (!this._watched.has(dir))\n this._watched.set(dir, new DirEntry(dir, this._boundRemove));\n return this._watched.get(dir);\n }\n // File helpers\n // ------------\n /**\n * Check for read permissions: https://stackoverflow.com/a/11781404/1358405\n */\n _hasReadPermissions(stats) {\n if (this.options.ignorePermissionErrors)\n return true;\n return Boolean(Number(stats.mode) & 0o400);\n }\n /**\n * Handles emitting unlink events for\n * files and directories, and via recursion, for\n * files and directories within directories that are unlinked\n * @param directory within which the following item is located\n * @param item base path of item/directory\n */\n _remove(directory, item, isDirectory) {\n // if what is being deleted is a directory, get that directory's paths\n // for recursive deleting and cleaning of watched object\n // if it is not a directory, nestedDirectoryChildren will be empty array\n const path = sp.join(directory, item);\n const fullPath = sp.resolve(path);\n isDirectory =\n isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);\n // prevent duplicate handling in case of arriving here nearly simultaneously\n // via multiple paths (such as _handleFile and _handleDir)\n if (!this._throttle('remove', path, 100))\n return;\n // if the only watched file is removed, watch for its return\n if (!isDirectory && this._watched.size === 1) {\n this.add(directory, item, true);\n }\n // This will create a new entry in the watched object in either case\n // so we got to do the directory check beforehand\n const wp = this._getWatchedDir(path);\n const nestedDirectoryChildren = wp.getChildren();\n // Recursively remove children directories / files.\n nestedDirectoryChildren.forEach((nested) => this._remove(path, nested));\n // Check if item was on the watched list and remove it\n const parent = this._getWatchedDir(directory);\n const wasTracked = parent.has(item);\n parent.remove(item);\n // Fixes issue #1042 -> Relative paths were detected and added as symlinks\n // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612),\n // but never removed from the map in case the path was deleted.\n // This leads to an incorrect state if the path was recreated:\n // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553\n if (this._symlinkPaths.has(fullPath)) {\n this._symlinkPaths.delete(fullPath);\n }\n // If we wait for this file to be fully written, cancel the wait.\n let relPath = path;\n if (this.options.cwd)\n relPath = sp.relative(this.options.cwd, path);\n if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {\n const event = this._pendingWrites.get(relPath).cancelWait();\n if (event === EV.ADD)\n return;\n }\n // The Entry will either be a directory that just got removed\n // or a bogus entry to a file, in either case we have to remove it\n this._watched.delete(path);\n this._watched.delete(fullPath);\n const eventName = isDirectory ? EV.UNLINK_DIR : EV.UNLINK;\n if (wasTracked && !this._isIgnored(path))\n this._emit(eventName, path);\n // Avoid conflicts if we later create another file with the same name\n this._closePath(path);\n }\n /**\n * Closes all watchers for a path\n */\n _closePath(path) {\n this._closeFile(path);\n const dir = sp.dirname(path);\n this._getWatchedDir(dir).remove(sp.basename(path));\n }\n /**\n * Closes only file-specific watchers\n */\n _closeFile(path) {\n const closers = this._closers.get(path);\n if (!closers)\n return;\n closers.forEach((closer) => closer());\n this._closers.delete(path);\n }\n _addPathCloser(path, closer) {\n if (!closer)\n return;\n let list = this._closers.get(path);\n if (!list) {\n list = [];\n this._closers.set(path, list);\n }\n list.push(closer);\n }\n _readdirp(root, opts) {\n if (this.closed)\n return;\n const options = { type: EV.ALL, alwaysStat: true, lstat: true, ...opts, depth: 0 };\n let stream = readdirp(root, options);\n this._streams.add(stream);\n stream.once(STR_CLOSE, () => {\n stream = undefined;\n });\n stream.once(STR_END, () => {\n if (stream) {\n this._streams.delete(stream);\n stream = undefined;\n }\n });\n return stream;\n }\n}\n/**\n * Instantiates watcher with paths to be tracked.\n * @param paths file / directory paths\n * @param options opts, such as `atomic`, `awaitWriteFinish`, `ignored`, and others\n * @returns an instance of FSWatcher for chaining.\n * @example\n * const watcher = watch('.').on('all', (event, path) => { console.log(event, path); });\n * watch('.', { atomic: true, awaitWriteFinish: true, ignored: (f, stats) => stats?.isFile() && !f.endsWith('.js') })\n */\nexport function watch(paths, options = {}) {\n const watcher = new FSWatcher(options);\n watcher.add(paths);\n return watcher;\n}\nexport default { watch: watch, FSWatcher: FSWatcher };\n","import { lstat, readdir, realpath, stat } from 'node:fs/promises';\nimport { join as pjoin, resolve as presolve, sep as psep } from 'node:path';\nimport { Readable } from 'node:stream';\nexport const EntryTypes = {\n FILE_TYPE: 'files',\n DIR_TYPE: 'directories',\n FILE_DIR_TYPE: 'files_directories',\n EVERYTHING_TYPE: 'all',\n};\nconst defaultOptions = {\n root: '.',\n fileFilter: (_entryInfo) => true,\n directoryFilter: (_entryInfo) => true,\n type: EntryTypes.FILE_TYPE,\n lstat: false,\n depth: 2147483648,\n alwaysStat: false,\n // Throughput is flat from 16 to 65536 (traversal is I/O-bound), but\n // batches of 1024+ entries survive young-gen GC and bloat RSS ~20-60%.\n highWaterMark: 256,\n};\nObject.freeze(defaultOptions);\nconst RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR';\nconst NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]);\nconst ALL_TYPES = [\n EntryTypes.DIR_TYPE,\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n EntryTypes.FILE_TYPE,\n];\nconst DIR_TYPES = new Set([\n EntryTypes.DIR_TYPE,\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n]);\nconst FILE_TYPES = new Set([\n EntryTypes.EVERYTHING_TYPE,\n EntryTypes.FILE_DIR_TYPE,\n EntryTypes.FILE_TYPE,\n]);\nconst isNormalFlowError = (error) => NORMAL_FLOW_ERRORS.has(error.code);\nconst wantBigintFsStats = process.platform === 'win32';\nconst emptyFn = (_entryInfo) => true;\nconst normalizeFilter = (filter) => {\n if (filter === undefined)\n return emptyFn;\n if (typeof filter === 'function')\n return filter;\n if (typeof filter === 'string') {\n const fl = filter.trim();\n return (entry) => entry.basename === fl;\n }\n if (Array.isArray(filter)) {\n const trItems = filter.map((item) => item.trim());\n return (entry) => trItems.some((f) => entry.basename === f);\n }\n return emptyFn;\n};\nexport class ReaddirpStream extends Readable {\n /**\n * Directories discovered but not yet emitted from. Listings are read\n * lazily (on pop, plus one prefetch) instead of eagerly on discovery:\n * keeping whole listings for every queued dir balloons RAM on wide trees.\n */\n parents;\n reading;\n parent;\n _stat;\n _maxDepth;\n _wantsDir;\n _wantsFile;\n _wantsEverything;\n _root;\n _isDirent;\n _statsProp;\n _rdOptions;\n _fileFilter;\n _directoryFilter;\n _relStart;\n constructor(options = {}) {\n super({\n objectMode: true,\n autoDestroy: true,\n highWaterMark: options.highWaterMark ?? defaultOptions.highWaterMark,\n });\n const opts = { ...defaultOptions, ...options };\n // Use ?? so an explicit `undefined` in user options doesn't shadow defaults.\n const root = opts.root ?? defaultOptions.root;\n const type = opts.type ?? defaultOptions.type;\n this._fileFilter = normalizeFilter(opts.fileFilter);\n this._directoryFilter = normalizeFilter(opts.directoryFilter);\n const statMethod = opts.lstat ? lstat : stat;\n // Use bigint stats if it's windows and stat() supports options (node 10+).\n if (wantBigintFsStats) {\n this._stat = (path) => statMethod(path, { bigint: true });\n }\n else {\n this._stat = statMethod;\n }\n this._maxDepth =\n opts.depth != null && Number.isSafeInteger(opts.depth) ? opts.depth : defaultOptions.depth;\n this._wantsDir = DIR_TYPES.has(type);\n this._wantsFile = FILE_TYPES.has(type);\n this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;\n this._root = presolve(root);\n // Every fullPath is `_root + sep + relative path` (see _formatEntry), so\n // the relative path is a slice starting past the root and its trailing\n // separator (which resolved paths lack, except fs roots like '/', 'C:\\').\n this._relStart = this._root.endsWith(psep) ? this._root.length : this._root.length + 1;\n this._isDirent = !opts.alwaysStat;\n this._statsProp = this._isDirent ? 'dirent' : 'stats';\n this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent };\n // Launch stream with one parent, the root dir, whose readdir starts\n // right away. Explore the resolved root so all parent paths stay\n // absolute even if process.cwd() changes mid-iteration.\n const rootDir = { path: this._root, depth: 1 };\n rootDir.pending = this._exploreDir(this._root, 1);\n this.parents = [rootDir];\n this.reading = false;\n this.parent = undefined;\n }\n async _read(batch) {\n if (this.reading)\n return;\n this.reading = true;\n try {\n while (!this.destroyed && batch > 0) {\n const par = this.parent;\n const fil = par && par.files;\n if (fil && fil.length > 0) {\n const { path, depth } = par;\n const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path));\n // In dirent mode _formatEntry is synchronous: skip Promise.all and\n // its per-entry microtask overhead.\n const awaited = this._isDirent\n ? slice\n : await Promise.all(slice);\n for (const entry of awaited) {\n if (!entry)\n continue;\n if (this.destroyed)\n return;\n // Only symlinks require async work; plain files / dirs resolve synchronously.\n let entryType = this._getEntryType(entry);\n if (typeof entryType !== 'string')\n entryType = await entryType;\n if (entryType === 'directory' && this._directoryFilter(entry)) {\n if (depth <= this._maxDepth) {\n // Lazy: don't readdir until this dir is popped. Keeping whole\n // listings for every queued dir would balloon RAM on wide trees.\n this.parents.push({ path: entry.fullPath, depth: depth + 1 });\n }\n if (this._wantsDir) {\n this.push(entry);\n batch--;\n }\n }\n else if ((entryType === 'file' || this._includeAsFile(entry)) &&\n this._fileFilter(entry)) {\n if (this._wantsFile) {\n this.push(entry);\n batch--;\n }\n }\n }\n }\n else {\n const parent = this.parents.pop();\n if (!parent) {\n this.push(null);\n break;\n }\n const dir = parent.pending ?? this._exploreDir(parent.path, parent.depth);\n // Prefetch the next dir so its readdir overlaps with processing\n // this one's entries. Only the stack top is prefetched, keeping at\n // most a handful of listings (~tree depth) in RAM at once.\n const next = this.parents[this.parents.length - 1];\n if (next && !next.pending) {\n next.pending = this._exploreDir(next.path, next.depth);\n }\n this.parent = await dir;\n if (this.destroyed)\n return;\n }\n }\n }\n catch (error) {\n this.destroy(error);\n }\n finally {\n this.reading = false;\n }\n }\n // NOTE: native `readdir(path, { recursive: true })` was evaluated as a\n // replacement for this per-directory traversal and rejected:\n // - Not faster: node implements it in JS, walking directories sequentially\n // just like this loop, but with extra path bookkeeping. Benchmarks\n // (node 24): ~10% slower on wide trees, ~40% slower on small ones,\n // parity on deep ones.\n // - Much more RAM: it buffers the entire subtree listing in one array,\n // instead of one directory at a time, defeating streaming.\n // - Semantics diverge: it can't limit depth, can't skip directories a\n // directoryFilter rejects, doesn't follow symlinked dirs, and fails\n // wholesale (all entries lost) if anything in the subtree is unreadable,\n // instead of emitting a 'warn' and continuing.\n async _exploreDir(path, depth) {\n let files;\n try {\n files = await readdir(path, this._rdOptions);\n }\n catch (error) {\n this._onError(error);\n }\n return { files, depth, path };\n }\n // Synchronous in dirent mode; returns a promise only when stats are needed.\n _formatEntry(dirent, path) {\n const basename = this._isDirent ? dirent.name : dirent;\n // `path` is always an absolute, normalized parent dir (see _exploreDir\n // seeding in the constructor), so a plain join is enough — resolve()\n // would re-read cwd on every entry.\n const fullPath = pjoin(path, basename);\n // Slice instead of path.relative(): equivalent here (fullPath is always\n // under _root) and avoids several intermediate allocations per entry.\n const entry = { path: fullPath.slice(this._relStart), fullPath, basename };\n if (this._isDirent) {\n entry.dirent = dirent;\n return entry;\n }\n return this._stat(fullPath).then((stats) => {\n entry.stats = stats;\n return entry;\n }, (err) => {\n this._onError(err);\n return undefined;\n });\n }\n _onError(err) {\n if (isNormalFlowError(err) && !this.destroyed) {\n this.emit('warn', err);\n }\n else {\n this.destroy(err);\n }\n }\n // Synchronous for regular files and directories; returns a promise only for\n // symlinks, which need realpath() to be classified.\n _getEntryType(entry) {\n // entry may be undefined, because a warning or an error were emitted\n // and the statsProp is undefined\n if (!entry || !(this._statsProp in entry)) {\n return '';\n }\n const stats = entry[this._statsProp];\n if (stats.isFile())\n return 'file';\n if (stats.isDirectory())\n return 'directory';\n if (stats.isSymbolicLink())\n return this._getSymlinkEntryType(entry);\n return '';\n }\n async _getSymlinkEntryType(entry) {\n const full = entry.fullPath;\n try {\n const entryRealPath = await realpath(full);\n const entryRealPathStats = await lstat(entryRealPath);\n if (entryRealPathStats.isFile()) {\n return 'file';\n }\n if (entryRealPathStats.isDirectory()) {\n const len = entryRealPath.length;\n if (full.startsWith(entryRealPath) && full[len] === psep) {\n const recursiveError = new Error(`Circular symlink detected: \"${full}\" points to \"${entryRealPath}\"`);\n // @ts-ignore\n recursiveError.code = RECURSIVE_ERROR_CODE;\n this._onError(recursiveError);\n return '';\n }\n return 'directory';\n }\n }\n catch (error) {\n this._onError(error);\n }\n return '';\n }\n _includeAsFile(entry) {\n const stats = entry && entry[this._statsProp];\n return stats && this._wantsEverything && !stats.isDirectory();\n }\n}\n/**\n * Streaming version: Reads all files and directories in given root recursively.\n * Consumes ~constant small amount of RAM.\n * @param root Root directory\n * @param options Options to specify root (start directory), filters and recursion depth\n */\nexport function readdirp(root, options = {}) {\n // @ts-ignore\n let type = options.entryType || options.type;\n if (type === 'both')\n type = EntryTypes.FILE_DIR_TYPE; // backwards-compatibility\n if (!root) {\n throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)');\n }\n else if (typeof root !== 'string') {\n throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)');\n }\n else if (type && !ALL_TYPES.includes(type)) {\n throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`);\n }\n // Copy options instead of mutating the caller's object.\n const opts = { ...options, root };\n if (type)\n opts.type = type;\n return new ReaddirpStream(opts);\n}\n/**\n * Promise version: Reads all files and directories in given root recursively.\n * Compared to streaming version, will consume a lot of RAM e.g. when 1 million files are listed.\n * @returns array of paths and their entry infos\n */\nexport function readdirpPromise(root, options = {}) {\n return new Promise((resolve, reject) => {\n const files = [];\n readdirp(root, options)\n .on('data', (entry) => files.push(entry))\n .on('end', () => resolve(files))\n .on('error', (error) => reject(error));\n });\n}\nexport default readdirp;\n","import { watch as fs_watch, unwatchFile, watchFile } from 'node:fs';\nimport { realpath as fsrealpath, lstat, open, stat } from 'node:fs/promises';\nimport { type as osType } from 'node:os';\nimport * as sp from 'node:path';\nexport const STR_DATA = 'data';\nexport const STR_END = 'end';\nexport const STR_CLOSE = 'close';\nexport const EMPTY_FN = () => { };\nexport const IDENTITY_FN = (val) => val;\nconst pl = process.platform;\nexport const isWindows = pl === 'win32';\nexport const isMacos = pl === 'darwin';\nexport const isLinux = pl === 'linux';\nexport const isFreeBSD = pl === 'freebsd';\nexport const isIBMi = osType() === 'OS400';\nexport const EVENTS = {\n ALL: 'all',\n READY: 'ready',\n ADD: 'add',\n CHANGE: 'change',\n ADD_DIR: 'addDir',\n UNLINK: 'unlink',\n UNLINK_DIR: 'unlinkDir',\n RAW: 'raw',\n ERROR: 'error',\n};\nconst EV = EVENTS;\nconst THROTTLE_MODE_WATCH = 'watch';\nconst statMethods = { lstat, stat };\nconst KEY_LISTENERS = 'listeners';\nconst KEY_ERR = 'errHandlers';\nconst KEY_RAW = 'rawEmitters';\nconst HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];\n// prettier-ignore\nconst binaryExtensions = new Set([\n '3dm', '3ds', '3g2', '3gp', '7z', 'a', 'aac', 'adp', 'afdesign', 'afphoto', 'afpub', 'ai',\n 'aif', 'aiff', 'alz', 'ape', 'apk', 'appimage', 'ar', 'arj', 'asf', 'au', 'avi',\n 'bak', 'baml', 'bh', 'bin', 'bk', 'bmp', 'btif', 'bz2', 'bzip2',\n 'cab', 'caf', 'cgm', 'class', 'cmx', 'cpio', 'cr2', 'cur', 'dat', 'dcm', 'deb', 'dex', 'djvu',\n 'dll', 'dmg', 'dng', 'doc', 'docm', 'docx', 'dot', 'dotm', 'dra', 'DS_Store', 'dsk', 'dts',\n 'dtshd', 'dvb', 'dwg', 'dxf',\n 'ecelp4800', 'ecelp7470', 'ecelp9600', 'egg', 'eol', 'eot', 'epub', 'exe',\n 'f4v', 'fbs', 'fh', 'fla', 'flac', 'flatpak', 'fli', 'flv', 'fpx', 'fst', 'fvt',\n 'g3', 'gh', 'gif', 'graffle', 'gz', 'gzip',\n 'h261', 'h263', 'h264', 'icns', 'ico', 'ief', 'img', 'ipa', 'iso',\n 'jar', 'jpeg', 'jpg', 'jpgv', 'jpm', 'jxr', 'key', 'ktx',\n 'lha', 'lib', 'lvp', 'lz', 'lzh', 'lzma', 'lzo',\n 'm3u', 'm4a', 'm4v', 'mar', 'mdi', 'mht', 'mid', 'midi', 'mj2', 'mka', 'mkv', 'mmr', 'mng',\n 'mobi', 'mov', 'movie', 'mp3',\n 'mp4', 'mp4a', 'mpeg', 'mpg', 'mpga', 'mxu',\n 'nef', 'npx', 'numbers', 'nupkg',\n 'o', 'odp', 'ods', 'odt', 'oga', 'ogg', 'ogv', 'otf', 'ott',\n 'pages', 'pbm', 'pcx', 'pdb', 'pdf', 'pea', 'pgm', 'pic', 'png', 'pnm', 'pot', 'potm',\n 'potx', 'ppa', 'ppam',\n 'ppm', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx', 'psd', 'pya', 'pyc', 'pyo', 'pyv',\n 'qt',\n 'rar', 'ras', 'raw', 'resources', 'rgb', 'rip', 'rlc', 'rmf', 'rmvb', 'rpm', 'rtf', 'rz',\n 's3m', 's7z', 'scpt', 'sgi', 'shar', 'snap', 'sil', 'sketch', 'slk', 'smv', 'snk', 'so',\n 'stl', 'suo', 'sub', 'swf',\n 'tar', 'tbz', 'tbz2', 'tga', 'tgz', 'thmx', 'tif', 'tiff', 'tlz', 'ttc', 'ttf', 'txz',\n 'udf', 'uvh', 'uvi', 'uvm', 'uvp', 'uvs', 'uvu',\n 'viv', 'vob',\n 'war', 'wav', 'wax', 'wbmp', 'wdp', 'weba', 'webm', 'webp', 'whl', 'wim', 'wm', 'wma',\n 'wmv', 'wmx', 'woff', 'woff2', 'wrm', 'wvx',\n 'xbm', 'xif', 'xla', 'xlam', 'xls', 'xlsb', 'xlsm', 'xlsx', 'xlt', 'xltm', 'xltx', 'xm',\n 'xmind', 'xpi', 'xpm', 'xwd', 'xz',\n 'z', 'zip', 'zipx',\n]);\nconst isBinaryPath = (filePath) => binaryExtensions.has(sp.extname(filePath).slice(1).toLowerCase());\n// TODO: emit errors properly. Example: EMFILE on Macos.\nconst foreach = (val, fn) => {\n if (val instanceof Set) {\n val.forEach(fn);\n }\n else {\n fn(val);\n }\n};\nconst addAndConvert = (main, prop, item) => {\n let container = main[prop];\n if (!(container instanceof Set)) {\n main[prop] = container = new Set([container]);\n }\n container.add(item);\n};\nconst clearItem = (cont) => (key) => {\n const set = cont[key];\n if (set instanceof Set) {\n set.clear();\n }\n else {\n delete cont[key];\n }\n};\nconst delFromSet = (main, prop, item) => {\n const container = main[prop];\n if (container instanceof Set) {\n container.delete(item);\n }\n else if (container === item) {\n delete main[prop];\n }\n};\nconst isEmptySet = (val) => (val instanceof Set ? val.size === 0 : !val);\nconst FsWatchInstances = new Map();\n/**\n * Instantiates the fs_watch interface\n * @param path to be watched\n * @param options to be passed to fs_watch\n * @param listener main event handler\n * @param errHandler emits info about errors\n * @param emitRaw emits raw event data\n * @returns {NativeFsWatcher}\n */\nfunction createFsWatchInstance(path, options, listener, errHandler, emitRaw) {\n const handleEvent = (rawEvent, evPath) => {\n listener(path);\n emitRaw(rawEvent, evPath, { watchedPath: path });\n // emit based on events occurring for files from a directory's watcher in\n // case the file's watcher misses it (and rely on throttling to de-dupe)\n if (evPath && path !== evPath) {\n fsWatchBroadcast(sp.resolve(path, evPath), KEY_LISTENERS, sp.join(path, evPath));\n }\n };\n try {\n return fs_watch(path, {\n persistent: options.persistent,\n }, handleEvent);\n }\n catch (error) {\n errHandler(error);\n return undefined;\n }\n}\n/**\n * Helper for passing fs_watch event data to a collection of listeners\n * @param fullPath absolute path bound to fs_watch instance\n */\nconst fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {\n const cont = FsWatchInstances.get(fullPath);\n if (!cont)\n return;\n foreach(cont[listenerType], (listener) => {\n listener(val1, val2, val3);\n });\n};\n/**\n * Instantiates the fs_watch interface or binds listeners\n * to an existing one covering the same file system entry\n * @param path\n * @param fullPath absolute path\n * @param options to be passed to fs_watch\n * @param handlers container for event listener functions\n */\nconst setFsWatchListener = (path, fullPath, options, handlers) => {\n const { listener, errHandler, rawEmitter } = handlers;\n let cont = FsWatchInstances.get(fullPath);\n let watcher;\n if (!options.persistent) {\n watcher = createFsWatchInstance(path, options, listener, errHandler, rawEmitter);\n if (!watcher)\n return;\n return watcher.close.bind(watcher);\n }\n if (cont) {\n addAndConvert(cont, KEY_LISTENERS, listener);\n addAndConvert(cont, KEY_ERR, errHandler);\n addAndConvert(cont, KEY_RAW, rawEmitter);\n }\n else {\n watcher = createFsWatchInstance(path, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, // no need to use broadcast here\n fsWatchBroadcast.bind(null, fullPath, KEY_RAW));\n if (!watcher)\n return;\n watcher.on(EV.ERROR, async (error) => {\n const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);\n if (cont)\n cont.watcherUnusable = true; // documented since Node 10.4.1\n // Workaround for https://github.com/joyent/node/issues/4337\n if (isWindows && error.code === 'EPERM') {\n try {\n const fd = await open(path, 'r');\n await fd.close();\n broadcastErr(error);\n }\n catch (err) {\n // do nothing\n }\n }\n else {\n broadcastErr(error);\n }\n });\n cont = {\n listeners: listener,\n errHandlers: errHandler,\n rawEmitters: rawEmitter,\n watcher,\n };\n FsWatchInstances.set(fullPath, cont);\n }\n // const index = cont.listeners.indexOf(listener);\n // removes this instance's listeners and closes the underlying fs_watch\n // instance if there are no more listeners left\n return () => {\n delFromSet(cont, KEY_LISTENERS, listener);\n delFromSet(cont, KEY_ERR, errHandler);\n delFromSet(cont, KEY_RAW, rawEmitter);\n if (isEmptySet(cont.listeners)) {\n // Check to protect against issue gh-730.\n // if (cont.watcherUnusable) {\n cont.watcher.close();\n // }\n FsWatchInstances.delete(fullPath);\n HANDLER_KEYS.forEach(clearItem(cont));\n // @ts-ignore\n cont.watcher = undefined;\n Object.freeze(cont);\n }\n };\n};\n// fs_watchFile helpers\n// object to hold per-process fs_watchFile instances\n// (may be shared across chokidar FSWatcher instances)\nconst FsWatchFileInstances = new Map();\n/**\n * Instantiates the fs_watchFile interface or binds listeners\n * to an existing one covering the same file system entry\n * @param path to be watched\n * @param fullPath absolute path\n * @param options options to be passed to fs_watchFile\n * @param handlers container for event listener functions\n * @returns closer\n */\nconst setFsWatchFileListener = (path, fullPath, options, handlers) => {\n const { listener, rawEmitter } = handlers;\n let cont = FsWatchFileInstances.get(fullPath);\n // let listeners = new Set();\n // let rawEmitters = new Set();\n const copts = cont && cont.options;\n if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {\n // \"Upgrade\" the watcher to persistence or a quicker interval.\n // This creates some unlikely edge case issues if the user mixes\n // settings in a very weird way, but solving for those cases\n // doesn't seem worthwhile for the added complexity.\n // listeners = cont.listeners;\n // rawEmitters = cont.rawEmitters;\n unwatchFile(fullPath);\n cont = undefined;\n }\n if (cont) {\n addAndConvert(cont, KEY_LISTENERS, listener);\n addAndConvert(cont, KEY_RAW, rawEmitter);\n }\n else {\n // TODO\n // listeners.add(listener);\n // rawEmitters.add(rawEmitter);\n cont = {\n listeners: listener,\n rawEmitters: rawEmitter,\n options,\n watcher: watchFile(fullPath, options, (curr, prev) => {\n foreach(cont.rawEmitters, (rawEmitter) => {\n rawEmitter(EV.CHANGE, fullPath, { curr, prev });\n });\n const currmtime = curr.mtimeMs;\n if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {\n foreach(cont.listeners, (listener) => listener(path, curr));\n }\n }),\n };\n FsWatchFileInstances.set(fullPath, cont);\n }\n // const index = cont.listeners.indexOf(listener);\n // Removes this instance's listeners and closes the underlying fs_watchFile\n // instance if there are no more listeners left.\n return () => {\n delFromSet(cont, KEY_LISTENERS, listener);\n delFromSet(cont, KEY_RAW, rawEmitter);\n if (isEmptySet(cont.listeners)) {\n FsWatchFileInstances.delete(fullPath);\n unwatchFile(fullPath);\n cont.options = cont.watcher = undefined;\n Object.freeze(cont);\n }\n };\n};\n/**\n * @mixin\n */\nexport class NodeFsHandler {\n fsw;\n _boundHandleError;\n constructor(fsW) {\n this.fsw = fsW;\n this._boundHandleError = (error) => fsW._handleError(error);\n }\n /**\n * Watch file for changes with fs_watchFile or fs_watch.\n * @param path to file or dir\n * @param listener on fs change\n * @returns closer for the watcher instance\n */\n _watchWithNodeFs(path, listener) {\n const opts = this.fsw.options;\n const directory = sp.dirname(path);\n const basename = sp.basename(path);\n const parent = this.fsw._getWatchedDir(directory);\n parent.add(basename);\n const absolutePath = sp.resolve(path);\n const options = {\n persistent: opts.persistent,\n };\n if (!listener)\n listener = EMPTY_FN;\n let closer;\n if (opts.usePolling) {\n const enableBin = opts.interval !== opts.binaryInterval;\n options.interval = enableBin && isBinaryPath(basename) ? opts.binaryInterval : opts.interval;\n closer = setFsWatchFileListener(path, absolutePath, options, {\n listener,\n rawEmitter: this.fsw._emitRaw,\n });\n }\n else {\n closer = setFsWatchListener(path, absolutePath, options, {\n listener,\n errHandler: this._boundHandleError,\n rawEmitter: this.fsw._emitRaw,\n });\n }\n return closer;\n }\n /**\n * Watch a file and emit add event if warranted.\n * @returns closer for the watcher instance\n */\n _handleFile(file, stats, initialAdd) {\n if (this.fsw.closed) {\n return;\n }\n const dirname = sp.dirname(file);\n const basename = sp.basename(file);\n const parent = this.fsw._getWatchedDir(dirname);\n // stats is always present\n let prevStats = stats;\n // if the file is already being watched, do nothing\n if (parent.has(basename))\n return;\n const listener = async (path, newStats) => {\n if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))\n return;\n if (!newStats || newStats.mtimeMs === 0) {\n try {\n const newStats = await stat(file);\n if (this.fsw.closed)\n return;\n // Check that change event was not fired because of changed only accessTime.\n const at = newStats.atimeMs;\n const mt = newStats.mtimeMs;\n if (!at || at <= mt || mt !== prevStats.mtimeMs) {\n this.fsw._emit(EV.CHANGE, file, newStats);\n }\n if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats.ino) {\n this.fsw._closeFile(path);\n prevStats = newStats;\n const closer = this._watchWithNodeFs(file, listener);\n if (closer)\n this.fsw._addPathCloser(path, closer);\n }\n else {\n prevStats = newStats;\n }\n }\n catch (error) {\n // Fix issues where mtime is null but file is still present\n this.fsw._remove(dirname, basename);\n }\n // add is about to be emitted if file not already tracked in parent\n }\n else if (parent.has(basename)) {\n // Check that change event was not fired because of changed only accessTime.\n const at = newStats.atimeMs;\n const mt = newStats.mtimeMs;\n if (!at || at <= mt || mt !== prevStats.mtimeMs) {\n this.fsw._emit(EV.CHANGE, file, newStats);\n }\n prevStats = newStats;\n }\n };\n // kick off the watcher\n const closer = this._watchWithNodeFs(file, listener);\n // emit an add event if we're supposed to\n if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {\n if (!this.fsw._throttle(EV.ADD, file, 0))\n return;\n this.fsw._emit(EV.ADD, file, stats);\n }\n return closer;\n }\n /**\n * Handle symlinks encountered while reading a dir.\n * @param entry returned by readdirp\n * @param directory path of dir being read\n * @param path of this item\n * @param item basename of this item\n * @returns true if no more processing is needed for this entry.\n */\n async _handleSymlink(entry, directory, path, item) {\n if (this.fsw.closed) {\n return;\n }\n const full = entry.fullPath;\n const dir = this.fsw._getWatchedDir(directory);\n if (!this.fsw.options.followSymlinks) {\n // watch symlink directly (don't follow) and detect changes\n this.fsw._incrReadyCount();\n let linkPath;\n try {\n linkPath = await fsrealpath(path);\n }\n catch (e) {\n this.fsw._emitReady();\n return true;\n }\n if (this.fsw.closed)\n return;\n if (dir.has(item)) {\n if (this.fsw._symlinkPaths.get(full) !== linkPath) {\n this.fsw._symlinkPaths.set(full, linkPath);\n this.fsw._emit(EV.CHANGE, path, entry.stats);\n }\n }\n else {\n dir.add(item);\n this.fsw._symlinkPaths.set(full, linkPath);\n this.fsw._emit(EV.ADD, path, entry.stats);\n }\n this.fsw._emitReady();\n return true;\n }\n // don't follow the same symlink more than once\n if (this.fsw._symlinkPaths.has(full)) {\n return true;\n }\n this.fsw._symlinkPaths.set(full, true);\n }\n _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {\n // Normalize the directory name on Windows\n directory = sp.join(directory, '');\n const throttleKey = target ? `${directory}:${target}` : directory;\n throttler = this.fsw._throttle('readdir', throttleKey, 1000);\n if (!throttler)\n return;\n const previous = this.fsw._getWatchedDir(wh.path);\n const current = new Set();\n let stream = this.fsw._readdirp(directory, {\n fileFilter: (entry) => wh.filterPath(entry),\n directoryFilter: (entry) => wh.filterDir(entry),\n });\n if (!stream)\n return;\n stream\n .on(STR_DATA, async (entry) => {\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n const item = entry.path;\n let path = sp.join(directory, item);\n current.add(item);\n if (entry.stats.isSymbolicLink() &&\n (await this._handleSymlink(entry, directory, path, item))) {\n return;\n }\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n // Files that present in current directory snapshot\n // but absent in previous are added to watch list and\n // emit `add` event.\n if (item === target || (!target && !previous.has(item))) {\n this.fsw._incrReadyCount();\n // ensure relativeness of path is preserved in case of watcher reuse\n path = sp.join(dir, sp.relative(dir, path));\n this._addToNodeFs(path, initialAdd, wh, depth + 1);\n }\n })\n .on(EV.ERROR, this._boundHandleError);\n return new Promise((resolve, reject) => {\n if (!stream)\n return reject();\n stream.once(STR_END, () => {\n if (this.fsw.closed) {\n stream = undefined;\n return;\n }\n const wasThrottled = throttler ? throttler.clear() : false;\n resolve(undefined);\n // Files that absent in current directory snapshot\n // but present in previous emit `remove` event\n // and are removed from @watched[directory].\n previous\n .getChildren()\n .filter((item) => {\n return item !== directory && !current.has(item);\n })\n .forEach((item) => {\n this.fsw._remove(directory, item);\n });\n stream = undefined;\n // one more time for any missed in case changes came in extremely quickly\n if (wasThrottled)\n this._handleRead(directory, false, wh, target, dir, depth, throttler);\n });\n });\n }\n /**\n * Read directory to add / remove files from `@watched` list and re-read it on change.\n * @param dir fs path\n * @param stats\n * @param initialAdd\n * @param depth relative to user-supplied path\n * @param target child path targeted for watch\n * @param wh Common watch helpers for this path\n * @param realpath\n * @returns closer for the watcher instance.\n */\n async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {\n const parentDir = this.fsw._getWatchedDir(sp.dirname(dir));\n const tracked = parentDir.has(sp.basename(dir));\n if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {\n this.fsw._emit(EV.ADD_DIR, dir, stats);\n }\n // ensure dir is tracked (harmless if redundant)\n parentDir.add(sp.basename(dir));\n this.fsw._getWatchedDir(dir);\n let throttler;\n let closer;\n const oDepth = this.fsw.options.depth;\n if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {\n if (!target) {\n await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);\n if (this.fsw.closed)\n return;\n }\n closer = this._watchWithNodeFs(dir, (dirPath, stats) => {\n // if current directory is removed, do nothing\n if (stats && stats.mtimeMs === 0)\n return;\n this._handleRead(dirPath, false, wh, target, dir, depth, throttler);\n });\n }\n return closer;\n }\n /**\n * Handle added file, directory, or glob pattern.\n * Delegates call to _handleFile / _handleDir after checks.\n * @param path to file or ir\n * @param initialAdd was the file added at watch instantiation?\n * @param priorWh depth relative to user-supplied path\n * @param depth Child path actually targeted for watch\n * @param target Child path actually targeted for watch\n */\n async _addToNodeFs(path, initialAdd, priorWh, depth, target) {\n const ready = this.fsw._emitReady;\n if (this.fsw._isIgnored(path) || this.fsw.closed) {\n ready();\n return false;\n }\n const wh = this.fsw._getWatchHelpers(path);\n if (priorWh) {\n wh.filterPath = (entry) => priorWh.filterPath(entry);\n wh.filterDir = (entry) => priorWh.filterDir(entry);\n }\n // evaluate what is at the path we're being asked to watch\n try {\n const stats = await statMethods[wh.statMethod](wh.watchPath);\n if (this.fsw.closed)\n return;\n if (this.fsw._isIgnored(wh.watchPath, stats)) {\n ready();\n return false;\n }\n const follow = this.fsw.options.followSymlinks;\n let closer;\n if (stats.isDirectory()) {\n const absPath = sp.resolve(path);\n const targetPath = follow ? await fsrealpath(path) : path;\n if (this.fsw.closed)\n return;\n closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);\n if (this.fsw.closed)\n return;\n // preserve this symlink's target path\n if (absPath !== targetPath && targetPath !== undefined) {\n this.fsw._symlinkPaths.set(absPath, targetPath);\n }\n }\n else if (stats.isSymbolicLink()) {\n const targetPath = follow ? await fsrealpath(path) : path;\n if (this.fsw.closed)\n return;\n const parent = sp.dirname(wh.watchPath);\n this.fsw._getWatchedDir(parent).add(wh.watchPath);\n this.fsw._emit(EV.ADD, wh.watchPath, stats);\n closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);\n if (this.fsw.closed)\n return;\n // preserve this symlink's target path\n if (targetPath !== undefined) {\n this.fsw._symlinkPaths.set(sp.resolve(path), targetPath);\n }\n }\n else {\n closer = this._handleFile(wh.watchPath, stats, initialAdd);\n }\n ready();\n if (closer)\n this.fsw._addPathCloser(path, closer);\n return false;\n }\n catch (error) {\n if (this.fsw._handleError(error)) {\n ready();\n return path;\n }\n }\n }\n}\n","export const balanced = (\n a: string | RegExp,\n b: string | RegExp,\n str: string,\n) => {\n const ma = a instanceof RegExp ? maybeMatch(a, str) : a\n const mb = b instanceof RegExp ? maybeMatch(b, str) : b\n\n const r = ma !== null && mb != null && range(ma, mb, str)\n\n return (\n r && {\n start: r[0],\n end: r[1],\n pre: str.slice(0, r[0]),\n body: str.slice(r[0] + ma.length, r[1]),\n post: str.slice(r[1] + mb.length),\n }\n )\n}\n\nconst maybeMatch = (reg: RegExp, str: string) => {\n const m = str.match(reg)\n return m ? m[0] : null\n}\n\nexport const range = (\n a: string,\n b: string,\n str: string,\n): undefined | [number, number] => {\n let begs: number[],\n beg: number | undefined,\n left: number,\n right: number | undefined = undefined,\n result: undefined | [number, number]\n let ai = str.indexOf(a)\n let bi = str.indexOf(b, ai + 1)\n let i = ai\n\n if (ai >= 0 && bi > 0) {\n if (a === b) {\n return [ai, bi]\n }\n begs = []\n left = str.length\n\n while (i >= 0 && !result) {\n if (i === ai) {\n begs.push(i)\n ai = str.indexOf(a, i + 1)\n } else if (begs.length === 1) {\n const r = begs.pop()\n if (r !== undefined) result = [r, bi]\n } else {\n beg = begs.pop()\n if (beg !== undefined && beg < left) {\n left = beg\n right = bi\n }\n\n bi = str.indexOf(b, i + 1)\n }\n\n i = ai < bi && ai >= 0 ? ai : bi\n }\n\n if (begs.length && right !== undefined) {\n result = [left, right]\n }\n }\n\n return result\n}\n","import { balanced } from 'balanced-match'\n\nconst escSlash = '\\0SLASH' + Math.random() + '\\0'\nconst escOpen = '\\0OPEN' + Math.random() + '\\0'\nconst escClose = '\\0CLOSE' + Math.random() + '\\0'\nconst escComma = '\\0COMMA' + Math.random() + '\\0'\nconst escPeriod = '\\0PERIOD' + Math.random() + '\\0'\nconst escSlashPattern = new RegExp(escSlash, 'g')\nconst escOpenPattern = new RegExp(escOpen, 'g')\nconst escClosePattern = new RegExp(escClose, 'g')\nconst escCommaPattern = new RegExp(escComma, 'g')\nconst escPeriodPattern = new RegExp(escPeriod, 'g')\nconst slashPattern = /\\\\\\\\/g\nconst openPattern = /\\\\{/g\nconst closePattern = /\\\\}/g\nconst commaPattern = /\\\\,/g\nconst periodPattern = /\\\\\\./g\n\nexport const EXPANSION_MAX = 100_000\n\n// `EXPANSION_MAX` caps the *number* of expansions, but not their length. An\n// input like `'{a,b}'.repeat(1500)` stays under that count - its output is\n// truncated to 100k results - while making every result ~1500 characters\n// long. The result set, and the intermediate arrays built while combining\n// brace sets, then grow large enough to exhaust memory and crash the process\n// (CVE-2026-14257). `EXPANSION_MAX_LENGTH` bounds the total number of\n// characters the accumulator may hold at any point, so memory stays flat no\n// matter how many brace groups are chained. The limit sits well above any\n// realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M\n// characters) so legitimate input is unaffected.\nexport const EXPANSION_MAX_LENGTH = 4_000_000\n\nfunction numeric(str: string) {\n return !isNaN(str as any) ? parseInt(str, 10) : str.charCodeAt(0)\n}\n\nfunction escapeBraces(str: string) {\n return str\n .replace(slashPattern, escSlash)\n .replace(openPattern, escOpen)\n .replace(closePattern, escClose)\n .replace(commaPattern, escComma)\n .replace(periodPattern, escPeriod)\n}\n\nfunction unescapeBraces(str: string) {\n return str\n .replace(escSlashPattern, '\\\\')\n .replace(escOpenPattern, '{')\n .replace(escClosePattern, '}')\n .replace(escCommaPattern, ',')\n .replace(escPeriodPattern, '.')\n}\n\n/**\n * Basically just str.split(\",\"), but handling cases\n * where we have nested braced sections, which should be\n * treated as individual members, like {a,{b,c},d}\n */\nfunction parseCommaParts(str: string) {\n if (!str) {\n return ['']\n }\n\n const parts: string[] = []\n const m = balanced('{', '}', str)\n\n if (!m) {\n return str.split(',')\n }\n\n const { pre, body, post } = m\n const p = pre.split(',')\n\n p[p.length - 1] += '{' + body + '}'\n const postParts = parseCommaParts(post)\n if (post.length) {\n ;(p[p.length - 1] as string) += postParts.shift()\n p.push.apply(p, postParts)\n }\n\n parts.push.apply(parts, p)\n\n return parts\n}\n\nexport type BraceExpansionOptions = {\n max?: number\n maxLength?: number\n}\n\nexport function expand(str: string, options: BraceExpansionOptions = {}) {\n if (!str) {\n return []\n }\n\n const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH } = options\n\n // I don't know why Bash 4.3 does this, but it does.\n // Anything starting with {} will have the first two bytes preserved\n // but *only* at the top level, so {},a}b will not expand to anything,\n // but a{},b}c will be expanded to [a}c,abc].\n // One could argue that this is a bug in Bash, but since the goal of\n // this module is to match Bash's rules, we escape a leading {}\n if (str.slice(0, 2) === '{}') {\n str = '\\\\{\\\\}' + str.slice(2)\n }\n\n return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces)\n}\n\nfunction embrace(str: string) {\n return '{' + str + '}'\n}\n\nfunction isPadded(el: string) {\n return /^-?0\\d/.test(el)\n}\n\nfunction lte(i: number, y: number) {\n return i <= y\n}\n\nfunction gte(i: number, y: number) {\n return i >= y\n}\n\n// Build `{ acc[a] + pre + values[v] }` for every combination, capping the\n// number of results at `max` and the total number of characters at `maxLength`.\n// This is the one place output grows, so bounding it here keeps the single\n// accumulator - and therefore memory - flat regardless of how many brace groups\n// are combined (CVE-2026-14257).\nfunction combine(\n acc: string[],\n pre: string,\n values: string[],\n max: number,\n maxLength: number,\n dropEmpties: boolean,\n): string[] {\n const out: string[] = []\n let length = 0\n for (let a = 0; a < acc.length; a++) {\n for (let v = 0; v < values.length; v++) {\n if (out.length >= max) return out\n const expansion = (acc[a] as string) + pre + values[v]\n // Bash drops empty results at the top level. Skip them before they count\n // against `max`, so `max` bounds the number of *kept* results.\n if (dropEmpties && !expansion) continue\n if (length + expansion.length > maxLength) return out\n out.push(expansion)\n length += expansion.length\n }\n }\n return out\n}\n\n// The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)\n// sequence body.\nfunction expandSequence(\n body: string,\n isAlphaSequence: boolean,\n max: number,\n maxLength: number,\n): string[] {\n const n = body.split(/\\.\\./)\n const N: string[] = []\n // A sequence body always splits into two or three parts, but the compiler\n // can't know that.\n /* c8 ignore start */\n if (n[0] === undefined || n[1] === undefined) {\n return N\n }\n /* c8 ignore stop */\n const x = numeric(n[0])\n const y = numeric(n[1])\n const width = Math.max(n[0].length, n[1].length)\n let incr =\n n.length === 3 && n[2] !== undefined ?\n Math.max(Math.abs(numeric(n[2])), 1)\n : 1\n let test = lte\n const reverse = y < x\n if (reverse) {\n incr *= -1\n test = gte\n }\n const pad = n.some(isPadded)\n\n let length = 0\n for (let i = x; test(i, y) && N.length < max; i += incr) {\n let c\n if (isAlphaSequence) {\n c = String.fromCharCode(i)\n if (c === '\\\\') {\n c = ''\n }\n } else {\n c = String(i)\n if (pad) {\n const need = width - c.length\n if (need > 0) {\n const z = new Array(need + 1).join('0')\n if (i < 0) {\n c = '-' + z + c.slice(1)\n } else {\n c = z + c\n }\n }\n }\n }\n if (length + c.length > maxLength) break\n N.push(c)\n length += c.length\n }\n return N\n}\n\nfunction expand_(\n str: string,\n max: number,\n maxLength: number,\n isTop: boolean,\n): string[] {\n // Consume the string's top-level brace groups left to right, threading a\n // running set of combined prefixes (`acc`). Expanding the tail iteratively -\n // rather than recursing on `m.post` once per group - keeps the native stack\n // depth constant, so deeply chained input (`'{a,b}'.repeat(3000)`) can no\n // longer overflow the stack, and leaves a single accumulator whose size\n // `maxLength` bounds directly (CVE-2026-14257).\n let acc: string[] = ['']\n\n // Bash drops empty results, but only when the *first* top-level group is a\n // comma set - a sequence like `{a..\\}` may legitimately yield ''. The drop\n // is on the final strings, so it is applied to whichever `combine` produces\n // them (the one with no brace set left in the tail).\n let dropEmpties = false\n let firstGroup = true\n\n for (;;) {\n const m = balanced('{', '}', str)\n\n // No brace set left: the rest of the string is literal.\n if (!m) {\n return combine(acc, str, [''], max, maxLength, dropEmpties)\n }\n\n // no need to expand pre, since it is guaranteed to be free of brace-sets\n const pre = m.pre\n\n if (/\\$$/.test(pre)) {\n acc = combine(\n acc,\n pre + '{' + m.body + '}',\n [''],\n max,\n maxLength,\n dropEmpties && !m.post.length,\n )\n firstGroup = false\n if (!m.post.length) break\n str = m.post\n continue\n }\n\n const isNumericSequence = /^-?\\d+\\.\\.-?\\d+(?:\\.\\.-?\\d+)?$/.test(m.body)\n const isAlphaSequence = /^[a-zA-Z]\\.\\.[a-zA-Z](?:\\.\\.-?\\d+)?$/.test(\n m.body,\n )\n const isSequence = isNumericSequence || isAlphaSequence\n const isOptions = m.body.indexOf(',') >= 0\n if (!isSequence && !isOptions) {\n // {a},b}\n if (m.post.match(/,(?!,).*\\}/)) {\n str = m.pre + '{' + m.body + escClose + m.post\n isTop = true\n continue\n }\n // Nothing here expands, so the whole remaining string is literal.\n return combine(\n acc,\n pre + '{' + m.body + '}' + m.post,\n [''],\n max,\n maxLength,\n dropEmpties,\n )\n }\n\n if (firstGroup) {\n dropEmpties = isTop && !isSequence\n firstGroup = false\n }\n\n let values: string[]\n if (isSequence) {\n values = expandSequence(m.body, isAlphaSequence, max, maxLength)\n } else {\n let n = parseCommaParts(m.body)\n if (n.length === 1 && n[0] !== undefined) {\n // x{{a,b}}y ==> x{a}y x{b}y\n n = expand_(n[0], max, maxLength, false).map(embrace)\n //XXX is this necessary? Can't seem to hit it in tests.\n /* c8 ignore start */\n if (n.length === 1) {\n acc = combine(\n acc,\n pre + n[0],\n [''],\n max,\n maxLength,\n dropEmpties && !m.post.length,\n )\n if (!m.post.length) break\n str = m.post\n continue\n }\n /* c8 ignore stop */\n }\n\n // Values that `combine` is going to drop as empty produce no result, so\n // they must not count against `max` - otherwise `{a,,b}` with `max: 2`\n // would stop at `['a', '']` and yield one result instead of two. Skipping\n // them outright keeps `values` bounded while leaving `max` a bound on\n // *kept* results.\n let dropsEmpties = dropEmpties && !m.post.length && !pre\n for (let d = 0; dropsEmpties && d < acc.length; d++) {\n if (acc[d]) {\n dropsEmpties = false\n }\n }\n\n values = []\n let valuesLength = 0\n outer: for (let j = 0; j < n.length; j++) {\n const expanded = expand_(n[j] as string, max, maxLength, false)\n for (let k = 0; k < expanded.length; k++) {\n const v = expanded[k] as string\n if (dropsEmpties && !v) continue\n if (values.length >= max || valuesLength + v.length > maxLength) {\n break outer\n }\n values.push(v)\n valuesLength += v.length\n }\n }\n }\n\n acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length)\n if (!m.post.length) break\n str = m.post\n }\n\n return acc\n}\n","const MAX_PATTERN_LENGTH = 1024 * 64\nexport const assertValidPattern: (pattern: unknown) => void = (\n pattern: unknown,\n): asserts pattern is string => {\n if (typeof pattern !== 'string') {\n throw new TypeError('invalid pattern')\n }\n\n if (pattern.length > MAX_PATTERN_LENGTH) {\n throw new TypeError('pattern is too long')\n }\n}\n","// translate the various posix character classes into unicode properties\n// this works across all unicode locales\n\n// { <posix class>: [<translation>, /u flag required, negated]\nconst posixClasses: { [k: string]: [e: string, u: boolean, n?: boolean] } =\n {\n '[:alnum:]': ['\\\\p{L}\\\\p{Nl}\\\\p{Nd}', true],\n '[:alpha:]': ['\\\\p{L}\\\\p{Nl}', true],\n '[:ascii:]': ['\\\\x' + '00-\\\\x' + '7f', false],\n '[:blank:]': ['\\\\p{Zs}\\\\t', true],\n '[:cntrl:]': ['\\\\p{Cc}', true],\n '[:digit:]': ['\\\\p{Nd}', true],\n '[:graph:]': ['\\\\p{Z}\\\\p{C}', true, true],\n '[:lower:]': ['\\\\p{Ll}', true],\n '[:print:]': ['\\\\p{C}', true],\n '[:punct:]': ['\\\\p{P}', true],\n '[:space:]': ['\\\\p{Z}\\\\t\\\\r\\\\n\\\\v\\\\f', true],\n '[:upper:]': ['\\\\p{Lu}', true],\n '[:word:]': ['\\\\p{L}\\\\p{Nl}\\\\p{Nd}\\\\p{Pc}', true],\n '[:xdigit:]': ['A-Fa-f0-9', false],\n }\n\n// only need to escape a few things inside of brace expressions\n// escapes: [ \\ ] -\nconst braceEscape = (s: string) => s.replace(/[[\\]\\\\-]/g, '\\\\$&')\n// escape all regexp magic characters\nconst regexpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\n// everything has already been escaped, we just have to join\nconst rangesToString = (ranges: string[]): string => ranges.join('')\n\nexport type ParseClassResult = [\n src: string,\n uFlag: boolean,\n consumed: number,\n hasMagic: boolean,\n]\n\n// takes a glob string at a posix brace expression, and returns\n// an equivalent regular expression source, and boolean indicating\n// whether the /u flag needs to be applied, and the number of chars\n// consumed to parse the character class.\n// This also removes out of order ranges, and returns ($.) if the\n// entire class just no good.\nexport const parseClass = (\n glob: string,\n position: number,\n): ParseClassResult => {\n const pos = position\n /* c8 ignore start */\n if (glob.charAt(pos) !== '[') {\n throw new Error('not in a brace expression')\n }\n /* c8 ignore stop */\n const ranges: string[] = []\n const negs: string[] = []\n\n let i = pos + 1\n let sawStart = false\n let uflag = false\n let escaping = false\n let negate = false\n let endPos = pos\n let rangeStart = ''\n WHILE: while (i < glob.length) {\n const c = glob.charAt(i)\n if ((c === '!' || c === '^') && i === pos + 1) {\n negate = true\n i++\n continue\n }\n\n if (c === ']' && sawStart && !escaping) {\n endPos = i + 1\n break\n }\n\n sawStart = true\n if (c === '\\\\') {\n if (!escaping) {\n escaping = true\n i++\n continue\n }\n // escaped \\ char, fall through and treat like normal char\n }\n if (c === '[' && !escaping) {\n // either a posix class, a collation equivalent, or just a [\n for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {\n if (glob.startsWith(cls, i)) {\n // invalid, [a-[] is fine, but not [a-[:alpha]]\n if (rangeStart) {\n return ['$.', false, glob.length - pos, true]\n }\n i += cls.length\n if (neg) negs.push(unip)\n else ranges.push(unip)\n uflag = uflag || u\n continue WHILE\n }\n }\n }\n\n // now it's just a normal character, effectively\n escaping = false\n if (rangeStart) {\n // throw this range away if it's not valid, but others\n // can still match.\n if (c > rangeStart) {\n ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c))\n } else if (c === rangeStart) {\n ranges.push(braceEscape(c))\n }\n rangeStart = ''\n i++\n continue\n }\n\n // now might be the start of a range.\n // can be either c-d or c-] or c<more...>] or c] at this point\n if (glob.startsWith('-]', i + 1)) {\n ranges.push(braceEscape(c + '-'))\n i += 2\n continue\n }\n if (glob.startsWith('-', i + 1)) {\n rangeStart = c\n i += 2\n continue\n }\n\n // not the start of a range, just a single character\n ranges.push(braceEscape(c))\n i++\n }\n\n if (endPos < i) {\n // didn't see the end of the class, not a valid class,\n // but might still be valid as a literal match.\n return ['', false, 0, false]\n }\n\n // if we got no ranges and no negates, then we have a range that\n // cannot possibly match anything, and that poisons the whole glob\n if (!ranges.length && !negs.length) {\n return ['$.', false, glob.length - pos, true]\n }\n\n // if we got one positive range, and it's a single character, then that's\n // not actually a magic pattern, it's just that one literal character.\n // we should not treat that as \"magic\", we should just return the literal\n // character. [_] is a perfectly valid way to escape glob magic chars.\n if (\n negs.length === 0 &&\n ranges.length === 1 &&\n /^\\\\?.$/.test(ranges[0]) &&\n !negate\n ) {\n const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0]\n return [regexpEscape(r), false, endPos - pos, false]\n }\n\n const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']'\n const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']'\n const comb =\n ranges.length && negs.length ? '(' + sranges + '|' + snegs + ')'\n : ranges.length ? sranges\n : snegs\n\n return [comb, uflag, endPos - pos, true]\n}\n","import type { MinimatchOptions } from './index.js'\n\n/**\n * Un-escape a string that has been escaped with {@link escape}.\n *\n * If the {@link MinimatchOptions.windowsPathsNoEscape} option is used, then\n * square-bracket escapes are removed, but not backslash escapes.\n *\n * For example, it will turn the string `'[*]'` into `*`, but it will not\n * turn `'\\\\*'` into `'*'`, because `\\` is a path separator in\n * `windowsPathsNoEscape` mode.\n *\n * When `windowsPathsNoEscape` is not set, then both square-bracket escapes and\n * backslash escapes are removed.\n *\n * Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped\n * or unescaped.\n *\n * When `magicalBraces` is not set, escapes of braces (`{` and `}`) will not be\n * unescaped.\n */\n\nexport const unescape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n magicalBraces = true,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape' | 'magicalBraces'> = {},\n) => {\n if (magicalBraces) {\n return windowsPathsNoEscape ?\n s.replace(/\\[([^/\\\\])\\]/g, '$1')\n : s\n .replace(/((?!\\\\).|^)\\[([^/\\\\])\\]/g, '$1$2')\n .replace(/\\\\([^/])/g, '$1')\n }\n return windowsPathsNoEscape ?\n s.replace(/\\[([^/\\\\{}])\\]/g, '$1')\n : s\n .replace(/((?!\\\\).|^)\\[([^/\\\\{}])\\]/g, '$1$2')\n .replace(/\\\\([^/{}])/g, '$1')\n}\n","// parse a single path portion\n\nimport { parseClass } from './brace-expressions.js'\nimport type { MinimatchOptions, MMRegExp } from './index.js'\nimport { unescape } from './unescape.js'\n\n// classes [] are handled by the parseClass method\n// for positive extglobs, we sub-parse the contents, and combine,\n// with the appropriate regexp close.\n// for negative extglobs, we sub-parse the contents, but then\n// have to include the rest of the pattern, then the parent, etc.,\n// as the thing that cannot be because RegExp negative lookaheads\n// are different from globs.\n//\n// So for example:\n// a@(i|w!(x|y)z|j)b => ^a(i|w((!?(x|y)zb).*)z|j)b$\n// 1 2 3 4 5 6 1 2 3 46 5 6\n//\n// Assembling the extglob requires not just the negated patterns themselves,\n// but also anything following the negative patterns up to the boundary\n// of the current pattern, plus anything following in the parent pattern.\n//\n//\n// So, first, we parse the string into an AST of extglobs, without turning\n// anything into regexps yet.\n//\n// ['a', {@ [['i'], ['w', {!['x', 'y']}, 'z'], ['j']]}, 'b']\n//\n// Then, for all the negative extglobs, we append whatever comes after in\n// each parent as their tail\n//\n// ['a', {@ [['i'], ['w', {!['x', 'y'], 'z', 'b'}, 'z'], ['j']]}, 'b']\n//\n// Lastly, we turn each of these pieces into a regexp, and join\n//\n// v----- .* because there's more following,\n// v v otherwise, .+ because it must be\n// v v *something* there.\n// ['^a', {@ ['i', 'w(?:(!?(?:x|y).*zb$).*)z', 'j' ]}, 'b$']\n// copy what follows into here--^^^^^\n// ['^a', '(?:i|w(?:(?!(?:x|y).*zb$).*)z|j)', 'b$']\n// ['^a(?:i|w(?:(?!(?:x|y).*zb$).*)z|j)b$']\n\nexport type ExtglobType = '!' | '?' | '+' | '*' | '@'\nconst types = new Set<ExtglobType>(['!', '?', '+', '*', '@'])\nconst isExtglobType = (c: string | null): c is ExtglobType =>\n types.has(c as ExtglobType)\nconst isExtglobAST = (c: AST): c is AST & { type: ExtglobType } =>\n isExtglobType(c.type)\n\n// Map of which extglob types can adopt the children of a nested extglob\n//\n// anything but ! can adopt a matching type:\n// +(a|+(b|c)|d) => +(a|b|c|d)\n// *(a|*(b|c)|d) => *(a|b|c|d)\n// @(a|@(b|c)|d) => @(a|b|c|d)\n// ?(a|?(b|c)|d) => ?(a|b|c|d)\n//\n// * can adopt anything, because 0 or repetition is allowed\n// *(a|?(b|c)|d) => *(a|b|c|d)\n// *(a|+(b|c)|d) => *(a|b|c|d)\n// *(a|@(b|c)|d) => *(a|b|c|d)\n//\n// + can adopt @, because 1 or repetition is allowed\n// +(a|@(b|c)|d) => +(a|b|c|d)\n//\n// + and @ CANNOT adopt *, because 0 would be allowed\n// +(a|*(b|c)|d) => would match \"\", on *(b|c)\n// @(a|*(b|c)|d) => would match \"\", on *(b|c)\n//\n// + and @ CANNOT adopt ?, because 0 would be allowed\n// +(a|?(b|c)|d) => would match \"\", on ?(b|c)\n// @(a|?(b|c)|d) => would match \"\", on ?(b|c)\n//\n// ? can adopt @, because 0 or 1 is allowed\n// ?(a|@(b|c)|d) => ?(a|b|c|d)\n//\n// ? and @ CANNOT adopt * or +, because >1 would be allowed\n// ?(a|*(b|c)|d) => would match bbb on *(b|c)\n// @(a|*(b|c)|d) => would match bbb on *(b|c)\n// ?(a|+(b|c)|d) => would match bbb on +(b|c)\n// @(a|+(b|c)|d) => would match bbb on +(b|c)\n//\n// ! CANNOT adopt ! (nothing else can either)\n// !(a|!(b|c)|d) => !(a|b|c|d) would fail to match on b (not not b|c)\n//\n// ! can adopt @\n// !(a|@(b|c)|d) => !(a|b|c|d)\n//\n// ! CANNOT adopt *\n// !(a|*(b|c)|d) => !(a|b|c|d) would match on bbb, not allowed\n//\n// ! CANNOT adopt +\n// !(a|+(b|c)|d) => !(a|b|c|d) would match on bbb, not allowed\n//\n// ! CANNOT adopt ?\n// x!(a|?(b|c)|d) => x!(a|b|c|d) would fail to match \"x\"\nconst adoptionMap = new Map<ExtglobType, ExtglobType[]>([\n ['!', ['@']],\n ['?', ['?', '@']],\n ['@', ['@']],\n ['*', ['*', '+', '?', '@']],\n ['+', ['+', '@']],\n])\n\n// nested extglobs that can be adopted in, but with the addition of\n// a blank '' element.\nconst adoptionWithSpaceMap = new Map<ExtglobType, ExtglobType[]>([\n ['!', ['?']],\n ['@', ['?']],\n ['+', ['?', '*']],\n])\n\n// union of the previous two maps\nconst adoptionAnyMap = new Map<ExtglobType, ExtglobType[]>([\n ['!', ['?', '@']],\n ['?', ['?', '@']],\n ['@', ['?', '@']],\n ['*', ['*', '+', '?', '@']],\n ['+', ['+', '@', '?', '*']],\n])\n\n// Extglobs that can take over their parent if they are the only child\n// the key is parent, value maps child to resulting extglob parent type\n// '@' is omitted because it's a special case. An `@` extglob with a single\n// member can always be usurped by that subpattern.\nconst usurpMap = new Map<\n ExtglobType,\n Map<ExtglobType | null, ExtglobType | null>\n>([\n ['!', new Map([['!', '@']])],\n [\n '?',\n new Map([\n ['*', '*'],\n ['+', '*'],\n ]),\n ],\n [\n '@',\n new Map([\n ['!', '!'],\n ['?', '?'],\n ['@', '@'],\n ['*', '*'],\n ['+', '+'],\n ]),\n ],\n [\n '+',\n new Map([\n ['?', '*'],\n ['*', '*'],\n ]),\n ],\n])\n\n// Patterns that get prepended to bind to the start of either the\n// entire string, or just a single path portion, to prevent dots\n// and/or traversal patterns, when needed.\n// Exts don't need the ^ or / bit, because the root binds that already.\nconst startNoTraversal = '(?!(?:^|/)\\\\.\\\\.?(?:$|/))'\nconst startNoDot = '(?!\\\\.)'\n\n// characters that indicate a start of pattern needs the \"no dots\" bit,\n// because a dot *might* be matched. ( is not in the list, because in\n// the case of a child extglob, it will handle the prevention itself.\nconst addPatternStart = new Set(['[', '.'])\n// cases where traversal is A-OK, no dot prevention needed\nconst justDots = new Set(['..', '.'])\nconst reSpecials = new Set('().*{}+?[]^$\\\\!')\nconst regExpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\n// any single thing other than /\nconst qmark = '[^/]'\n\n// * => any number of characters\nconst star = qmark + '*?'\n// use + when we need to ensure that *something* matches, because the * is\n// the only thing in the path portion.\nconst starNoEmpty = qmark + '+?'\n\n// remove the \\ chars that we added if we end up doing a nonmagic compare\n// const deslash = (s: string) => s.replace(/\\\\(.)/g, '$1')\n\nlet ID = 0\nexport class AST {\n type: ExtglobType | null\n readonly #root: AST\n\n #hasMagic?: boolean\n #uflag: boolean = false\n #parts: (string | AST)[] = []\n #parent?: AST\n #parentIndex: number\n #negs: AST[]\n #filledNegs: boolean = false\n #options: MinimatchOptions\n #toString?: string\n // set to true if it's an extglob with no children\n // (which really means one child of '')\n #emptyExt: boolean = false\n id = ++ID\n\n get depth(): number {\n return (this.#parent?.depth ?? -1) + 1\n }\n\n [Symbol.for('nodejs.util.inspect.custom')]() {\n return {\n '@@type': 'AST',\n id: this.id,\n type: this.type,\n root: this.#root.id,\n parent: this.#parent?.id,\n depth: this.depth,\n partsLength: this.#parts.length,\n parts: this.#parts,\n }\n }\n\n constructor(\n type: ExtglobType | null,\n parent?: AST,\n options: MinimatchOptions = {},\n ) {\n this.type = type\n // extglobs are inherently magical\n if (type) this.#hasMagic = true\n this.#parent = parent\n this.#root = this.#parent ? this.#parent.#root : this\n this.#options = this.#root === this ? options : this.#root.#options\n this.#negs = this.#root === this ? [] : this.#root.#negs\n if (type === '!' && !this.#root.#filledNegs) this.#negs.push(this)\n this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0\n }\n\n get hasMagic(): boolean | undefined {\n /* c8 ignore start */\n if (this.#hasMagic !== undefined) return this.#hasMagic\n /* c8 ignore stop */\n for (const p of this.#parts) {\n if (typeof p === 'string') continue\n if (p.type || p.hasMagic) return (this.#hasMagic = true)\n }\n // note: will be undefined until we generate the regexp src and find out\n return this.#hasMagic\n }\n\n // reconstructs the pattern\n toString(): string {\n return (\n this.#toString !== undefined ? this.#toString\n : !this.type ?\n (this.#toString = this.#parts.map(p => String(p)).join(''))\n : (this.#toString =\n this.type +\n '(' +\n this.#parts.map(p => String(p)).join('|') +\n ')')\n )\n }\n\n #fillNegs() {\n /* c8 ignore start */\n if (this !== this.#root) throw new Error('should only call on root')\n if (this.#filledNegs) return this\n /* c8 ignore stop */\n\n // call toString() once to fill this out\n this.toString()\n this.#filledNegs = true\n let n: AST | undefined\n while ((n = this.#negs.pop())) {\n if (n.type !== '!') continue\n // walk up the tree, appending everthing that comes AFTER parentIndex\n let p: AST | undefined = n\n let pp = p.#parent\n while (pp) {\n for (\n let i = p.#parentIndex + 1;\n !pp.type && i < pp.#parts.length;\n i++\n ) {\n for (const part of n.#parts) {\n /* c8 ignore start */\n if (typeof part === 'string') {\n throw new Error('string part in extglob AST??')\n }\n /* c8 ignore stop */\n part.copyIn(pp.#parts[i])\n }\n }\n p = pp\n pp = p.#parent\n }\n }\n return this\n }\n\n push(...parts: (string | AST)[]) {\n for (const p of parts) {\n if (p === '') continue\n /* c8 ignore start */\n if (\n typeof p !== 'string' &&\n !(p instanceof AST && p.#parent === this)\n ) {\n throw new Error('invalid part: ' + p)\n }\n /* c8 ignore stop */\n this.#parts.push(p)\n }\n }\n\n toJSON() {\n const ret: unknown[] =\n this.type === null ?\n this.#parts\n .slice()\n .map(p => (typeof p === 'string' ? p : p.toJSON()))\n : [this.type, ...this.#parts.map(p => (p as AST).toJSON())]\n if (this.isStart() && !this.type) ret.unshift([])\n if (\n this.isEnd() &&\n (this === this.#root ||\n (this.#root.#filledNegs && this.#parent?.type === '!'))\n ) {\n ret.push({})\n }\n return ret\n }\n\n isStart(): boolean {\n if (this.#root === this) return true\n // if (this.type) return !!this.#parent?.isStart()\n if (!this.#parent?.isStart()) return false\n if (this.#parentIndex === 0) return true\n // if everything AHEAD of this is a negation, then it's still the \"start\"\n const p = this.#parent\n for (let i = 0; i < this.#parentIndex; i++) {\n const pp = p.#parts[i]\n if (!(pp instanceof AST && pp.type === '!')) {\n return false\n }\n }\n return true\n }\n\n isEnd(): boolean {\n if (this.#root === this) return true\n if (this.#parent?.type === '!') return true\n if (!this.#parent?.isEnd()) return false\n if (!this.type) return this.#parent?.isEnd()\n // if not root, it'll always have a parent\n /* c8 ignore start */\n const pl = this.#parent ? this.#parent.#parts.length : 0\n /* c8 ignore stop */\n return this.#parentIndex === pl - 1\n }\n\n copyIn(part: AST | string) {\n if (typeof part === 'string') this.push(part)\n else this.push(part.clone(this))\n }\n\n clone(parent: AST) {\n const c = new AST(this.type, parent)\n for (const p of this.#parts) {\n c.copyIn(p)\n }\n return c\n }\n\n static #parseAST(\n str: string,\n ast: AST,\n pos: number,\n opt: MinimatchOptions,\n extDepth: number,\n ): number {\n const maxDepth = opt.maxExtglobRecursion ?? 2\n let escaping = false\n let inBrace = false\n let braceStart = -1\n let braceNeg = false\n if (ast.type === null) {\n // outside of a extglob, append until we find a start\n let i = pos\n let acc = ''\n while (i < str.length) {\n const c = str.charAt(i++)\n // still accumulate escapes at this point, but we do ignore\n // starts that are escaped\n if (escaping || c === '\\\\') {\n escaping = !escaping\n acc += c\n continue\n }\n\n if (inBrace) {\n if (i === braceStart + 1) {\n if (c === '^' || c === '!') {\n braceNeg = true\n }\n } else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {\n inBrace = false\n }\n acc += c\n continue\n } else if (c === '[') {\n inBrace = true\n braceStart = i\n braceNeg = false\n acc += c\n continue\n }\n\n // we don't have to check for adoption here, because that's\n // done at the other recursion point.\n const doRecurse =\n !opt.noext &&\n isExtglobType(c) &&\n str.charAt(i) === '(' &&\n extDepth <= maxDepth\n if (doRecurse) {\n ast.push(acc)\n acc = ''\n const ext = new AST(c, ast)\n i = AST.#parseAST(str, ext, i, opt, extDepth + 1)\n ast.push(ext)\n continue\n }\n acc += c\n }\n ast.push(acc)\n return i\n }\n\n // some kind of extglob, pos is at the (\n // find the next | or )\n let i = pos + 1\n let part = new AST(null, ast)\n const parts: AST[] = []\n let acc = ''\n while (i < str.length) {\n const c = str.charAt(i++)\n // still accumulate escapes at this point, but we do ignore\n // starts that are escaped\n if (escaping || c === '\\\\') {\n escaping = !escaping\n acc += c\n continue\n }\n\n if (inBrace) {\n if (i === braceStart + 1) {\n if (c === '^' || c === '!') {\n braceNeg = true\n }\n } else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {\n inBrace = false\n }\n acc += c\n continue\n } else if (c === '[') {\n inBrace = true\n braceStart = i\n braceNeg = false\n acc += c\n continue\n }\n\n const doRecurse =\n !opt.noext &&\n isExtglobType(c) &&\n str.charAt(i) === '(' &&\n /* c8 ignore start - the maxDepth is sufficient here */\n (extDepth <= maxDepth || (ast && ast.#canAdoptType(c)))\n /* c8 ignore stop */\n if (doRecurse) {\n const depthAdd = ast && ast.#canAdoptType(c) ? 0 : 1\n part.push(acc)\n acc = ''\n const ext = new AST(c, part)\n part.push(ext)\n i = AST.#parseAST(str, ext, i, opt, extDepth + depthAdd)\n continue\n }\n if (c === '|') {\n part.push(acc)\n acc = ''\n parts.push(part)\n part = new AST(null, ast)\n continue\n }\n if (c === ')') {\n if (acc === '' && ast.#parts.length === 0) {\n ast.#emptyExt = true\n }\n part.push(acc)\n acc = ''\n ast.push(...parts, part)\n return i\n }\n acc += c\n }\n\n // unfinished extglob\n // if we got here, it was a malformed extglob! not an extglob, but\n // maybe something else in there.\n ast.type = null\n ast.#hasMagic = undefined\n ast.#parts = [str.substring(pos - 1)]\n return i\n }\n\n #canAdoptWithSpace(child?: AST | string): child is AST & {\n type: null\n parts: [AST & { type: ExtglobType }]\n } {\n return this.#canAdopt(child, adoptionWithSpaceMap)\n }\n\n #canAdopt(\n child?: AST | string,\n map: Map<ExtglobType, ExtglobType[]> = adoptionMap,\n ): child is AST & {\n type: null\n parts: [AST & { type: ExtglobType }]\n } {\n if (\n !child ||\n typeof child !== 'object' ||\n child.type !== null ||\n child.#parts.length !== 1 ||\n this.type === null\n ) {\n return false\n }\n const gc = child.#parts[0]\n if (!gc || typeof gc !== 'object' || gc.type === null) {\n return false\n }\n return (this as AST & { type: ExtglobType }).#canAdoptType(\n gc.type,\n map,\n )\n }\n #canAdoptType(\n c: string,\n map: Map<ExtglobType, ExtglobType[]> = adoptionAnyMap,\n ): c is ExtglobType {\n return !!map.get(this.type as ExtglobType)?.includes(c as ExtglobType)\n }\n\n #adoptWithSpace(\n this: AST & { type: ExtglobType },\n child: AST & {\n type: null\n },\n index: number,\n ) {\n const gc = child.#parts[0] as AST & { type: ExtglobType }\n const blank = new AST(null, gc, this.options)\n blank.#parts.push('')\n gc.push(blank)\n this.#adopt(child, index)\n }\n\n #adopt(\n child: AST & {\n type: null\n },\n index: number,\n ) {\n const gc = child.#parts[0] as AST & { type: ExtglobType }\n this.#parts.splice(index, 1, ...gc.#parts)\n for (const p of gc.#parts) {\n if (typeof p === 'object') p.#parent = this\n }\n this.#toString = undefined\n }\n\n #canUsurpType(c: string): boolean {\n const m = usurpMap.get(this.type as ExtglobType)\n return !!m?.has(c as ExtglobType)\n }\n\n #canUsurp(child?: AST | string): child is AST & {\n type: null\n parts: [AST & { type: ExtglobType }]\n } {\n if (\n !child ||\n typeof child !== 'object' ||\n child.type !== null ||\n child.#parts.length !== 1 ||\n this.type === null ||\n this.#parts.length !== 1\n ) {\n return false\n }\n const gc = child.#parts[0]\n if (!gc || typeof gc !== 'object' || gc.type === null) {\n return false\n }\n return (this as AST & { type: ExtglobType }).#canUsurpType(gc.type)\n }\n\n #usurp(this: AST & { type: ExtglobType }, child: AST & { type: null }) {\n const m = usurpMap.get(this.type as ExtglobType)\n const gc = child.#parts[0] as AST & { type: ExtglobType }\n const nt = m?.get(gc.type)\n /* c8 ignore start - impossible */\n if (!nt) return false\n /* c8 ignore stop */\n this.#parts = gc.#parts\n for (const p of this.#parts) {\n if (typeof p === 'object') {\n p.#parent = this\n }\n }\n this.type = nt\n this.#toString = undefined\n this.#emptyExt = false\n }\n\n static fromGlob(pattern: string, options: MinimatchOptions = {}) {\n const ast = new AST(null, undefined, options)\n AST.#parseAST(pattern, ast, 0, options, 0)\n return ast\n }\n\n // returns the regular expression if there's magic, or the unescaped\n // string if not.\n toMMPattern(): MMRegExp | string {\n // should only be called on root\n /* c8 ignore start */\n if (this !== this.#root) return this.#root.toMMPattern()\n /* c8 ignore stop */\n const glob = this.toString()\n const [re, body, hasMagic, uflag] = this.toRegExpSource()\n // if we're in nocase mode, and not nocaseMagicOnly, then we do\n // still need a regular expression if we have to case-insensitively\n // match capital/lowercase characters.\n const anyMagic =\n hasMagic ||\n this.#hasMagic ||\n (this.#options.nocase &&\n !this.#options.nocaseMagicOnly &&\n glob.toUpperCase() !== glob.toLowerCase())\n if (!anyMagic) {\n return body\n }\n\n const flags = (this.#options.nocase ? 'i' : '') + (uflag ? 'u' : '')\n return Object.assign(new RegExp(`^${re}$`, flags), {\n _src: re,\n _glob: glob,\n })\n }\n\n get options() {\n return this.#options\n }\n\n // returns the string match, the regexp source, whether there's magic\n // in the regexp (so a regular expression is required) and whether or\n // not the uflag is needed for the regular expression (for posix classes)\n // TODO: instead of injecting the start/end at this point, just return\n // the BODY of the regexp, along with the start/end portions suitable\n // for binding the start/end in either a joined full-path makeRe context\n // (where we bind to (^|/), or a standalone matchPart context (where\n // we bind to ^, and not /). Otherwise slashes get duped!\n //\n // In part-matching mode, the start is:\n // - if not isStart: nothing\n // - if traversal possible, but not allowed: ^(?!\\.\\.?$)\n // - if dots allowed or not possible: ^\n // - if dots possible and not allowed: ^(?!\\.)\n // end is:\n // - if not isEnd(): nothing\n // - else: $\n //\n // In full-path matching mode, we put the slash at the START of the\n // pattern, so start is:\n // - if first pattern: same as part-matching mode\n // - if not isStart(): nothing\n // - if traversal possible, but not allowed: /(?!\\.\\.?(?:$|/))\n // - if dots allowed or not possible: /\n // - if dots possible and not allowed: /(?!\\.)\n // end is:\n // - if last pattern, same as part-matching mode\n // - else nothing\n //\n // Always put the (?:$|/) on negated tails, though, because that has to be\n // there to bind the end of the negated pattern portion, and it's easier to\n // just stick it in now rather than try to inject it later in the middle of\n // the pattern.\n //\n // We can just always return the same end, and leave it up to the caller\n // to know whether it's going to be used joined or in parts.\n // And, if the start is adjusted slightly, can do the same there:\n // - if not isStart: nothing\n // - if traversal possible, but not allowed: (?:/|^)(?!\\.\\.?$)\n // - if dots allowed or not possible: (?:/|^)\n // - if dots possible and not allowed: (?:/|^)(?!\\.)\n //\n // But it's better to have a simpler binding without a conditional, for\n // performance, so probably better to return both start options.\n //\n // Then the caller just ignores the end if it's not the first pattern,\n // and the start always gets applied.\n //\n // But that's always going to be $ if it's the ending pattern, or nothing,\n // so the caller can just attach $ at the end of the pattern when building.\n //\n // So the todo is:\n // - better detect what kind of start is needed\n // - return both flavors of starting pattern\n // - attach $ at the end of the pattern when creating the actual RegExp\n //\n // Ah, but wait, no, that all only applies to the root when the first pattern\n // is not an extglob. If the first pattern IS an extglob, then we need all\n // that dot prevention biz to live in the extglob portions, because eg\n // +(*|.x*) can match .xy but not .yx.\n //\n // So, return the two flavors if it's #root and the first child is not an\n // AST, otherwise leave it to the child AST to handle it, and there,\n // use the (?:^|/) style of start binding.\n //\n // Even simplified further:\n // - Since the start for a join is eg /(?!\\.) and the start for a part\n // is ^(?!\\.), we can just prepend (?!\\.) to the pattern (either root\n // or start or whatever) and prepend ^ or / at the Regexp construction.\n toRegExpSource(\n allowDot?: boolean,\n ): [re: string, body: string, hasMagic: boolean, uflag: boolean] {\n const dot = allowDot ?? !!this.#options.dot\n if (this.#root === this) {\n this.#flatten()\n this.#fillNegs()\n }\n if (!isExtglobAST(this)) {\n const noEmpty =\n this.isStart() &&\n this.isEnd() &&\n !this.#parts.some(s => typeof s !== 'string')\n const src = this.#parts\n .map(p => {\n const [re, _, hasMagic, uflag] =\n typeof p === 'string' ?\n AST.#parseGlob(p, this.#hasMagic, noEmpty)\n : p.toRegExpSource(allowDot)\n this.#hasMagic = this.#hasMagic || hasMagic\n this.#uflag = this.#uflag || uflag\n return re\n })\n .join('')\n\n let start = ''\n if (this.isStart()) {\n if (typeof this.#parts[0] === 'string') {\n // this is the string that will match the start of the pattern,\n // so we need to protect against dots and such.\n\n // '.' and '..' cannot match unless the pattern is that exactly,\n // even if it starts with . or dot:true is set.\n const dotTravAllowed =\n this.#parts.length === 1 && justDots.has(this.#parts[0])\n if (!dotTravAllowed) {\n const aps = addPatternStart\n // check if we have a possibility of matching . or ..,\n // and prevent that.\n const needNoTrav =\n // dots are allowed, and the pattern starts with [ or .\n (dot && aps.has(src.charAt(0))) ||\n // the pattern starts with \\., and then [ or .\n (src.startsWith('\\\\.') && aps.has(src.charAt(2))) ||\n // the pattern starts with \\.\\., and then [ or .\n (src.startsWith('\\\\.\\\\.') && aps.has(src.charAt(4)))\n // no need to prevent dots if it can't match a dot, or if a\n // sub-pattern will be preventing it anyway.\n const needNoDot = !dot && !allowDot && aps.has(src.charAt(0))\n\n start =\n needNoTrav ? startNoTraversal\n : needNoDot ? startNoDot\n : ''\n }\n }\n }\n\n // append the \"end of path portion\" pattern to negation tails\n let end = ''\n if (\n this.isEnd() &&\n this.#root.#filledNegs &&\n this.#parent?.type === '!'\n ) {\n end = '(?:$|\\\\/)'\n }\n const final = start + src + end\n return [\n final,\n unescape(src),\n (this.#hasMagic = !!this.#hasMagic),\n this.#uflag,\n ]\n }\n\n // We need to calculate the body *twice* if it's a repeat pattern\n // at the start, once in nodot mode, then again in dot mode, so a\n // pattern like *(?) can match 'x.y'\n\n const repeated = this.type === '*' || this.type === '+'\n // some kind of extglob\n const start = this.type === '!' ? '(?:(?!(?:' : '(?:'\n let body = (this as AST & { type: ExtglobType }).#partsToRegExp(dot)\n\n if (this.isStart() && this.isEnd() && !body && this.type !== '!') {\n // invalid extglob, has to at least be *something* present, if it's\n // the entire path portion.\n const s = this.toString()\n const me = this as AST\n me.#parts = [s]\n me.type = null\n me.#hasMagic = undefined\n return [s, unescape(this.toString()), false, false]\n }\n\n let bodyDotAllowed =\n !repeated || allowDot || dot || !startNoDot ?\n ''\n : this.#partsToRegExp(true)\n if (bodyDotAllowed === body) {\n bodyDotAllowed = ''\n }\n if (bodyDotAllowed) {\n body = `(?:${body})(?:${bodyDotAllowed})*?`\n }\n\n // an empty !() is exactly equivalent to a starNoEmpty\n let final = ''\n if (this.type === '!' && this.#emptyExt) {\n final = (this.isStart() && !dot ? startNoDot : '') + starNoEmpty\n } else {\n const close =\n this.type === '!' ?\n // !() must match something,but !(x) can match ''\n '))' +\n (this.isStart() && !dot && !allowDot ? startNoDot : '') +\n star +\n ')'\n : this.type === '@' ? ')'\n : this.type === '?' ? ')?'\n : this.type === '+' && bodyDotAllowed ? ')'\n : this.type === '*' && bodyDotAllowed ? `)?`\n : `)${this.type}`\n final = start + body + close\n }\n return [\n final,\n unescape(body),\n (this.#hasMagic = !!this.#hasMagic),\n this.#uflag,\n ]\n }\n\n #flatten() {\n if (!isExtglobAST(this)) {\n for (const p of this.#parts) {\n if (typeof p === 'object') {\n p.#flatten()\n }\n }\n } else {\n // do up to 10 passes to flatten as much as possible\n let iterations = 0\n let done = false\n do {\n done = true\n for (let i = 0; i < this.#parts.length; i++) {\n const c = this.#parts[i]\n if (typeof c === 'object') {\n c.#flatten()\n if (this.#canAdopt(c)) {\n done = false\n this.#adopt(c, i)\n } else if (this.#canAdoptWithSpace(c)) {\n done = false\n ;(this as AST & { type: ExtglobType }).#adoptWithSpace(c, i)\n } else if (this.#canUsurp(c)) {\n done = false\n ;(this as AST & { type: ExtglobType }).#usurp(c)\n }\n }\n }\n } while (!done && ++iterations < 10)\n }\n this.#toString = undefined\n }\n\n #partsToRegExp(this: AST & { type: ExtglobType }, dot: boolean) {\n return this.#parts\n .map(p => {\n // extglob ASTs should only contain parent ASTs\n /* c8 ignore start */\n if (typeof p === 'string') {\n throw new Error('string type in extglob ast??')\n }\n /* c8 ignore stop */\n // can ignore hasMagic, because extglobs are already always magic\n const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot)\n this.#uflag = this.#uflag || uflag\n return re\n })\n .filter(p => !(this.isStart() && this.isEnd()) || !!p)\n .join('|')\n }\n\n static #parseGlob(\n glob: string,\n hasMagic: boolean | undefined,\n noEmpty: boolean = false,\n ): [re: string, body: string, hasMagic: boolean, uflag: boolean] {\n let escaping = false\n let re = ''\n let uflag = false\n // multiple stars that aren't globstars coalesce into one *\n let inStar = false\n for (let i = 0; i < glob.length; i++) {\n const c = glob.charAt(i)\n if (escaping) {\n escaping = false\n re += (reSpecials.has(c) ? '\\\\' : '') + c\n continue\n }\n if (c === '*') {\n if (inStar) continue\n inStar = true\n re += noEmpty && /^[*]+$/.test(glob) ? starNoEmpty : star\n hasMagic = true\n continue\n } else {\n inStar = false\n }\n if (c === '\\\\') {\n if (i === glob.length - 1) {\n re += '\\\\\\\\'\n } else {\n escaping = true\n }\n continue\n }\n if (c === '[') {\n const [src, needUflag, consumed, magic] = parseClass(glob, i)\n if (consumed) {\n re += src\n uflag = uflag || needUflag\n i += consumed - 1\n hasMagic = hasMagic || magic\n continue\n }\n }\n if (c === '?') {\n re += qmark\n hasMagic = true\n continue\n }\n re += regExpEscape(c)\n }\n return [re, unescape(glob), !!hasMagic, uflag]\n }\n}\n","import type { MinimatchOptions } from './index.js'\n\n/**\n * Escape all magic characters in a glob pattern.\n *\n * If the {@link MinimatchOptions.windowsPathsNoEscape}\n * option is used, then characters are escaped by wrapping in `[]`, because\n * a magic character wrapped in a character class can only be satisfied by\n * that exact character. In this mode, `\\` is _not_ escaped, because it is\n * not interpreted as a magic character, but instead as a path separator.\n *\n * If the {@link MinimatchOptions.magicalBraces} option is used,\n * then braces (`{` and `}`) will be escaped.\n */\nexport const escape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n magicalBraces = false,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape' | 'magicalBraces'> = {},\n) => {\n // don't need to escape +@! because we escape the parens\n // that make those magic, and escaping ! as [!] isn't valid,\n // because [!]] is a valid glob class meaning not ']'.\n if (magicalBraces) {\n return windowsPathsNoEscape ?\n s.replace(/[?*()[\\]{}]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\{}]/g, '\\\\$&')\n }\n return windowsPathsNoEscape ?\n s.replace(/[?*()[\\]]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\]/g, '\\\\$&')\n}\n","import { expand } from 'brace-expansion'\nimport { assertValidPattern } from './assert-valid-pattern.js'\nimport type { ExtglobType } from './ast.js'\nimport { AST } from './ast.js'\nimport { escape } from './escape.js'\nimport { unescape } from './unescape.js'\n\nexport type Platform =\n | 'aix'\n | 'android'\n | 'darwin'\n | 'freebsd'\n | 'haiku'\n | 'linux'\n | 'openbsd'\n | 'sunos'\n | 'win32'\n | 'cygwin'\n | 'netbsd'\n\nexport interface MinimatchOptions {\n /** do not expand `{x,y}` style braces */\n nobrace?: boolean\n /** do not treat patterns starting with `#` as a comment */\n nocomment?: boolean\n /** do not treat patterns starting with `!` as a negation */\n nonegate?: boolean\n /** print LOTS of debugging output */\n debug?: boolean\n /** treat `**` the same as `*` */\n noglobstar?: boolean\n /** do not expand extglobs like `+(a|b)` */\n noext?: boolean\n /** return the pattern if nothing matches */\n nonull?: boolean\n /** treat `\\\\` as a path separator, not an escape character */\n windowsPathsNoEscape?: boolean\n /**\n * inverse of {@link MinimatchOptions.windowsPathsNoEscape}\n * @deprecated\n */\n allowWindowsEscape?: boolean\n /**\n * Compare a partial path to a pattern. As long as the parts\n * of the path that are present are not contradicted by the\n * pattern, it will be treated as a match. This is useful in\n * applications where you're walking through a folder structure,\n * and don't yet have the full path, but want to ensure that you\n * do not walk down paths that can never be a match.\n */\n partial?: boolean\n /** allow matches that start with `.` even if the pattern does not */\n dot?: boolean\n /** ignore case */\n nocase?: boolean\n /** ignore case only in wildcard patterns */\n nocaseMagicOnly?: boolean\n /** consider braces to be \"magic\" for the purpose of `hasMagic` */\n magicalBraces?: boolean\n /**\n * If set, then patterns without slashes will be matched\n * against the basename of the path if it contains slashes.\n * For example, `a?b` would match the path `/xyz/123/acb`, but\n * not `/xyz/acb/123`.\n */\n matchBase?: boolean\n /** invert the results of negated matches */\n flipNegate?: boolean\n /** do not collapse multiple `/` into a single `/` */\n preserveMultipleSlashes?: boolean\n /**\n * A number indicating the level of optimization that should be done\n * to the pattern prior to parsing and using it for matches.\n */\n optimizationLevel?: number\n /** operating system platform */\n platform?: Platform\n /**\n * When a pattern starts with a UNC path or drive letter, and in\n * `nocase:true` mode, do not convert the root portions of the\n * pattern into a case-insensitive regular expression, and instead\n * leave them as strings.\n *\n * This is the default when the platform is `win32` and\n * `nocase:true` is set.\n */\n windowsNoMagicRoot?: boolean\n /**\n * max number of `{...}` patterns to expand. Default 100_000.\n */\n braceExpandMax?: number\n /**\n * Max number of non-adjacent `**` patterns to recursively walk down.\n *\n * The default of 200 is almost certainly high enough for most purposes,\n * and can handle absurdly excessive patterns.\n */\n maxGlobstarRecursion?: number\n\n /**\n * Max depth to traverse for nested extglobs like `*(a|b|c)`\n *\n * Default is 2, which is quite low, but any higher value\n * swiftly results in punishing performance impacts. Note\n * that this is *not* relevant when the globstar types can\n * be safely coalesced into a single set.\n *\n * For example, `*(a|@(b|c)|d)` would be flattened into\n * `*(a|b|c|d)`. Thus, many common extglobs will retain good\n * performance and never hit this limit, even if they are\n * excessively deep and complicated.\n *\n * If the limit is hit, then the extglob characters are simply\n * not parsed, and the pattern effectively switches into\n * `noextglob: true` mode for the contents of that nested\n * sub-pattern. This will typically _not_ result in a match,\n * but is considered a valid trade-off for security and\n * performance.\n */\n maxExtglobRecursion?: number\n}\n\nexport const minimatch = (\n p: string,\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n assertValidPattern(pattern)\n\n // shortcut: comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n return false\n }\n\n return new Minimatch(pattern, options).match(p)\n}\n\n// Optimized checking for the most common glob patterns.\nconst starDotExtRE = /^\\*+([^+@!?*[(]*)$/\nconst starDotExtTest = (ext: string) => (f: string) =>\n !f.startsWith('.') && f.endsWith(ext)\nconst starDotExtTestDot = (ext: string) => (f: string) => f.endsWith(ext)\nconst starDotExtTestNocase = (ext: string) => {\n ext = ext.toLowerCase()\n return (f: string) => !f.startsWith('.') && f.toLowerCase().endsWith(ext)\n}\nconst starDotExtTestNocaseDot = (ext: string) => {\n ext = ext.toLowerCase()\n return (f: string) => f.toLowerCase().endsWith(ext)\n}\nconst starDotStarRE = /^\\*+\\.\\*+$/\nconst starDotStarTest = (f: string) =>\n !f.startsWith('.') && f.includes('.')\nconst starDotStarTestDot = (f: string) =>\n f !== '.' && f !== '..' && f.includes('.')\nconst dotStarRE = /^\\.\\*+$/\nconst dotStarTest = (f: string) =>\n f !== '.' && f !== '..' && f.startsWith('.')\nconst starRE = /^\\*+$/\nconst starTest = (f: string) => f.length !== 0 && !f.startsWith('.')\nconst starTestDot = (f: string) =>\n f.length !== 0 && f !== '.' && f !== '..'\nconst qmarksRE = /^\\?+([^+@!?*[(]*)?$/\nconst qmarksTestNocase = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExt([$0])\n if (!ext) return noext\n ext = ext.toLowerCase()\n return (f: string) => noext(f) && f.toLowerCase().endsWith(ext)\n}\nconst qmarksTestNocaseDot = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExtDot([$0])\n if (!ext) return noext\n ext = ext.toLowerCase()\n return (f: string) => noext(f) && f.toLowerCase().endsWith(ext)\n}\nconst qmarksTestDot = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExtDot([$0])\n return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext)\n}\nconst qmarksTest = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExt([$0])\n return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext)\n}\nconst qmarksTestNoExt = ([$0]: RegExpMatchArray) => {\n const len = $0.length\n return (f: string) => f.length === len && !f.startsWith('.')\n}\nconst qmarksTestNoExtDot = ([$0]: RegExpMatchArray) => {\n const len = $0.length\n return (f: string) => f.length === len && f !== '.' && f !== '..'\n}\n\n/* c8 ignore start */\nconst defaultPlatform: Platform = (\n typeof process === 'object' && process ?\n (typeof process.env === 'object' &&\n process.env &&\n process.env.__MINIMATCH_TESTING_PLATFORM__) ||\n process.platform\n : 'posix') as Platform\n\nexport type Sep = '\\\\' | '/'\n\nconst path: { [k: string]: { sep: Sep } } = {\n win32: { sep: '\\\\' },\n posix: { sep: '/' },\n}\n/* c8 ignore stop */\n\nexport const sep =\n defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep\nminimatch.sep = sep\n\nexport const GLOBSTAR = Symbol('globstar **')\nminimatch.GLOBSTAR = GLOBSTAR\n\n// any single thing other than /\n// don't need to escape / when using new RegExp()\nconst qmark = '[^/]'\n\n// * => any number of characters\nconst star = qmark + '*?'\n\n// ** when dots are allowed. Anything goes, except .. and .\n// not (^ or / followed by one or two dots followed by $ or /),\n// followed by anything, any number of times.\nconst twoStarDot = '(?:(?!(?:\\\\/|^)(?:\\\\.{1,2})($|\\\\/)).)*?'\n\n// not a ^ or / followed by a dot,\n// followed by anything, any number of times.\nconst twoStarNoDot = '(?:(?!(?:\\\\/|^)\\\\.).)*?'\n\nexport const filter =\n (pattern: string, options: MinimatchOptions = {}) =>\n (p: string) =>\n minimatch(p, pattern, options)\nminimatch.filter = filter\n\nconst ext = (a: MinimatchOptions, b: MinimatchOptions = {}) =>\n Object.assign({}, a, b)\n\nexport const defaults = (def: MinimatchOptions): typeof minimatch => {\n if (!def || typeof def !== 'object' || !Object.keys(def).length) {\n return minimatch\n }\n\n const orig = minimatch\n\n const m = (p: string, pattern: string, options: MinimatchOptions = {}) =>\n orig(p, pattern, ext(def, options))\n\n return Object.assign(m, {\n Minimatch: class Minimatch extends orig.Minimatch {\n constructor(pattern: string, options: MinimatchOptions = {}) {\n super(pattern, ext(def, options))\n }\n static defaults(options: MinimatchOptions) {\n return orig.defaults(ext(def, options)).Minimatch\n }\n },\n\n AST: class AST extends orig.AST {\n /* c8 ignore start */\n constructor(\n type: ExtglobType | null,\n parent?: AST,\n options: MinimatchOptions = {},\n ) {\n super(type, parent, ext(def, options))\n }\n /* c8 ignore stop */\n\n static fromGlob(pattern: string, options: MinimatchOptions = {}) {\n return orig.AST.fromGlob(pattern, ext(def, options))\n }\n },\n\n unescape: (\n s: string,\n options: Pick<\n MinimatchOptions,\n 'windowsPathsNoEscape' | 'magicalBraces'\n > = {},\n ) => orig.unescape(s, ext(def, options)),\n\n escape: (\n s: string,\n options: Pick<\n MinimatchOptions,\n 'windowsPathsNoEscape' | 'magicalBraces'\n > = {},\n ) => orig.escape(s, ext(def, options)),\n\n filter: (pattern: string, options: MinimatchOptions = {}) =>\n orig.filter(pattern, ext(def, options)),\n\n defaults: (options: MinimatchOptions) =>\n orig.defaults(ext(def, options)),\n\n makeRe: (pattern: string, options: MinimatchOptions = {}) =>\n orig.makeRe(pattern, ext(def, options)),\n\n braceExpand: (pattern: string, options: MinimatchOptions = {}) =>\n orig.braceExpand(pattern, ext(def, options)),\n\n match: (\n list: string[],\n pattern: string,\n options: MinimatchOptions = {},\n ) => orig.match(list, pattern, ext(def, options)),\n\n sep: orig.sep,\n GLOBSTAR: GLOBSTAR as typeof GLOBSTAR,\n })\n}\nminimatch.defaults = defaults\n\n// Brace expansion:\n// a{b,c}d -> abd acd\n// a{b,}c -> abc ac\n// a{0..3}d -> a0d a1d a2d a3d\n// a{b,c{d,e}f}g -> abg acdfg acefg\n// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg\n//\n// Invalid sets are not expanded.\n// a{2..}b -> a{2..}b\n// a{b}c -> a{b}c\nexport const braceExpand = (\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n assertValidPattern(pattern)\n\n // Thanks to Yeting Li <https://github.com/yetingli> for\n // improving this regexp to avoid a ReDOS vulnerability.\n if (options.nobrace || !/\\{(?:(?!\\{).)*\\}/.test(pattern)) {\n // shortcut. no need to expand.\n return [pattern]\n }\n\n return expand(pattern, { max: options.braceExpandMax })\n}\nminimatch.braceExpand = braceExpand\n\n// parse a component of the expanded set.\n// At this point, no pattern may contain \"/\" in it\n// so we're going to return a 2d array, where each entry is the full\n// pattern, split on '/', and then turned into a regular expression.\n// A regexp is made at the end which joins each array with an\n// escaped /, and another full one which joins each regexp with |.\n//\n// Following the lead of Bash 4.1, note that \"**\" only has special meaning\n// when it is the *only* thing in a path portion. Otherwise, any series\n// of * is equivalent to a single *. Globstar behavior is enabled by\n// default, and can be disabled by setting options.noglobstar.\n\nexport const makeRe = (pattern: string, options: MinimatchOptions = {}) =>\n new Minimatch(pattern, options).makeRe()\nminimatch.makeRe = makeRe\n\nexport const match = (\n list: string[],\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n const mm = new Minimatch(pattern, options)\n list = list.filter(f => mm.match(f))\n if (mm.options.nonull && !list.length) {\n list.push(pattern)\n }\n return list\n}\nminimatch.match = match\n\n// replace stuff like \\* with *\nconst globMagic = /[?*]|[+@!]\\(.*?\\)|\\[|\\]/\nconst regExpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\nexport type MMRegExp = RegExp & {\n _src?: string\n _glob?: string\n}\n\nexport type ParseReturnFiltered = string | MMRegExp | typeof GLOBSTAR\nexport type ParseReturn = ParseReturnFiltered | false\n\nexport class Minimatch {\n options: MinimatchOptions\n set: ParseReturnFiltered[][]\n pattern: string\n\n windowsPathsNoEscape: boolean\n nonegate: boolean\n negate: boolean\n comment: boolean\n empty: boolean\n preserveMultipleSlashes: boolean\n partial: boolean\n globSet: string[]\n globParts: string[][]\n nocase: boolean\n\n isWindows: boolean\n platform: Platform\n windowsNoMagicRoot: boolean\n maxGlobstarRecursion: number\n\n regexp: false | null | MMRegExp\n constructor(pattern: string, options: MinimatchOptions = {}) {\n assertValidPattern(pattern)\n\n options = options || {}\n this.options = options\n this.maxGlobstarRecursion = options.maxGlobstarRecursion ?? 200\n this.pattern = pattern\n this.platform = options.platform || defaultPlatform\n this.isWindows = this.platform === 'win32'\n // avoid the annoying deprecation flag lol\n const awe = ('allowWindow' + 'sEscape') as keyof MinimatchOptions\n this.windowsPathsNoEscape =\n !!options.windowsPathsNoEscape || options[awe] === false\n if (this.windowsPathsNoEscape) {\n this.pattern = this.pattern.replace(/\\\\/g, '/')\n }\n this.preserveMultipleSlashes = !!options.preserveMultipleSlashes\n this.regexp = null\n this.negate = false\n this.nonegate = !!options.nonegate\n this.comment = false\n this.empty = false\n this.partial = !!options.partial\n this.nocase = !!this.options.nocase\n this.windowsNoMagicRoot =\n options.windowsNoMagicRoot !== undefined ?\n options.windowsNoMagicRoot\n : !!(this.isWindows && this.nocase)\n\n this.globSet = []\n this.globParts = []\n this.set = []\n\n // make the set of regexps etc.\n this.make()\n }\n\n hasMagic(): boolean {\n if (this.options.magicalBraces && this.set.length > 1) {\n return true\n }\n for (const pattern of this.set) {\n for (const part of pattern) {\n if (typeof part !== 'string') return true\n }\n }\n return false\n }\n\n debug(..._: unknown[]) {}\n\n make() {\n const pattern = this.pattern\n const options = this.options\n\n // empty patterns and comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n this.comment = true\n return\n }\n\n if (!pattern) {\n this.empty = true\n return\n }\n\n // step 1: figure out negation, etc.\n this.parseNegate()\n\n // step 2: expand braces\n this.globSet = [...new Set(this.braceExpand())]\n\n if (options.debug) {\n //oxlint-disable-next-line no-console\n this.debug = (...args: unknown[]) => console.error(...args)\n }\n\n this.debug(this.pattern, this.globSet)\n\n // step 3: now we have a set, so turn each one into a series of\n // path-portion matching patterns.\n // These will be regexps, except in the case of \"**\", which is\n // set to the GLOBSTAR object for globstar behavior,\n // and will not contain any / characters\n //\n // First, we preprocess to make the glob pattern sets a bit simpler\n // and deduped. There are some perf-killing patterns that can cause\n // problems with a glob walk, but we can simplify them down a bit.\n const rawGlobParts = this.globSet.map(s => this.slashSplit(s))\n this.globParts = this.preprocess(rawGlobParts)\n this.debug(this.pattern, this.globParts)\n\n // glob --> regexps\n let set = this.globParts.map((s, _, __) => {\n if (this.isWindows && this.windowsNoMagicRoot) {\n // check if it's a drive or unc path.\n const isUNC =\n s[0] === '' &&\n s[1] === '' &&\n (s[2] === '?' || !globMagic.test(s[2])) &&\n !globMagic.test(s[3])\n const isDrive = /^[a-z]:/i.test(s[0])\n if (isUNC) {\n return [\n ...s.slice(0, 4),\n ...s.slice(4).map(ss => this.parse(ss)),\n ]\n } else if (isDrive) {\n return [s[0], ...s.slice(1).map(ss => this.parse(ss))]\n }\n }\n return s.map(ss => this.parse(ss))\n })\n\n this.debug(this.pattern, set)\n\n // filter out everything that didn't compile properly.\n this.set = set.filter(\n s => s.indexOf(false) === -1,\n ) as ParseReturnFiltered[][]\n\n // do not treat the ? in UNC paths as magic\n if (this.isWindows) {\n for (let i = 0; i < this.set.length; i++) {\n const p = this.set[i]\n if (\n p[0] === '' &&\n p[1] === '' &&\n this.globParts[i][2] === '?' &&\n typeof p[3] === 'string' &&\n /^[a-z]:$/i.test(p[3])\n ) {\n p[2] = '?'\n }\n }\n }\n\n this.debug(this.pattern, this.set)\n }\n\n // various transforms to equivalent pattern sets that are\n // faster to process in a filesystem walk. The goal is to\n // eliminate what we can, and push all ** patterns as far\n // to the right as possible, even if it increases the number\n // of patterns that we have to process.\n preprocess(globParts: string[][]) {\n // if we're not in globstar mode, then turn ** into *\n if (this.options.noglobstar) {\n for (const partset of globParts) {\n for (let j = 0; j < partset.length; j++) {\n if (partset[j] === '**') {\n partset[j] = '*'\n }\n }\n }\n }\n\n const { optimizationLevel = 1 } = this.options\n\n if (optimizationLevel >= 2) {\n // aggressive optimization for the purpose of fs walking\n globParts = this.firstPhasePreProcess(globParts)\n globParts = this.secondPhasePreProcess(globParts)\n } else if (optimizationLevel >= 1) {\n // just basic optimizations to remove some .. parts\n globParts = this.levelOneOptimize(globParts)\n } else {\n // just collapse multiple ** portions into one\n globParts = this.adjascentGlobstarOptimize(globParts)\n }\n\n return globParts\n }\n\n // just get rid of adjascent ** portions\n adjascentGlobstarOptimize(globParts: string[][]) {\n return globParts.map(parts => {\n let gs: number = -1\n while (-1 !== (gs = parts.indexOf('**', gs + 1))) {\n let i = gs\n while (parts[i + 1] === '**') {\n i++\n }\n if (i !== gs) {\n parts.splice(gs, i - gs)\n }\n }\n return parts\n })\n }\n\n // get rid of adjascent ** and resolve .. portions\n levelOneOptimize(globParts: string[][]) {\n return globParts.map(parts => {\n parts = parts.reduce((set: string[], part) => {\n const prev = set[set.length - 1]\n if (part === '**' && prev === '**') {\n return set\n }\n if (part === '..') {\n if (prev && prev !== '..' && prev !== '.' && prev !== '**') {\n set.pop()\n return set\n }\n }\n set.push(part)\n return set\n }, [])\n return parts.length === 0 ? [''] : parts\n })\n }\n\n levelTwoFileOptimize(parts: string | string[]) {\n if (!Array.isArray(parts)) {\n parts = this.slashSplit(parts)\n }\n let didSomething: boolean = false\n\n do {\n didSomething = false\n // <pre>/<e>/<rest> -> <pre>/<rest>\n if (!this.preserveMultipleSlashes) {\n for (let i = 1; i < parts.length - 1; i++) {\n const p = parts[i]\n // don't squeeze out UNC patterns\n if (i === 1 && p === '' && parts[0] === '') continue\n if (p === '.' || p === '') {\n didSomething = true\n parts.splice(i, 1)\n i--\n }\n }\n if (\n parts[0] === '.' &&\n parts.length === 2 &&\n (parts[1] === '.' || parts[1] === '')\n ) {\n didSomething = true\n parts.pop()\n }\n }\n\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n let dd: number = 0\n while (-1 !== (dd = parts.indexOf('..', dd + 1))) {\n const p = parts[dd - 1]\n if (\n p &&\n p !== '.' &&\n p !== '..' &&\n p !== '**' &&\n !(this.isWindows && /^[a-z]:$/i.test(p))\n ) {\n didSomething = true\n parts.splice(dd - 1, 2)\n dd -= 2\n }\n }\n } while (didSomething)\n return parts.length === 0 ? [''] : parts\n }\n\n // First phase: single-pattern processing\n // <pre> is 1 or more portions\n // <rest> is 1 or more portions\n // <p> is any portion other than ., .., '', or **\n // <e> is . or ''\n //\n // **/.. is *brutal* for filesystem walking performance, because\n // it effectively resets the recursive walk each time it occurs,\n // and ** cannot be reduced out by a .. pattern part like a regexp\n // or most strings (other than .., ., and '') can be.\n //\n // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}\n // <pre>/<e>/<rest> -> <pre>/<rest>\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n // **/**/<rest> -> **/<rest>\n //\n // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow\n // this WOULD be allowed if ** did follow symlinks, or * didn't\n firstPhasePreProcess(globParts: string[][]) {\n let didSomething = false\n do {\n didSomething = false\n // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}\n for (let parts of globParts) {\n let gs: number = -1\n while (-1 !== (gs = parts.indexOf('**', gs + 1))) {\n let gss: number = gs\n while (parts[gss + 1] === '**') {\n // <pre>/**/**/<rest> -> <pre>/**/<rest>\n gss++\n }\n // eg, if gs is 2 and gss is 4, that means we have 3 **\n // parts, and can remove 2 of them.\n if (gss > gs) {\n parts.splice(gs + 1, gss - gs)\n }\n\n let next = parts[gs + 1]\n const p = parts[gs + 2]\n const p2 = parts[gs + 3]\n if (next !== '..') continue\n if (\n !p ||\n p === '.' ||\n p === '..' ||\n !p2 ||\n p2 === '.' ||\n p2 === '..'\n ) {\n continue\n }\n didSomething = true\n // edit parts in place, and push the new one\n parts.splice(gs, 1)\n const other = parts.slice(0)\n other[gs] = '**'\n globParts.push(other)\n gs--\n }\n\n // <pre>/<e>/<rest> -> <pre>/<rest>\n if (!this.preserveMultipleSlashes) {\n for (let i = 1; i < parts.length - 1; i++) {\n const p = parts[i]\n // don't squeeze out UNC patterns\n if (i === 1 && p === '' && parts[0] === '') continue\n if (p === '.' || p === '') {\n didSomething = true\n parts.splice(i, 1)\n i--\n }\n }\n if (\n parts[0] === '.' &&\n parts.length === 2 &&\n (parts[1] === '.' || parts[1] === '')\n ) {\n didSomething = true\n parts.pop()\n }\n }\n\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n let dd: number = 0\n while (-1 !== (dd = parts.indexOf('..', dd + 1))) {\n const p = parts[dd - 1]\n if (p && p !== '.' && p !== '..' && p !== '**') {\n didSomething = true\n const needDot = dd === 1 && parts[dd + 1] === '**'\n const splin = needDot ? ['.'] : []\n parts.splice(dd - 1, 2, ...splin)\n if (parts.length === 0) parts.push('')\n dd -= 2\n }\n }\n }\n } while (didSomething)\n\n return globParts\n }\n\n // second phase: multi-pattern dedupes\n // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>\n // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>\n // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>\n //\n // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>\n // ^-- not valid because ** doens't follow symlinks\n secondPhasePreProcess(globParts: string[][]): string[][] {\n for (let i = 0; i < globParts.length - 1; i++) {\n for (let j = i + 1; j < globParts.length; j++) {\n const matched = this.partsMatch(\n globParts[i],\n globParts[j],\n !this.preserveMultipleSlashes,\n )\n if (matched) {\n globParts[i] = []\n globParts[j] = matched\n break\n }\n }\n }\n return globParts.filter(gs => gs.length)\n }\n\n partsMatch(\n a: string[],\n b: string[],\n emptyGSMatch: boolean = false,\n ): false | string[] {\n let ai = 0\n let bi = 0\n let result: string[] = []\n let which: string = ''\n while (ai < a.length && bi < b.length) {\n if (a[ai] === b[bi]) {\n result.push(which === 'b' ? b[bi] : a[ai])\n ai++\n bi++\n } else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) {\n result.push(a[ai])\n ai++\n } else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) {\n result.push(b[bi])\n bi++\n } else if (\n a[ai] === '*' &&\n b[bi] &&\n (this.options.dot || !b[bi].startsWith('.')) &&\n b[bi] !== '**'\n ) {\n if (which === 'b') return false\n which = 'a'\n result.push(a[ai])\n ai++\n bi++\n } else if (\n b[bi] === '*' &&\n a[ai] &&\n (this.options.dot || !a[ai].startsWith('.')) &&\n a[ai] !== '**'\n ) {\n if (which === 'a') return false\n which = 'b'\n result.push(b[bi])\n ai++\n bi++\n } else {\n return false\n }\n }\n // if we fall out of the loop, it means they two are identical\n // as long as their lengths match\n return a.length === b.length && result\n }\n\n parseNegate() {\n if (this.nonegate) return\n\n const pattern = this.pattern\n let negate = false\n let negateOffset = 0\n\n for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {\n negate = !negate\n negateOffset++\n }\n\n if (negateOffset) this.pattern = pattern.slice(negateOffset)\n this.negate = negate\n }\n\n // set partial to true to test if, for example,\n // \"/a/b\" matches the start of \"/*/b/*/d\"\n // Partial means, if you run out of file before you run\n // out of pattern, then that's fine, as long as all\n // the parts match.\n matchOne(\n file: string[],\n pattern: ParseReturn[],\n partial: boolean = false,\n ) {\n let fileStartIndex = 0\n let patternStartIndex = 0\n\n // UNC paths like //?/X:/... can match X:/... and vice versa\n // Drive letters in absolute drive or unc paths are always compared\n // case-insensitively.\n if (this.isWindows) {\n const fileDrive =\n typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0])\n const fileUNC =\n !fileDrive &&\n file[0] === '' &&\n file[1] === '' &&\n file[2] === '?' &&\n /^[a-z]:$/i.test(file[3])\n\n const patternDrive =\n typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0])\n const patternUNC =\n !patternDrive &&\n pattern[0] === '' &&\n pattern[1] === '' &&\n pattern[2] === '?' &&\n typeof pattern[3] === 'string' &&\n /^[a-z]:$/i.test(pattern[3])\n\n const fdi =\n fileUNC ? 3\n : fileDrive ? 0\n : undefined\n const pdi =\n patternUNC ? 3\n : patternDrive ? 0\n : undefined\n if (typeof fdi === 'number' && typeof pdi === 'number') {\n const [fd, pd]: [string, string] = [\n file[fdi],\n pattern[pdi] as string,\n ]\n // start matching at the drive letter index of each\n if (fd.toLowerCase() === pd.toLowerCase()) {\n pattern[pdi] = fd\n patternStartIndex = pdi\n fileStartIndex = fdi\n }\n }\n }\n\n // resolve and reduce . and .. portions in the file as well.\n // don't need to do the second phase, because it's only one string[]\n const { optimizationLevel = 1 } = this.options\n if (optimizationLevel >= 2) {\n file = this.levelTwoFileOptimize(file)\n }\n\n if (pattern.includes(GLOBSTAR)) {\n return this.#matchGlobstar(\n file,\n pattern,\n partial,\n fileStartIndex,\n patternStartIndex,\n )\n }\n\n return this.#matchOne(\n file,\n pattern,\n partial,\n fileStartIndex,\n patternStartIndex,\n )\n }\n\n #matchGlobstar(\n file: string[],\n pattern: ParseReturn[],\n partial: boolean,\n fileIndex: number,\n patternIndex: number,\n ) {\n // split the pattern into head, tail, and middle of ** delimited parts\n const firstgs = pattern.indexOf(GLOBSTAR, patternIndex)\n const lastgs = pattern.lastIndexOf(GLOBSTAR)\n\n // split the pattern up into globstar-delimited sections\n // the tail has to be at the end, and the others just have\n // to be found in order from the head.\n const [head, body, tail] =\n partial ?\n [\n pattern.slice(patternIndex, firstgs),\n pattern.slice(firstgs + 1),\n [],\n ]\n : [\n pattern.slice(patternIndex, firstgs),\n pattern.slice(firstgs + 1, lastgs),\n pattern.slice(lastgs + 1),\n ]\n\n // check the head, from the current file/pattern index.\n if (head.length) {\n const fileHead = file.slice(fileIndex, fileIndex + head.length)\n if (!this.#matchOne(fileHead, head, partial, 0, 0)) {\n return false\n }\n fileIndex += head.length\n patternIndex += head.length\n }\n // now we know the head matches!\n\n // if the last portion is not empty, it MUST match the end\n // check the tail\n let fileTailMatch: number = 0\n if (tail.length) {\n // if head + tail > file, then we cannot possibly match\n if (tail.length + fileIndex > file.length) return false\n\n // try to match the tail\n let tailStart = file.length - tail.length\n if (this.#matchOne(file, tail, partial, tailStart, 0)) {\n fileTailMatch = tail.length\n } else {\n // affordance for stuff like a/**/* matching a/b/\n // if the last file portion is '', and there's more to the pattern\n // then try without the '' bit.\n if (\n file[file.length - 1] !== '' ||\n fileIndex + tail.length === file.length\n ) {\n return false\n }\n tailStart--\n if (!this.#matchOne(file, tail, partial, tailStart, 0)) {\n return false\n }\n fileTailMatch = tail.length + 1\n }\n }\n\n // now we know the tail matches!\n\n // the middle is zero or more portions wrapped in **, possibly\n // containing more ** sections.\n // so a/**/b/**/c/**/d has become **/b/**/c/**\n // if it's empty, it means a/**/b, just verify we have no bad dots\n // if there's no tail, so it ends on /**, then we must have *something*\n // after the head, or it's not a matc\n if (!body.length) {\n let sawSome = !!fileTailMatch\n for (let i = fileIndex; i < file.length - fileTailMatch; i++) {\n const f = String(file[i])\n sawSome = true\n if (\n f === '.' ||\n f === '..' ||\n (!this.options.dot && f.startsWith('.'))\n ) {\n return false\n }\n }\n // in partial mode, we just need to get past all file parts\n return partial || sawSome\n }\n\n // now we know that there's one or more body sections, which can\n // be matched anywhere from the 0 index (because the head was pruned)\n // through to the length-fileTailMatch index.\n // split the body up into sections, and note the minimum index it can\n // be found at (start with the length of all previous segments)\n // [section, before, after]\n const bodySegments: [ParseReturn[], number][] = [[[], 0]]\n let currentBody: [ParseReturn[], number] = bodySegments[0]\n let nonGsParts = 0\n const nonGsPartsSums: number[] = [0]\n for (const b of body) {\n if (b === GLOBSTAR) {\n nonGsPartsSums.push(nonGsParts)\n currentBody = [[], 0]\n bodySegments.push(currentBody)\n } else {\n currentBody[0].push(b)\n nonGsParts++\n }\n }\n let i = bodySegments.length - 1\n const fileLength = file.length - fileTailMatch\n for (const b of bodySegments) {\n b[1] = fileLength - ((nonGsPartsSums[i--] as number) + b[0].length)\n }\n\n return !!this.#matchGlobStarBodySections(\n file,\n bodySegments,\n fileIndex,\n 0,\n partial,\n 0,\n !!fileTailMatch,\n )\n }\n\n // return false for \"nope, not matching\"\n // return null for \"not matching, cannot keep trying\"\n #matchGlobStarBodySections(\n file: string[],\n // pattern section, last possible position for it\n bodySegments: [ParseReturn[], number][],\n fileIndex: number,\n bodyIndex: number,\n partial: boolean,\n globStarDepth: number,\n sawTail: boolean,\n ): boolean | null {\n // take the first body segment, and walk from fileIndex to its \"after\"\n // value at the end\n // If it doesn't match at that position, we increment, until we hit\n // that final possible position, and give up.\n // If it does match, then advance and try to rest.\n // If any of them fail we keep walking forward.\n // this is still a bit recursively painful, but it's more constrained\n // than previous implementations, because we never test something that\n // can't possibly be a valid matching condition.\n const bs = bodySegments[bodyIndex]\n if (!bs) {\n // just make sure that there's no bad dots\n for (let i = fileIndex; i < file.length; i++) {\n sawTail = true\n const f = file[i]\n if (\n f === '.' ||\n f === '..' ||\n (!this.options.dot && f.startsWith('.'))\n ) {\n return false\n }\n }\n return sawTail\n }\n\n // have a non-globstar body section to test\n const [body, after] = bs\n while (fileIndex <= after) {\n const m = this.#matchOne(\n file.slice(0, fileIndex + body.length),\n body,\n partial,\n fileIndex,\n 0,\n )\n // if limit exceeded, no match. intentional false negative,\n // acceptable break in correctness for security.\n if (m && globStarDepth < this.maxGlobstarRecursion) {\n // match! see if the rest match. if so, we're done!\n const sub = this.#matchGlobStarBodySections(\n file,\n bodySegments,\n fileIndex + body.length,\n bodyIndex + 1,\n partial,\n globStarDepth + 1,\n sawTail,\n )\n if (sub !== false) {\n return sub\n }\n }\n const f = file[fileIndex]\n if (\n f === '.' ||\n f === '..' ||\n (!this.options.dot && f.startsWith('.'))\n ) {\n return false\n }\n\n fileIndex++\n }\n // walked off. no point continuing\n return partial || null\n }\n\n #matchOne(\n file: string[],\n pattern: ParseReturn[],\n partial: boolean,\n fileIndex: number,\n patternIndex: number,\n ) {\n let fi: number\n let pi: number\n let pl: number\n let fl: number\n for (\n fi = fileIndex,\n pi = patternIndex,\n fl = file.length,\n pl = pattern.length;\n fi < fl && pi < pl;\n fi++, pi++\n ) {\n this.debug('matchOne loop')\n let p = pattern[pi]\n let f = file[fi]\n\n this.debug(pattern, p, f)\n\n // should be impossible.\n // some invalid regexp stuff in the set.\n /* c8 ignore start */\n if (p === false || p === GLOBSTAR) {\n return false\n }\n /* c8 ignore stop */\n\n // something other than **\n // non-magic patterns just have to match exactly\n // patterns with magic have been turned into regexps.\n let hit: boolean\n if (typeof p === 'string') {\n hit = f === p\n this.debug('string match', p, f, hit)\n } else {\n hit = p.test(f)\n this.debug('pattern match', p, f, hit)\n }\n\n if (!hit) return false\n }\n\n // Note: ending in / means that we'll get a final \"\"\n // at the end of the pattern. This can only match a\n // corresponding \"\" at the end of the file.\n // If the file ends in /, then it can only match a\n // a pattern that ends in /, unless the pattern just\n // doesn't have any more for it. But, a/b/ should *not*\n // match \"a/b/*\", even though \"\" matches against the\n // [^/]*? pattern, except in partial mode, where it might\n // simply not be reached yet.\n // However, a/b/ should still satisfy a/*\n\n // now either we fell off the end of the pattern, or we're done.\n if (fi === fl && pi === pl) {\n // ran out of pattern and filename at the same time.\n // an exact hit!\n return true\n } else if (fi === fl) {\n // ran out of file, but still had pattern left.\n // this is ok if we're doing the match as part of\n // a glob fs traversal.\n return partial\n } else if (pi === pl) {\n // ran out of pattern, still have file left.\n // this is only acceptable if we're on the very last\n // empty segment of a file with a trailing slash.\n // a/* should match a/b/\n return fi === fl - 1 && file[fi] === ''\n\n /* c8 ignore start */\n } else {\n // should be unreachable.\n throw new Error('wtf?')\n }\n /* c8 ignore stop */\n }\n\n braceExpand() {\n return braceExpand(this.pattern, this.options)\n }\n\n parse(pattern: string): ParseReturn {\n assertValidPattern(pattern)\n\n const options = this.options\n\n // shortcuts\n if (pattern === '**') return GLOBSTAR\n if (pattern === '') return ''\n\n // far and away, the most common glob pattern parts are\n // *, *.*, and *.<ext> Add a fast check method for those.\n let m: RegExpMatchArray | null\n let fastTest: null | ((f: string) => boolean) = null\n if ((m = pattern.match(starRE))) {\n fastTest = options.dot ? starTestDot : starTest\n } else if ((m = pattern.match(starDotExtRE))) {\n fastTest = (\n options.nocase ?\n options.dot ?\n starDotExtTestNocaseDot\n : starDotExtTestNocase\n : options.dot ? starDotExtTestDot\n : starDotExtTest)(m[1])\n } else if ((m = pattern.match(qmarksRE))) {\n fastTest = (\n options.nocase ?\n options.dot ?\n qmarksTestNocaseDot\n : qmarksTestNocase\n : options.dot ? qmarksTestDot\n : qmarksTest)(m)\n } else if ((m = pattern.match(starDotStarRE))) {\n fastTest = options.dot ? starDotStarTestDot : starDotStarTest\n } else if ((m = pattern.match(dotStarRE))) {\n fastTest = dotStarTest\n }\n\n const re = AST.fromGlob(pattern, this.options).toMMPattern()\n if (fastTest && typeof re === 'object') {\n // Avoids overriding in frozen environments\n Reflect.defineProperty(re, 'test', { value: fastTest })\n }\n return re\n }\n\n makeRe() {\n if (this.regexp || this.regexp === false) return this.regexp\n\n // at this point, this.set is a 2d array of partial\n // pattern strings, or \"**\".\n //\n // It's better to use .match(). This function shouldn't\n // be used, really, but it's pretty convenient sometimes,\n // when you just want to work with a regex.\n const set = this.set\n\n if (!set.length) {\n this.regexp = false\n return this.regexp\n }\n const options = this.options\n\n const twoStar =\n options.noglobstar ? star\n : options.dot ? twoStarDot\n : twoStarNoDot\n const flags = new Set(options.nocase ? ['i'] : [])\n\n // regexpify non-globstar patterns\n // if ** is only item, then we just do one twoStar\n // if ** is first, and there are more, prepend (\\/|twoStar\\/)? to next\n // if ** is last, append (\\/twoStar|) to previous\n // if ** is in the middle, append (\\/|\\/twoStar\\/) to previous\n // then filter out GLOBSTAR symbols\n let re = set\n .map(pattern => {\n const pp: (string | typeof GLOBSTAR)[] = pattern.map(p => {\n if (p instanceof RegExp) {\n for (const f of p.flags.split('')) flags.add(f)\n }\n return (\n typeof p === 'string' ? regExpEscape(p)\n : p === GLOBSTAR ? GLOBSTAR\n : p._src\n )\n }) as (string | typeof GLOBSTAR)[]\n pp.forEach((p, i) => {\n const next = pp[i + 1]\n const prev = pp[i - 1]\n if (p !== GLOBSTAR || prev === GLOBSTAR) {\n return\n }\n if (prev === undefined) {\n if (next !== undefined && next !== GLOBSTAR) {\n pp[i + 1] = '(?:\\\\/|' + twoStar + '\\\\/)?' + next\n } else {\n pp[i] = twoStar\n }\n } else if (next === undefined) {\n pp[i - 1] = prev + '(?:\\\\/|\\\\/' + twoStar + ')?'\n } else if (next !== GLOBSTAR) {\n pp[i - 1] = prev + '(?:\\\\/|\\\\/' + twoStar + '\\\\/)' + next\n pp[i + 1] = GLOBSTAR\n }\n })\n const filtered = pp.filter(p => p !== GLOBSTAR)\n\n // For partial matches, we need to make the pattern match\n // any prefix of the full path. We do this by generating\n // alternative patterns that match progressively longer prefixes.\n if (this.partial && filtered.length >= 1) {\n const prefixes: string[] = []\n for (let i = 1; i <= filtered.length; i++) {\n prefixes.push(filtered.slice(0, i).join('/'))\n }\n return '(?:' + prefixes.join('|') + ')'\n }\n\n return filtered.join('/')\n })\n .join('|')\n\n // need to wrap in parens if we had more than one thing with |,\n // otherwise only the first will be anchored to ^ and the last to $\n const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', '']\n // must match entire pattern\n // ending in a * or ** will make it less strict.\n re = '^' + open + re + close + '$'\n\n // In partial mode, '/' should always match as it's a valid prefix for any pattern\n if (this.partial) {\n re = '^(?:\\\\/|' + open + re.slice(1, -1) + close + ')$'\n }\n\n // can match anything, as long as it's not this.\n if (this.negate) re = '^(?!' + re + ').+$'\n\n try {\n this.regexp = new RegExp(re, [...flags].join(''))\n /* c8 ignore start */\n } catch {\n // should be impossible\n this.regexp = false\n }\n /* c8 ignore stop */\n return this.regexp\n }\n\n slashSplit(p: string) {\n // if p starts with // on windows, we preserve that\n // so that UNC paths aren't broken. Otherwise, any number of\n // / characters are coalesced into one, unless\n // preserveMultipleSlashes is set to true.\n if (this.preserveMultipleSlashes) {\n return p.split('/')\n } else if (this.isWindows && /^\\/\\/[^/]+/.test(p)) {\n // add an extra '' for the one we lose\n return ['', ...p.split(/\\/+/)]\n } else {\n return p.split(/\\/+/)\n }\n }\n\n match(f: string, partial = this.partial) {\n this.debug('match', f, this.pattern)\n // short-circuit in the case of busted things.\n // comments, etc.\n if (this.comment) {\n return false\n }\n if (this.empty) {\n return f === ''\n }\n\n if (f === '/' && partial) {\n return true\n }\n\n const options = this.options\n\n // windows: need to use /, not \\\n if (this.isWindows) {\n f = f.split('\\\\').join('/')\n }\n\n // treat the test path as a set of pathparts.\n const ff = this.slashSplit(f)\n this.debug(this.pattern, 'split', ff)\n\n // just ONE of the pattern sets in this.set needs to match\n // in order for it to be valid. If negating, then just one\n // match means that we have failed.\n // Either way, return on the first hit.\n\n const set = this.set\n this.debug(this.pattern, 'set', set)\n\n // Find the basename of the path by looking for the last non-empty segment\n let filename: string = ff[ff.length - 1]\n if (!filename) {\n for (let i = ff.length - 2; !filename && i >= 0; i--) {\n filename = ff[i]\n }\n }\n\n for (const pattern of set) {\n let file = ff\n if (options.matchBase && pattern.length === 1) {\n file = [filename]\n }\n const hit = this.matchOne(file, pattern, partial)\n if (hit) {\n if (options.flipNegate) {\n return true\n }\n return !this.negate\n }\n }\n\n // didn't get any hits. this is success if it's a negative\n // pattern, failure otherwise.\n if (options.flipNegate) {\n return false\n }\n return this.negate\n }\n\n static defaults(def: MinimatchOptions) {\n return minimatch.defaults(def).Minimatch\n }\n}\n/* c8 ignore start */\nexport { AST } from './ast.js'\nexport { escape } from './escape.js'\nexport { unescape } from './unescape.js'\n/* c8 ignore stop */\nminimatch.AST = AST\nminimatch.Minimatch = Minimatch\nminimatch.escape = escape\nminimatch.unescape = unescape\n","export {\n LCS,\n diffComm,\n diffIndices,\n diffPatch,\n diff3MergeRegions,\n diff3Merge,\n mergeDiff3,\n merge,\n mergeDigIn,\n patch,\n stripPatch,\n invertPatch\n};\n\n\n// Text diff algorithm following Hunt and McIlroy 1976.\n// J. W. Hunt and M. D. McIlroy, An algorithm for differential buffer\n// comparison, Bell Telephone Laboratories CSTR #41 (1976)\n// http://www.cs.dartmouth.edu/~doug/\n// https://en.wikipedia.org/wiki/Longest_common_subsequence_problem\n//\n// Expects two arrays, finds longest common sequence\nfunction LCS(buffer1, buffer2) {\n // Use a prototype-less object so input elements that happen to match\n // `Object.prototype` members (`constructor`, `__proto__`, `toString`, ...)\n // don't shadow the lookup with inherited values.\n let equivalenceClasses = Object.create(null);\n for (let j = 0; j < buffer2.length; j++) {\n const item = buffer2[j];\n if (equivalenceClasses[item]) {\n equivalenceClasses[item].push(j);\n } else {\n equivalenceClasses[item] = [j];\n }\n }\n\n const NULLRESULT = { buffer1index: -1, buffer2index: -1, chain: null };\n let candidates = [NULLRESULT];\n\n for (let i = 0; i < buffer1.length; i++) {\n const item = buffer1[i];\n const buffer2indices = equivalenceClasses[item] || [];\n let r = 0;\n let c = candidates[0];\n\n for (const j of buffer2indices) {\n let s;\n for (s = r; s < candidates.length; s++) {\n if ((candidates[s].buffer2index < j) && ((s === candidates.length - 1) || (candidates[s + 1].buffer2index > j))) {\n break;\n }\n }\n\n if (s < candidates.length) {\n const newCandidate = { buffer1index: i, buffer2index: j, chain: candidates[s] };\n if (r === candidates.length) {\n candidates.push(c);\n } else {\n candidates[r] = c;\n }\n r = s + 1;\n c = newCandidate;\n if (r === candidates.length) {\n break; // no point in examining further (j)s\n }\n }\n }\n\n candidates[r] = c;\n }\n\n // At this point, we know the LCS: it's in the reverse of the\n // linked-list through .chain of candidates[candidates.length - 1].\n\n return candidates[candidates.length - 1];\n}\n\n\n// We apply the LCS to build a 'comm'-style picture of the\n// differences between buffer1 and buffer2.\nfunction diffComm(buffer1, buffer2) {\n const lcs = LCS(buffer1, buffer2);\n let result = [];\n let tail1 = buffer1.length;\n let tail2 = buffer2.length;\n let common = {common: []};\n\n function processCommon() {\n if (common.common.length) {\n common.common.reverse();\n result.push(common);\n common = {common: []};\n }\n }\n\n for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {\n let different = {buffer1: [], buffer2: []};\n\n while (--tail1 > candidate.buffer1index) {\n different.buffer1.push(buffer1[tail1]);\n }\n\n while (--tail2 > candidate.buffer2index) {\n different.buffer2.push(buffer2[tail2]);\n }\n\n if (different.buffer1.length || different.buffer2.length) {\n processCommon();\n different.buffer1.reverse();\n different.buffer2.reverse();\n result.push(different);\n }\n\n if (tail1 >= 0) {\n common.common.push(buffer1[tail1]);\n }\n }\n\n processCommon();\n\n result.reverse();\n return result;\n}\n\n\n// We apply the LCS to give a simple representation of the\n// offsets and lengths of mismatched chunks in the input\n// buffers. This is used by diff3MergeRegions.\nfunction diffIndices(buffer1, buffer2) {\n const lcs = LCS(buffer1, buffer2);\n let result = [];\n let tail1 = buffer1.length;\n let tail2 = buffer2.length;\n\n for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {\n const mismatchLength1 = tail1 - candidate.buffer1index - 1;\n const mismatchLength2 = tail2 - candidate.buffer2index - 1;\n tail1 = candidate.buffer1index;\n tail2 = candidate.buffer2index;\n\n if (mismatchLength1 || mismatchLength2) {\n result.push({\n buffer1: [tail1 + 1, mismatchLength1],\n buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1),\n buffer2: [tail2 + 1, mismatchLength2],\n buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2)\n });\n }\n }\n\n result.reverse();\n return result;\n}\n\n\n// We apply the LCS to build a JSON representation of a\n// diff(1)-style patch.\nfunction diffPatch(buffer1, buffer2) {\n const lcs = LCS(buffer1, buffer2);\n let result = [];\n let tail1 = buffer1.length;\n let tail2 = buffer2.length;\n\n function chunkDescription(buffer, offset, length) {\n let chunk = [];\n for (let i = 0; i < length; i++) {\n chunk.push(buffer[offset + i]);\n }\n return {\n offset: offset,\n length: length,\n chunk: chunk\n };\n }\n\n for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {\n const mismatchLength1 = tail1 - candidate.buffer1index - 1;\n const mismatchLength2 = tail2 - candidate.buffer2index - 1;\n tail1 = candidate.buffer1index;\n tail2 = candidate.buffer2index;\n\n if (mismatchLength1 || mismatchLength2) {\n result.push({\n buffer1: chunkDescription(buffer1, candidate.buffer1index + 1, mismatchLength1),\n buffer2: chunkDescription(buffer2, candidate.buffer2index + 1, mismatchLength2)\n });\n }\n }\n\n result.reverse();\n return result;\n}\n\n\n// Given three buffers, A, O, and B, where both A and B are\n// independently derived from O, returns a fairly complicated\n// internal representation of merge decisions it's taken. The\n// interested reader may wish to consult\n//\n// Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce.\n// 'A Formal Investigation of ' In Arvind and Prasad,\n// editors, Foundations of Software Technology and Theoretical\n// Computer Science (FSTTCS), December 2007.\n//\n// (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)\n//\nfunction diff3MergeRegions(a, o, b) {\n\n // \"hunks\" are array subsets where `a` or `b` are different from `o`\n // https://www.gnu.org/software/diffutils/manual/html_node/diff3-Hunks.html\n let hunks = [];\n function addHunk(h, ab) {\n hunks.push({\n ab: ab,\n oStart: h.buffer1[0],\n oLength: h.buffer1[1], // length of o to remove\n abStart: h.buffer2[0],\n abLength: h.buffer2[1] // length of a/b to insert\n // abContent: (ab === 'a' ? a : b).slice(h.buffer2[0], h.buffer2[0] + h.buffer2[1])\n });\n }\n\n diffIndices(o, a).forEach(item => addHunk(item, 'a'));\n diffIndices(o, b).forEach(item => addHunk(item, 'b'));\n hunks.sort((x,y) => x.oStart - y.oStart);\n\n let results = [];\n let currOffset = 0;\n\n function advanceTo(endOffset) {\n if (endOffset > currOffset) {\n results.push({\n stable: true,\n buffer: 'o',\n bufferStart: currOffset,\n bufferLength: endOffset - currOffset,\n bufferContent: o.slice(currOffset, endOffset)\n });\n currOffset = endOffset;\n }\n }\n\n while (hunks.length) {\n let hunk = hunks.shift();\n let regionStart = hunk.oStart;\n let regionEnd = hunk.oStart + hunk.oLength;\n let regionHunks = [hunk];\n advanceTo(regionStart);\n\n // Try to pull next overlapping hunk into this region\n while (hunks.length) {\n const nextHunk = hunks[0];\n const nextHunkStart = nextHunk.oStart;\n if (nextHunkStart > regionEnd) break; // no overlap\n\n regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength);\n regionHunks.push(hunks.shift());\n }\n\n if (regionHunks.length === 1) {\n // Only one hunk touches this region, meaning that there is no conflict here.\n // Either `a` or `b` is inserting into a region of `o` unchanged by the other.\n if (hunk.abLength > 0) {\n const buffer = (hunk.ab === 'a' ? a : b);\n results.push({\n stable: true,\n buffer: hunk.ab,\n bufferStart: hunk.abStart,\n bufferLength: hunk.abLength,\n bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength)\n });\n }\n } else {\n // A true a/b conflict. Determine the bounds involved from `a`, `o`, and `b`.\n // Effectively merge all the `a` hunks into one giant hunk, then do the\n // same for the `b` hunks; then, correct for skew in the regions of `o`\n // that each side changed, and report appropriate spans for the three sides.\n let bounds = {\n a: [a.length, -1, o.length, -1],\n b: [b.length, -1, o.length, -1]\n };\n while (regionHunks.length) {\n hunk = regionHunks.shift();\n const oStart = hunk.oStart;\n const oEnd = oStart + hunk.oLength;\n const abStart = hunk.abStart;\n const abEnd = abStart + hunk.abLength;\n let b = bounds[hunk.ab];\n b[0] = Math.min(abStart, b[0]);\n b[1] = Math.max(abEnd, b[1]);\n b[2] = Math.min(oStart, b[2]);\n b[3] = Math.max(oEnd, b[3]);\n }\n\n const aStart = bounds.a[0] + (regionStart - bounds.a[2]);\n const aEnd = bounds.a[1] + (regionEnd - bounds.a[3]);\n const bStart = bounds.b[0] + (regionStart - bounds.b[2]);\n const bEnd = bounds.b[1] + (regionEnd - bounds.b[3]);\n\n let result = {\n stable: false,\n aStart: aStart,\n aLength: aEnd - aStart,\n aContent: a.slice(aStart, aEnd),\n oStart: regionStart,\n oLength: regionEnd - regionStart,\n oContent: o.slice(regionStart, regionEnd),\n bStart: bStart,\n bLength: bEnd - bStart,\n bContent: b.slice(bStart, bEnd)\n };\n results.push(result);\n }\n currOffset = regionEnd;\n }\n\n advanceTo(o.length);\n\n return results;\n}\n\n\n// Applies the output of diff3MergeRegions to actually\n// construct the merged buffer; the returned result alternates\n// between 'ok' and 'conflict' blocks.\n// A \"false conflict\" is where `a` and `b` both change the same from `o`\nfunction diff3Merge(a, o, b, options) {\n let defaults = {\n excludeFalseConflicts: true,\n stringSeparator: /\\s+/\n };\n options = Object.assign(defaults, options);\n\n if (typeof a === 'string') a = a.split(options.stringSeparator);\n if (typeof o === 'string') o = o.split(options.stringSeparator);\n if (typeof b === 'string') b = b.split(options.stringSeparator);\n\n let results = [];\n const regions = diff3MergeRegions(a, o, b);\n\n let okBuffer = [];\n function flushOk() {\n if (okBuffer.length) {\n results.push({ ok: okBuffer });\n }\n okBuffer = [];\n }\n\n function isFalseConflict(a, b) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n regions.forEach(region => {\n if (region.stable) {\n okBuffer.push(...region.bufferContent);\n } else {\n if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) {\n okBuffer.push(...region.aContent);\n } else {\n flushOk();\n results.push({\n conflict: {\n a: region.aContent,\n aIndex: region.aStart,\n o: region.oContent,\n oIndex: region.oStart,\n b: region.bContent,\n bIndex: region.bStart\n }\n });\n }\n }\n });\n\n flushOk();\n return results;\n}\n\n\nfunction mergeDiff3(a, o, b, options) {\n const defaults = {\n excludeFalseConflicts: true,\n stringSeparator: /\\s+/,\n label: {}\n };\n options = Object.assign(defaults, options);\n\n const aSection = '<<<<<<<' + (options.label.a ? ` ${options.label.a}` : '');\n const oSection = '|||||||' + (options.label.o ? ` ${options.label.o}` : '');\n const xSection = '=======';\n const bSection = '>>>>>>>' + (options.label.b ? ` ${options.label.b}` : '');\n\n const regions = diff3Merge(a, o, b, options);\n let conflict = false;\n let result = [];\n\n regions.forEach(region => {\n if (region.ok) {\n result = result.concat(region.ok);\n } else if (region.conflict) {\n conflict = true;\n result = result.concat(\n [aSection],\n region.conflict.a,\n [oSection],\n region.conflict.o,\n [xSection],\n region.conflict.b,\n [bSection]\n );\n }\n });\n\n return {\n conflict: conflict,\n result: result\n };\n}\n\n\nfunction merge(a, o, b, options) {\n const defaults = {\n excludeFalseConflicts: true,\n stringSeparator: /\\s+/,\n label: {}\n };\n options = Object.assign(defaults, options);\n\n const aSection = '<<<<<<<' + (options.label.a ? ` ${options.label.a}` : '');\n const xSection = '=======';\n const bSection = '>>>>>>>' + (options.label.b ? ` ${options.label.b}` : '');\n\n const regions = diff3Merge(a, o, b, options);\n let conflict = false;\n let result = [];\n\n regions.forEach(region => {\n if (region.ok) {\n result = result.concat(region.ok);\n } else if (region.conflict) {\n conflict = true;\n result = result.concat(\n [aSection],\n region.conflict.a,\n [xSection],\n region.conflict.b,\n [bSection]\n );\n }\n });\n\n return {\n conflict: conflict,\n result: result\n };\n}\n\n\nfunction mergeDigIn(a, o, b, options) {\n const defaults = {\n excludeFalseConflicts: true,\n stringSeparator: /\\s+/,\n label: {}\n };\n options = Object.assign(defaults, options);\n\n const aSection = '<<<<<<<' + (options.label.a ? ` ${options.label.a}` : '');\n const xSection = '=======';\n const bSection = '>>>>>>>' + (options.label.b ? ` ${options.label.b}` : '');\n\n const regions = diff3Merge(a, o, b, options);\n let conflict = false;\n let result = [];\n\n regions.forEach(region => {\n if (region.ok) {\n result = result.concat(region.ok);\n } else {\n const c = diffComm(region.conflict.a, region.conflict.b);\n for (const inner of c) {\n if (inner.common) {\n result = result.concat(inner.common);\n } else {\n conflict = true;\n result = result.concat(\n [aSection],\n inner.buffer1,\n [xSection],\n inner.buffer2,\n [bSection]\n );\n }\n }\n }\n });\n\n return {\n conflict: conflict,\n result: result\n };\n}\n\n\n// Applies a patch to a buffer.\n// Given buffer1 and buffer2, `patch(buffer1, diffPatch(buffer1, buffer2))` should give buffer2.\nfunction patch(buffer, patch) {\n let result = [];\n let currOffset = 0;\n\n function advanceTo(targetOffset) {\n while (currOffset < targetOffset) {\n result.push(buffer[currOffset]);\n currOffset++;\n }\n }\n\n for (const chunk of patch) {\n advanceTo(chunk.buffer1.offset);\n for (const item of chunk.buffer2.chunk) {\n result.push(item);\n }\n currOffset += chunk.buffer1.length;\n }\n\n advanceTo(buffer.length);\n return result;\n}\n\n\n// Takes the output of diffPatch(), and removes extra information from it.\n// It can still be used by patch(), below, but can no longer be inverted.\nfunction stripPatch(patch) {\n return patch.map(chunk => ({\n buffer1: { offset: chunk.buffer1.offset, length: chunk.buffer1.length },\n buffer2: { chunk: chunk.buffer2.chunk }\n }));\n}\n\n\n// Takes the output of diffPatch(), and inverts the sense of it, so that it\n// can be applied to buffer2 to give buffer1 rather than the other way around.\nfunction invertPatch(patch) {\n return patch.map(chunk => ({\n buffer1: chunk.buffer2,\n buffer2: chunk.buffer1\n }));\n}\n","import {\n ExtendedBaseAPI,\n HttpRequestScheduler,\n RemoteProject,\n SocketIOAPI,\n getServerSession,\n normalizeServerUrl,\n readConfig,\n removeKnownServer,\n removeServerSession,\n saveKnownServer,\n saveServerSession,\n serverKey,\n type Identity,\n type ServeRemoteProject,\n type ServerSession,\n} from '@leafrelay/core';\nimport type {\n ProjectEventNotification,\n ProjectOpenResult,\n ServerDescriptor,\n ServerImportParams,\n ServerLoginParams,\n} from '@leafrelay/protocol';\n\nconst PROJECT_IDLE_MS = 60_000;\n\nconst SERVER_OPERATIONS = new Set([\n 'userProjectsJson', 'getProjectsJson', 'projectEntitiesJson',\n 'newProject', 'cloneProject', 'renameProject', 'deleteProject',\n 'archiveProject', 'unarchiveProject', 'trashProject', 'untrashProject',\n 'getFile', 'addDoc', 'uploadFile', 'uploadProject', 'addFolder',\n 'deleteEntity', 'deleteAuxFiles', 'renameEntity', 'moveEntity',\n 'compile', 'stopCompile', 'indexAll', 'getMetadata',\n 'proxyRequestToSpellingApi', 'spellingControllerLearn', 'spellingControllerUnlearn',\n 'getProjectSettings', 'updateProjectSettings', 'getFileFromClsi',\n 'proxySyncPdf', 'proxySyncCode', 'getAllTags', 'createTag', 'renameTag',\n 'deleteTag', 'addProjectToTag', 'removeProjectFromTag',\n 'proxyToHistoryApiAndGetUpdates', 'proxyToHistoryApiAndGetFileDiff',\n 'proxyToHistoryApiAndGetFileTreeDiff', 'downloadZipOfVersion',\n 'getLabels', 'createLabel', 'deleteLabel', 'getMessages', 'sendMessage',\n 'refreshLinkedFile', 'createLinkedFile',\n]);\n\nconst PROJECT_OPERATIONS = new Set([\n 'init', 'joinProject', 'joinDoc', 'leaveDoc', 'applyOtUpdate',\n 'getConnectedUsers', 'updatePosition', 'syncFileChanges',\n]);\n\nconst REMOTE_PROJECT_OPERATIONS = new Set([\n 'entry', 'listEntries', 'read', 'write', 'mkdir', 'remove',\n 'getCurrentVersion', 'getFileTreeDiff',\n]);\n\ninterface ServerRuntime {\n key:string;\n session:ServerSession;\n scheduler:HttpRequestScheduler;\n api:ExtendedBaseAPI;\n}\n\ninterface ProjectRuntime {\n key:string;\n server:ServerRuntime;\n projectId:string;\n socket:SocketIOAPI;\n remote:RemoteProject;\n ready:Promise<void>;\n owners:Set<string>;\n replicaReferences:number;\n operationQueue:Promise<void>;\n idleTimer?:NodeJS.Timeout;\n}\n\nexport interface ProjectLease {\n remote:ServeRemoteProject;\n release():void;\n}\n\nexport interface NetworkRuntimeEvents {\n projectEvent:(owners:ReadonlySet<string>, event:ProjectEventNotification) => void;\n log:(level:'info'|'warn'|'error', message:string) => void;\n}\n\nexport class NetworkRuntimeRegistry {\n private readonly servers = new Map<string,ServerRuntime>();\n private readonly projects = new Map<string,ProjectRuntime>();\n\n constructor(private readonly events:NetworkRuntimeEvents) {}\n\n get projectCount():number { return this.projects.size; }\n\n async listServers():Promise<ServerDescriptor[]> {\n const config = await readConfig();\n const keys = new Set([...Object.keys(config.knownServers ?? {}), ...Object.keys(config.servers)]);\n if (keys.size===0) { keys.add('www.overleaf.com'); }\n return [...keys].sort().map(key => {\n const session = config.servers[key];\n const known = config.knownServers?.[key];\n return {\n name:known?.name ?? key,\n url:known?.url ?? session?.url ?? normalizeServerUrl(key),\n loggedIn:Boolean(session),\n userId:session?.userId,\n userEmail:session?.userEmail,\n };\n });\n }\n\n async addServer(name:string, url:string):Promise<void> {\n await saveKnownServer(name, url);\n }\n\n async removeServer(server:string):Promise<void> {\n const key = serverKey(server);\n for (const project of this.projects.values()) {\n if (project.server.key===key) { await this.stopProject(project); }\n }\n this.servers.delete(key);\n await removeKnownServer(server);\n }\n\n async login(params:ServerLoginParams) {\n const url = normalizeServerUrl(params.server);\n const scheduler = new HttpRequestScheduler({\n onRateLimit:until => this.events.log('warn', `${serverKey(url)} is rate limited until ${new Date(until).toISOString()}.`),\n });\n const api = new ExtendedBaseAPI(url, scheduler);\n const response = params.cookie\n ? await api.cookiesLogin(params.cookie)\n : await api.passportLogin(params.email ?? '', params.password ?? '');\n if (response.type!=='success' || !response.identity || !response.userInfo) {\n throw new Error(response.message || `Login to ${url} failed.`);\n }\n const session:ServerSession = {\n url,\n userId:response.userInfo.userId,\n userEmail:response.userInfo.userEmail || params.email || '',\n identity:response.identity,\n updatedAt:new Date().toISOString(),\n };\n await saveServerSession(session);\n this.servers.set(serverKey(url), {key:serverKey(url), session, scheduler, api});\n return {userId:session.userId, userEmail:session.userEmail};\n }\n\n async importSession(params:ServerImportParams) {\n const result = await this.login({server:params.url, cookie:params.identity.cookies});\n await saveKnownServer(params.name, params.url);\n return result;\n }\n\n async logout(server:string):Promise<void> {\n const runtime = await this.requireServer(server);\n await runtime.api.logout(runtime.session.identity);\n await removeServerSession(server);\n this.servers.delete(runtime.key);\n }\n\n async callServer(server:string, operation:string, args:unknown[]):Promise<unknown> {\n if (!SERVER_OPERATIONS.has(operation)) { throw new Error(`Unsupported server operation: ${operation}.`); }\n const runtime = await this.requireServer(server);\n const method = (runtime.api as unknown as Record<string,unknown>)[operation];\n if (typeof method!=='function') { throw new Error(`Server operation ${operation} is unavailable.`); }\n return (method as (...values:unknown[]) => Promise<unknown>).call(runtime.api, runtime.session.identity, ...args);\n }\n\n async openProject(clientId:string, server:string, projectId:string):Promise<ProjectOpenResult> {\n const runtime = await this.getOrCreateProject(server, projectId);\n const shared = runtime.owners.size!==0 || runtime.replicaReferences!==0;\n if (runtime.idleTimer) { clearTimeout(runtime.idleTimer); runtime.idleTimer = undefined; }\n runtime.owners.add(clientId);\n await runtime.ready;\n return {projectKey:runtime.key, shared};\n }\n\n closeProject(clientId:string, projectKey:string):void {\n const runtime = this.requireProject(projectKey);\n runtime.owners.delete(clientId);\n this.scheduleProjectStop(runtime);\n }\n\n async callProject(projectKey:string, operation:string, args:unknown[]):Promise<unknown> {\n const runtime = this.requireProject(projectKey);\n await runtime.ready;\n if (operation.startsWith('remote.')) {\n const remoteOperation = operation.slice('remote.'.length);\n if (!REMOTE_PROJECT_OPERATIONS.has(remoteOperation)) {\n throw new Error(`Unsupported remote project operation: ${remoteOperation}.`);\n }\n const method = (runtime.remote as unknown as Record<string,unknown>)[remoteOperation];\n if (typeof method!=='function') { throw new Error(`Remote project operation ${remoteOperation} is unavailable.`); }\n return this.enqueueProjectOperation(runtime, () => (\n (method as (...values:unknown[]) => unknown).apply(runtime.remote, args)\n ));\n }\n if (!PROJECT_OPERATIONS.has(operation)) { throw new Error(`Unsupported project operation: ${operation}.`); }\n const method = (runtime.socket as unknown as Record<string,unknown>)[operation];\n if (typeof method!=='function') { throw new Error(`Project operation ${operation} is unavailable.`); }\n return (method as (...values:unknown[]) => unknown).apply(runtime.socket, args);\n }\n\n async acquireReplica(server:string, projectId:string):Promise<ProjectLease> {\n const runtime = await this.getOrCreateProject(server, projectId);\n if (runtime.idleTimer) { clearTimeout(runtime.idleTimer); runtime.idleTimer = undefined; }\n runtime.replicaReferences += 1;\n await runtime.ready;\n let released = false;\n return {\n remote:this.replicaRemote(runtime),\n release:() => {\n if (released) { return; }\n released = true;\n runtime.replicaReferences -= 1;\n this.scheduleProjectStop(runtime);\n },\n };\n }\n\n detachClient(clientId:string):void {\n for (const runtime of this.projects.values()) {\n if (runtime.owners.delete(clientId)) { this.scheduleProjectStop(runtime); }\n }\n }\n\n async stopAll():Promise<void> {\n await Promise.all([...this.projects.values()].map(runtime => this.stopProject(runtime)));\n this.servers.clear();\n }\n\n private async requireServer(server:string):Promise<ServerRuntime> {\n const key = serverKey(server);\n const existing = this.servers.get(key);\n if (existing) { return existing; }\n const session = await getServerSession(server);\n if (!session) { throw new Error(`Not logged in to ${key}.`); }\n const scheduler = new HttpRequestScheduler({\n onRateLimit:until => this.events.log('warn', `${key} is rate limited until ${new Date(until).toISOString()}.`),\n });\n const runtime = {key, session, scheduler, api:new ExtendedBaseAPI(session.url, scheduler)};\n this.servers.set(key, runtime);\n return runtime;\n }\n\n private async getOrCreateProject(server:string, projectId:string):Promise<ProjectRuntime> {\n const serverRuntime = await this.requireServer(server);\n const key = `${serverRuntime.key}:${projectId}`;\n const existing = this.projects.get(key);\n if (existing) { return existing; }\n const socket = new SocketIOAPI(serverRuntime.session.url, serverRuntime.api, serverRuntime.session.identity, projectId);\n const remote = new RemoteProject(\n serverRuntime.session.url,\n projectId,\n serverRuntime.session.identity.cookies,\n {api:serverRuntime.api, identity:serverRuntime.session.identity, socket},\n );\n const runtime:ProjectRuntime = {\n key,\n server:serverRuntime,\n projectId,\n socket,\n remote,\n ready:Promise.resolve(),\n owners:new Set(),\n replicaReferences:0,\n operationQueue:Promise.resolve(),\n };\n runtime.ready = remote.connect().then(() => this.registerProjectEvents(runtime)).catch(error => {\n this.projects.delete(key);\n socket.disconnect();\n throw error;\n });\n this.projects.set(key, runtime);\n return runtime;\n }\n\n private registerProjectEvents(runtime:ProjectRuntime):void {\n const emit = (event:string, ...args:unknown[]) => this.events.projectEvent(runtime.owners, {\n projectKey:runtime.key,\n event,\n args,\n });\n runtime.socket.updateEventHandlers({\n onFileCreated:(...args) => emit('onFileCreated', ...args),\n onFileRenamed:(...args) => emit('onFileRenamed', ...args),\n onFileRemoved:(...args) => emit('onFileRemoved', ...args),\n onFileMoved:(...args) => emit('onFileMoved', ...args),\n onFileChanged:(...args) => emit('onFileChanged', ...args),\n onDisconnected:(reason) => emit('onDisconnected', reason),\n onConnectionAccepted:(...args) => emit('onConnectionAccepted', ...args),\n onClientUpdated:(...args) => emit('onClientUpdated', ...args),\n onClientDisconnected:(...args) => emit('onClientDisconnected', ...args),\n onReceivedMessage:(...args) => emit('onReceivedMessage', ...args),\n onSpellCheckLanguageUpdated:(...args) => emit('onSpellCheckLanguageUpdated', ...args),\n onCompilerUpdated:(...args) => emit('onCompilerUpdated', ...args),\n onRootDocUpdated:(...args) => emit('onRootDocUpdated', ...args),\n });\n }\n\n private requireProject(projectKey:string):ProjectRuntime {\n const runtime = this.projects.get(projectKey);\n if (!runtime) { throw new Error(`Unknown project runtime ${projectKey}.`); }\n return runtime;\n }\n\n private replicaRemote(runtime:ProjectRuntime):ServeRemoteProject {\n return {\n connect:async () => {},\n disconnect:() => {},\n listEntries:() => runtime.remote.listEntries(),\n entry:path => runtime.remote.entry(path),\n read:path => this.enqueueProjectOperation(runtime, () => runtime.remote.read(path)),\n write:(path, content) => this.enqueueProjectOperation(runtime, () => runtime.remote.write(path, content)),\n remove:path => this.enqueueProjectOperation(runtime, () => runtime.remote.remove(path)),\n getCurrentVersion:() => this.enqueueProjectOperation(runtime, () => runtime.remote.getCurrentVersion()),\n getFileTreeDiff:(from, to) => this.enqueueProjectOperation(runtime, () => runtime.remote.getFileTreeDiff(from, to)),\n onChange:handler => runtime.remote.onChange(handler),\n onReconnect:handler => runtime.remote.onReconnect(handler),\n };\n }\n\n private enqueueProjectOperation<T>(runtime:ProjectRuntime, operation:() => T|Promise<T>):Promise<T> {\n const result = runtime.operationQueue.then(operation);\n runtime.operationQueue = result.then(() => undefined, () => undefined);\n return result;\n }\n\n private scheduleProjectStop(runtime:ProjectRuntime):void {\n if (runtime.owners.size!==0 || runtime.replicaReferences!==0 || runtime.idleTimer) { return; }\n runtime.idleTimer = setTimeout(() => void this.stopProject(runtime), PROJECT_IDLE_MS);\n runtime.idleTimer.unref();\n }\n\n private async stopProject(runtime:ProjectRuntime):Promise<void> {\n if (!this.projects.delete(runtime.key)) { return; }\n if (runtime.idleTimer) { clearTimeout(runtime.idleTimer); }\n runtime.socket.disconnect();\n }\n}\n","import {randomUUID} from 'node:crypto';\nimport {realpath} from 'node:fs/promises';\nimport {resolve} from 'node:path';\nimport {readProjectSettings, startServe, type RunningServe} from '@leafrelay/core';\nimport type {\n ReplicaAttachParams,\n ReplicaAttachResult,\n ReplicaConflictNotification,\n ReplicaStatus,\n ReplicaStatusNotification,\n} from '@leafrelay/protocol';\n\nconst DETACHED_REPLICA_GRACE_MS = 60_000;\n\ninterface ReplicaEntry {\n id:string;\n root:string;\n projectKey:string;\n serverName:string;\n projectId:string;\n projectName:string;\n owners:Set<string>;\n running:RunningServe;\n status:ReplicaStatus;\n stopTimer?:NodeJS.Timeout;\n}\n\ntype ReplicaStarter = (directory:string, options:NonNullable<Parameters<typeof startServe>[1]>) => Promise<RunningServe>;\n\nexport class ReplicaAlreadyActiveError extends Error {\n readonly code = 'ReplicaAlreadyActive';\n\n constructor(readonly projectId:string, readonly activeRoot:string, readonly requestedRoot:string) {\n super(`Overleaf project ${projectId} is already synchronized by ${activeRoot}; ${requestedRoot} cannot become a second writable replica.`);\n }\n}\n\nexport interface ReplicaRegistryEvents {\n status:(owners:ReadonlySet<string>, notification:ReplicaStatusNotification) => void;\n conflict:(owners:ReadonlySet<string>, notification:ReplicaConflictNotification) => void;\n empty:() => void;\n log:(message:string) => void;\n}\n\nexport class ReplicaRegistry {\n private readonly byId = new Map<string,ReplicaEntry>();\n private readonly byRoot = new Map<string,ReplicaEntry>();\n private readonly byProject = new Map<string,ReplicaEntry>();\n private readonly projectOperations = new Map<string,Promise<void>>();\n\n constructor(\n private readonly events:ReplicaRegistryEvents,\n private readonly start:ReplicaStarter=startServe,\n ) {}\n\n get size():number { return this.byId.size; }\n\n async attach(clientId:string, params:ReplicaAttachParams):Promise<ReplicaAttachResult> {\n const root = await realpath(resolve(params.directory));\n const settings = await readProjectSettings(root);\n const projectKey = `${settings.serverName}\\0${settings.projectId}`;\n return this.withProjectLock(projectKey, () => this.attachResolved(clientId, params, root, settings, projectKey));\n }\n\n private async attachResolved(\n clientId:string,\n params:ReplicaAttachParams,\n root:string,\n settings:Awaited<ReturnType<typeof readProjectSettings>>,\n projectKey:string,\n ):Promise<ReplicaAttachResult> {\n const rootEntry = this.byRoot.get(root);\n if (rootEntry) {\n if (rootEntry.projectKey!==projectKey) {\n throw new Error(`${root} is already registered for another Overleaf project.`);\n }\n this.addOwner(rootEntry, clientId);\n return this.result(rootEntry, true);\n }\n const projectEntry = this.byProject.get(projectKey);\n if (projectEntry) {\n throw new ReplicaAlreadyActiveError(settings.projectId, projectEntry.root, root);\n }\n\n const id = randomUUID();\n const owners = new Set([clientId]);\n const status:ReplicaStatus = {state:'starting'};\n let entry:ReplicaEntry|undefined;\n this.events.status(owners, {replicaId:id, status});\n try {\n const running = await this.start(root, {\n cookie:params.cookie,\n log:message => this.events.log(`[${settings.projectName}] ${message}`),\n onConflict:(path, reason) => {\n if (!entry) { return; }\n entry.status = {state:'paused', message:`Conflict in ${path}`};\n this.events.conflict(entry.owners, {\n replicaId:entry.id,\n path,\n reason,\n conflicts:entry.running.conflicts(),\n });\n this.events.status(entry.owners, {replicaId:entry.id, status:entry.status});\n },\n });\n entry = {\n id,\n root,\n projectKey,\n serverName:settings.serverName,\n projectId:settings.projectId,\n projectName:settings.projectName,\n owners,\n running,\n status:running.conflicts().length===0 ? {state:'active'} : {state:'paused'},\n };\n this.byId.set(id, entry);\n this.byRoot.set(root, entry);\n this.byProject.set(projectKey, entry);\n this.events.status(owners, {replicaId:id, status:entry.status});\n return this.result(entry, false);\n } catch (error) {\n const failed:ReplicaStatus = {state:'error', message:error instanceof Error ? error.message : String(error)};\n this.events.status(owners, {replicaId:id, status:failed});\n throw error;\n }\n }\n\n detach(clientId:string, replicaId:string):void {\n const entry = this.require(replicaId);\n entry.owners.delete(clientId);\n this.scheduleStopWhenDetached(entry);\n }\n\n detachClient(clientId:string):void {\n for (const entry of this.byId.values()) {\n if (entry.owners.delete(clientId)) { this.scheduleStopWhenDetached(entry); }\n }\n }\n\n async resolveConflict(replicaId:string, path:string, winner:'local'|'remote'):Promise<void> {\n const entry = this.require(replicaId);\n await entry.running.resolveConflict(path, winner);\n entry.status = entry.running.conflicts().length===0 ? {state:'active'} : {state:'paused'};\n this.events.status(entry.owners, {replicaId, status:entry.status});\n }\n\n async retry(replicaId:string, path:string):Promise<void> {\n const entry = this.require(replicaId);\n await entry.running.retry(path);\n entry.status = entry.running.conflicts().length===0 ? {state:'active'} : {state:'paused'};\n this.events.status(entry.owners, {replicaId, status:entry.status});\n }\n\n list() {\n return [...this.byId.values()].map(entry => ({\n id:entry.id,\n root:entry.root,\n serverName:entry.serverName,\n projectId:entry.projectId,\n projectName:entry.projectName,\n clients:entry.owners.size,\n status:entry.status,\n conflicts:entry.running.conflicts(),\n }));\n }\n\n async stopAll():Promise<void> {\n await Promise.all([...this.byId.values()].map(entry => this.stop(entry)));\n }\n\n private addOwner(entry:ReplicaEntry, clientId:string):void {\n if (entry.stopTimer) { clearTimeout(entry.stopTimer); entry.stopTimer = undefined; }\n entry.owners.add(clientId);\n }\n\n private scheduleStopWhenDetached(entry:ReplicaEntry):void {\n if (entry.owners.size!==0 || entry.stopTimer) { return; }\n entry.stopTimer = setTimeout(() => void this.stop(entry), DETACHED_REPLICA_GRACE_MS);\n entry.stopTimer.unref();\n }\n\n private async stop(entry:ReplicaEntry):Promise<void> {\n if (!this.byId.delete(entry.id)) { return; }\n if (entry.stopTimer) { clearTimeout(entry.stopTimer); }\n this.byRoot.delete(entry.root);\n this.byProject.delete(entry.projectKey);\n entry.status = {state:'stopping'};\n this.events.status(entry.owners, {replicaId:entry.id, status:entry.status});\n await entry.running.stop();\n this.events.empty();\n }\n\n private require(replicaId:string):ReplicaEntry {\n const entry = this.byId.get(replicaId);\n if (!entry) { throw new Error(`Unknown replica ${replicaId}.`); }\n return entry;\n }\n\n private result(entry:ReplicaEntry, shared:boolean):ReplicaAttachResult {\n return {\n replicaId:entry.id,\n root:entry.root,\n serverName:entry.serverName,\n projectId:entry.projectId,\n projectName:entry.projectName,\n shared,\n status:entry.status,\n conflicts:entry.running.conflicts(),\n };\n }\n\n private async withProjectLock<T>(projectKey:string, operation:() => Promise<T>):Promise<T> {\n const previous = this.projectOperations.get(projectKey) ?? Promise.resolve();\n let release!:() => void;\n const current = new Promise<void>(resolveOperation => { release = resolveOperation; });\n this.projectOperations.set(projectKey, current);\n await previous;\n try {\n return await operation();\n } finally {\n release();\n if (this.projectOperations.get(projectKey)===current) { this.projectOperations.delete(projectKey); }\n }\n }\n}\n","import {randomBytes} from 'node:crypto';\nimport {appendFile, chmod, mkdir, readFile, rm, writeFile} from 'node:fs/promises';\nimport {createServer, type Server, type Socket} from 'node:net';\nimport {\n readProjectSettings,\n startServe,\n} from '@leafrelay/core';\nimport {\n LEAFRELAY_PROTOCOL_VERSION,\n RPC_METHOD,\n RPC_NOTIFICATION,\n type DaemonMetadata,\n type DaemonStatus,\n type InitializeParams,\n type InitializeResult,\n type LogNotification,\n type ReplicaAttachParams,\n type ReplicaConflictResolutionParams,\n type ReplicaStatusNotification,\n type ReplicaConflictNotification,\n type ProjectCallParams,\n type ProjectEventNotification,\n type ProjectOpenParams,\n type ServerCallParams,\n type ServerImportParams,\n type ServerLoginParams,\n} from '@leafrelay/protocol';\nimport {ResponseError, type MessageConnection} from 'vscode-jsonrpc/node';\nimport {daemonPaths, type DaemonPaths} from './paths';\nimport {decodeRpcValue, encodeRpcValue} from './codec';\nimport {NetworkRuntimeRegistry} from './networkRuntime';\nimport {ReplicaAlreadyActiveError, ReplicaRegistry} from './replicaRegistry';\nimport {createSocketRpcConnection} from './transport';\n\ndeclare const LEAFRELAY_DAEMON_VERSION:string;\n\nconst IDLE_EXIT_MS = 60_000;\nconst REPLICA_ALREADY_ACTIVE = -32010;\nconst daemonVersion = typeof LEAFRELAY_DAEMON_VERSION==='string' ? LEAFRELAY_DAEMON_VERSION : 'development';\n\ninterface ClientConnection {\n socket:Socket;\n rpc:MessageConnection;\n clientId?:string;\n initialized:boolean;\n}\n\nexport interface DaemonServerOptions {\n paths?:DaemonPaths;\n token?:string;\n exitOnIdle?:boolean;\n}\n\nexport class LeafRelayDaemonServer {\n private readonly paths:DaemonPaths;\n private readonly token:string;\n private readonly startedAt = new Date().toISOString();\n private readonly clients = new Set<ClientConnection>();\n private readonly network:NetworkRuntimeRegistry;\n private readonly replicas:ReplicaRegistry;\n private server?:Server;\n private idleTimer?:NodeJS.Timeout;\n private stopping?:Promise<void>;\n\n constructor(private readonly options:DaemonServerOptions={}) {\n this.paths = options.paths ?? daemonPaths();\n this.token = options.token ?? randomBytes(32).toString('hex');\n this.network = new NetworkRuntimeRegistry({\n projectEvent:(owners, notification) => this.notifyOwners(owners, RPC_NOTIFICATION.projectEvent, notification),\n log:(level, message) => void this.log(level, message),\n });\n this.replicas = new ReplicaRegistry({\n status:(owners, notification) => this.notifyOwners(owners, RPC_NOTIFICATION.replicaStatus, notification),\n conflict:(owners, notification) => this.notifyOwners(owners, RPC_NOTIFICATION.replicaConflict, notification),\n empty:() => this.scheduleIdleExit(),\n log:message => void this.log('info', message),\n }, async (directory, startOptions) => {\n const settings = await readProjectSettings(directory);\n const lease = await this.network.acquireReplica(settings.serverName, settings.projectId);\n try {\n const running = await startServe(directory, {...startOptions, remote:lease.remote});\n return {\n ...running,\n stop:async () => {\n await running.stop();\n lease.release();\n },\n };\n } catch (error) {\n lease.release();\n throw error;\n }\n });\n }\n\n async start():Promise<DaemonMetadata> {\n await mkdir(this.paths.home, {recursive:true, mode:0o700});\n if (process.platform!=='win32') { await rm(this.paths.socketPath, {force:true}); }\n this.server = createServer(socket => this.accept(socket));\n await new Promise<void>((resolveListen, reject) => {\n this.server!.once('error', reject);\n this.server!.listen(this.paths.socketPath, () => {\n this.server!.off('error', reject);\n resolveListen();\n });\n });\n if (process.platform!=='win32') { await chmod(this.paths.socketPath, 0o600); }\n const metadata:DaemonMetadata = {\n pid:process.pid,\n socketPath:this.paths.socketPath,\n token:this.token,\n protocolVersion:LEAFRELAY_PROTOCOL_VERSION,\n version:daemonVersion,\n startedAt:this.startedAt,\n };\n await writeFile(this.paths.metadataPath, `${JSON.stringify(metadata, null, 2)}\\n`, {encoding:'utf8', mode:0o600});\n await chmod(this.paths.metadataPath, 0o600);\n await this.log('info', `Daemon ${daemonVersion} listening on ${this.paths.socketPath}.`);\n this.scheduleIdleExit();\n return metadata;\n }\n\n async stop():Promise<void> {\n if (this.stopping) { return this.stopping; }\n this.stopping = this.performStop();\n return this.stopping;\n }\n\n status():DaemonStatus {\n return {\n pid:process.pid,\n version:daemonVersion,\n protocolVersion:LEAFRELAY_PROTOCOL_VERSION,\n startedAt:this.startedAt,\n clients:this.clients.size,\n projects:this.network.projectCount,\n replicas:this.replicas.list(),\n };\n }\n\n private accept(socket:Socket):void {\n this.cancelIdleExit();\n const rpc = createSocketRpcConnection(socket);\n const client:ClientConnection = {socket, rpc, initialized:false};\n this.clients.add(client);\n rpc.onRequest(RPC_METHOD.initialize, (params:InitializeParams) => this.initialize(client, params));\n rpc.onRequest(RPC_METHOD.daemonStatus, () => this.authorized(client, () => this.status()));\n rpc.onRequest(RPC_METHOD.daemonShutdown, () => this.authorized(client, async () => {\n setTimeout(() => void this.stop(), 25);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.replicaAttach, (params:ReplicaAttachParams) => this.authorized(client, async () => {\n try {\n return await this.replicas.attach(client.clientId!, params);\n } catch (error) {\n if (error instanceof ReplicaAlreadyActiveError) {\n throw new ResponseError(REPLICA_ALREADY_ACTIVE, error.message, {\n code:error.code,\n projectId:error.projectId,\n activeRoot:error.activeRoot,\n requestedRoot:error.requestedRoot,\n });\n }\n throw error;\n }\n }));\n rpc.onRequest(RPC_METHOD.replicaDetach, (params:{replicaId:string}) => this.authorized(client, () => {\n this.replicas.detach(client.clientId!, params.replicaId);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.replicaResolveConflict, (params:ReplicaConflictResolutionParams) => this.authorized(client, async () => {\n await this.replicas.resolveConflict(params.replicaId, params.path, params.winner);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.replicaRetry, (params:{replicaId:string; path:string}) => this.authorized(client, async () => {\n await this.replicas.retry(params.replicaId, params.path);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.serverList, () => this.authorized(client, () => this.network.listServers()));\n rpc.onRequest(RPC_METHOD.serverAdd, (params:{name:string; url:string}) => this.authorized(client, async () => {\n await this.network.addServer(params.name, params.url);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.serverRemove, (params:{server:string}) => this.authorized(client, async () => {\n await this.network.removeServer(params.server);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.sessionLogin, (params:ServerLoginParams) => this.authorized(client, () => this.network.login(params)));\n rpc.onRequest(RPC_METHOD.sessionImport, (params:ServerImportParams) => this.authorized(client, () => this.network.importSession(params)));\n rpc.onRequest(RPC_METHOD.sessionLogout, (params:{server:string}) => this.authorized(client, async () => {\n await this.network.logout(params.server);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.serverCall, (params:ServerCallParams) => this.authorized(client, async () => {\n const result = await this.network.callServer(params.server, params.operation, decodeRpcValue(params.args) as unknown[]);\n return encodeRpcValue(result);\n }));\n rpc.onRequest(RPC_METHOD.projectOpen, (params:ProjectOpenParams) => this.authorized(client, () => (\n this.network.openProject(client.clientId!, params.server, params.projectId)\n )));\n rpc.onRequest(RPC_METHOD.projectClose, (params:{projectKey:string}) => this.authorized(client, () => {\n this.network.closeProject(client.clientId!, params.projectKey);\n return null;\n }));\n rpc.onRequest(RPC_METHOD.projectCall, (params:ProjectCallParams) => this.authorized(client, async () => {\n const result = await this.network.callProject(params.projectKey, params.operation, decodeRpcValue(params.args) as unknown[]);\n return encodeRpcValue(await result);\n }));\n rpc.onClose(() => this.closeClient(client));\n rpc.onError(error => void this.log('error', `JSON-RPC connection error: ${String(error[0])}`));\n rpc.listen();\n }\n\n private initialize(client:ClientConnection, params:InitializeParams):InitializeResult {\n if (params.token!==this.token) { throw new ResponseError(-32001, 'Daemon authentication failed.'); }\n if (params.protocolVersion!==LEAFRELAY_PROTOCOL_VERSION) {\n throw new ResponseError(-32002, `Protocol ${params.protocolVersion} is incompatible with daemon protocol ${LEAFRELAY_PROTOCOL_VERSION}.`);\n }\n if (!params.clientId) { throw new ResponseError(-32602, 'clientId is required.'); }\n client.clientId = params.clientId;\n client.initialized = true;\n void this.log('info', `${params.clientName} ${params.clientVersion} connected (${params.clientId}).`);\n return {\n daemonVersion:daemonVersion,\n protocolVersion:LEAFRELAY_PROTOCOL_VERSION,\n pid:process.pid,\n startedAt:this.startedAt,\n };\n }\n\n private async authorized<T>(client:ClientConnection, operation:() => T|Promise<T>):Promise<T> {\n if (!client.initialized) { throw new ResponseError(-32001, 'Initialize the daemon connection first.'); }\n return operation();\n }\n\n private closeClient(client:ClientConnection):void {\n if (!this.clients.delete(client)) { return; }\n if (client.clientId) { this.replicas.detachClient(client.clientId); }\n if (client.clientId) { this.network.detachClient(client.clientId); }\n this.scheduleIdleExit();\n }\n\n private notifyOwners(\n owners:ReadonlySet<string>,\n method:typeof RPC_NOTIFICATION.replicaStatus|typeof RPC_NOTIFICATION.replicaConflict|typeof RPC_NOTIFICATION.projectEvent,\n notification:ReplicaStatusNotification|ReplicaConflictNotification|ProjectEventNotification,\n ):void {\n for (const client of this.clients) {\n if (client.clientId && owners.has(client.clientId)) { this.notifyClient(client, method, notification); }\n }\n }\n\n private async log(level:LogNotification['level'], message:string):Promise<void> {\n const notification:LogNotification = {timestamp:new Date().toISOString(), level, message};\n await appendFile(this.paths.logPath, `${notification.timestamp} [${level}] ${message}\\n`, {encoding:'utf8', mode:0o600});\n for (const client of this.clients) {\n if (client.initialized) { this.notifyClient(client, RPC_NOTIFICATION.log, notification); }\n }\n }\n\n private notifyClient(client:ClientConnection, method:string, notification:unknown):void {\n if (!this.clients.has(client) || client.socket.destroyed) { return; }\n void client.rpc.sendNotification(method, notification).catch(() => this.closeClient(client));\n }\n\n private scheduleIdleExit():void {\n if (this.options.exitOnIdle===false || this.clients.size!==0 || this.replicas.size!==0 || this.idleTimer) { return; }\n this.idleTimer = setTimeout(() => void this.stop(), IDLE_EXIT_MS);\n this.idleTimer.unref();\n }\n\n private cancelIdleExit():void {\n if (this.idleTimer) { clearTimeout(this.idleTimer); this.idleTimer = undefined; }\n }\n\n private async performStop():Promise<void> {\n this.cancelIdleExit();\n await this.replicas.stopAll();\n await this.network.stopAll();\n for (const client of this.clients) {\n client.rpc.dispose();\n client.socket.destroy();\n }\n this.clients.clear();\n if (this.server) {\n await new Promise<void>(resolveClose => this.server!.close(() => resolveClose()));\n }\n await rm(this.paths.metadataPath, {force:true});\n if (process.platform!=='win32') { await rm(this.paths.socketPath, {force:true}); }\n }\n}\n\nexport async function readDaemonMetadata(paths:DaemonPaths=daemonPaths()):Promise<DaemonMetadata|undefined> {\n try {\n return JSON.parse(await readFile(paths.metadataPath, 'utf8')) as DaemonMetadata;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code==='ENOENT') { return undefined; }\n throw error;\n }\n}\n","export const LEAFRELAY_PROTOCOL_VERSION = 1;\n\nexport const RPC_METHOD = {\n initialize:'leafrelay/initialize',\n daemonStatus:'leafrelay/daemon/status',\n daemonShutdown:'leafrelay/daemon/shutdown',\n replicaAttach:'leafrelay/replica/attach',\n replicaDetach:'leafrelay/replica/detach',\n replicaResolveConflict:'leafrelay/replica/resolveConflict',\n replicaRetry:'leafrelay/replica/retry',\n sessionImport:'leafrelay/session/import',\n sessionLogin:'leafrelay/session/login',\n sessionLogout:'leafrelay/session/logout',\n serverList:'leafrelay/server/list',\n serverAdd:'leafrelay/server/add',\n serverRemove:'leafrelay/server/remove',\n serverCall:'leafrelay/server/call',\n projectOpen:'leafrelay/project/open',\n projectClose:'leafrelay/project/close',\n projectCall:'leafrelay/project/call',\n} as const;\n\nexport const RPC_NOTIFICATION = {\n log:'leafrelay/log',\n replicaStatus:'leafrelay/replica/status',\n replicaConflict:'leafrelay/replica/conflict',\n projectEvent:'leafrelay/project/event',\n} as const;\n\nexport interface InitializeParams {\n token:string;\n clientId:string;\n clientName:'cli'|'vscode'|'library'|'test';\n clientVersion:string;\n protocolVersion:number;\n}\n\nexport interface InitializeResult {\n daemonVersion:string;\n protocolVersion:number;\n pid:number;\n startedAt:string;\n}\n\nexport interface DaemonStatus {\n pid:number;\n version:string;\n protocolVersion:number;\n startedAt:string;\n clients:number;\n projects:number;\n replicas:Array<{\n id:string;\n root:string;\n serverName:string;\n projectId:string;\n projectName:string;\n clients:number;\n status:ReplicaStatus;\n conflicts:string[];\n }>;\n}\n\nexport type ReplicaState = 'starting'|'syncing'|'active'|'paused'|'stopping'|'error';\n\nexport interface ReplicaStatus {\n state:ReplicaState;\n message?:string;\n}\n\nexport interface ReplicaAttachParams {\n directory:string;\n cookie?:string;\n}\n\nexport interface ReplicaAttachResult {\n replicaId:string;\n root:string;\n serverName:string;\n projectId:string;\n projectName:string;\n shared:boolean;\n status:ReplicaStatus;\n conflicts:string[];\n}\n\nexport interface ReplicaConflictResolutionParams {\n replicaId:string;\n path:string;\n winner:'local'|'remote';\n}\n\nexport interface ReplicaStatusNotification {\n replicaId:string;\n status:ReplicaStatus;\n}\n\nexport interface ReplicaConflictNotification {\n replicaId:string;\n path:string;\n reason:string;\n conflicts:string[];\n}\n\nexport interface LogNotification {\n timestamp:string;\n level:'info'|'warn'|'error';\n message:string;\n}\n\nexport interface DaemonMetadata {\n pid:number;\n socketPath:string;\n token:string;\n protocolVersion:number;\n version:string;\n startedAt:string;\n}\n\nexport interface ServerDescriptor {\n name:string;\n url:string;\n loggedIn:boolean;\n userId?:string;\n userEmail?:string;\n}\n\nexport interface ServerLoginParams {\n server:string;\n cookie?:string;\n email?:string;\n password?:string;\n}\n\nexport interface ServerImportParams {\n name:string;\n url:string;\n userId:string;\n userEmail:string;\n identity:{cookies:string; csrfToken:string};\n}\n\nexport interface ServerCallParams {\n server:string;\n operation:string;\n args:unknown[];\n}\n\nexport interface ProjectOpenParams {\n server:string;\n projectId:string;\n}\n\nexport interface ProjectOpenResult {\n projectKey:string;\n shared:boolean;\n}\n\nexport interface ProjectCallParams {\n projectKey:string;\n operation:string;\n args:unknown[];\n}\n\nexport interface ProjectEventNotification {\n projectKey:string;\n event:string;\n args:unknown[];\n}\n\nexport interface EncodedBinary {\n $leafrelay:'bytes';\n base64:string;\n}\n","import type {Socket} from 'node:net';\nimport {\n createMessageConnection,\n SocketMessageReader,\n SocketMessageWriter,\n type Message,\n type MessageConnection,\n} from 'vscode-jsonrpc/node';\n\nconst CLOSED_SOCKET_ERRORS = new Set([\n 'EPIPE',\n 'ECONNRESET',\n 'ERR_SOCKET_CLOSED',\n 'ERR_STREAM_DESTROYED',\n 'ERR_STREAM_WRITE_AFTER_END',\n]);\n\nclass LeafRelaySocketWriter extends SocketMessageWriter {\n constructor(private readonly transportSocket:Socket) {\n super(transportSocket);\n }\n\n override async write(message:Message):Promise<void> {\n try {\n await super.write(message);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (this.transportSocket.destroyed || this.transportSocket.writableEnded || (code && CLOSED_SOCKET_ERRORS.has(code))) { return; }\n throw error;\n }\n }\n}\n\nexport function createSocketRpcConnection(socket:Socket):MessageConnection {\n return createMessageConnection(new SocketMessageReader(socket), new LeafRelaySocketWriter(socket));\n}\n","import {randomUUID} from 'node:crypto';\nimport {mkdir, readFile, rm, stat} from 'node:fs/promises';\nimport {connect, type Socket} from 'node:net';\nimport {spawn} from 'node:child_process';\nimport {fileURLToPath} from 'node:url';\nimport {\n LEAFRELAY_PROTOCOL_VERSION,\n RPC_METHOD,\n RPC_NOTIFICATION,\n type DaemonMetadata,\n type DaemonStatus,\n type InitializeParams,\n type InitializeResult,\n type LogNotification,\n type ProjectEventNotification,\n type ProjectOpenResult,\n type ReplicaAttachParams,\n type ReplicaAttachResult,\n type ReplicaConflictNotification,\n type ReplicaConflictResolutionParams,\n type ReplicaStatusNotification,\n type ServerDescriptor,\n type ServerImportParams,\n type ServerLoginParams,\n} from '@leafrelay/protocol';\nimport type {MessageConnection} from 'vscode-jsonrpc/node';\nimport {decodeRpcValue, encodeRpcValue} from './codec';\nimport {daemonPaths, type DaemonPaths} from './paths';\nimport {createSocketRpcConnection} from './transport';\n\nconst START_TIMEOUT_MS = 15_000;\nconst START_POLL_MS = 75;\n\nexport interface DaemonClientOptions {\n clientName:InitializeParams['clientName'];\n clientVersion:string;\n clientId?:string;\n daemonEntrypoint?:string|URL;\n environment?:NodeJS.ProcessEnv;\n autoStart?:boolean;\n}\n\nexport interface DaemonClientListener {\n dispose():void;\n}\n\ninterface ReplicaRegistration {\n params:ReplicaAttachParams;\n currentId:string;\n}\n\ninterface ProjectRegistration {\n server:string;\n projectId:string;\n currentKey:string;\n}\n\nexport class LeafRelayDaemonClient {\n private socket?:Socket;\n private rpc?:MessageConnection;\n private connected = false;\n private closing = false;\n private reconnecting?:Promise<void>;\n private connectionClosed:Promise<void> = Promise.resolve();\n private initializeState!:InitializeResult;\n private readonly paths:DaemonPaths;\n private readonly environment:NodeJS.ProcessEnv;\n private readonly logListeners = new Set<(event:LogNotification) => void>();\n private readonly statusListeners = new Set<(event:ReplicaStatusNotification) => void>();\n private readonly conflictListeners = new Set<(event:ReplicaConflictNotification) => void>();\n private readonly projectListeners = new Set<(event:ProjectEventNotification) => void>();\n private readonly replicas = new Map<string,ReplicaRegistration>();\n private readonly projects = new Map<string,ProjectRegistration>();\n\n readonly clientId:string;\n\n private constructor(private readonly options:DaemonClientOptions) {\n this.environment = options.environment ?? process.env;\n this.paths = daemonPaths(this.environment);\n this.clientId = options.clientId ?? randomUUID();\n }\n\n static async connect(options:DaemonClientOptions):Promise<LeafRelayDaemonClient> {\n const client = new LeafRelayDaemonClient(options);\n await client.connectTransport();\n return client;\n }\n\n get initializeResult():InitializeResult { return this.initializeState; }\n\n status():Promise<DaemonStatus> {\n return this.request(RPC_METHOD.daemonStatus);\n }\n\n async attachReplica(params:ReplicaAttachParams):Promise<ReplicaAttachResult> {\n const result = await this.request<ReplicaAttachResult>(RPC_METHOD.replicaAttach, params);\n this.replicas.set(result.replicaId, {params, currentId:result.replicaId});\n return result;\n }\n\n async detachReplica(replicaId:string):Promise<void> {\n const registration = this.replicas.get(replicaId);\n await this.request(RPC_METHOD.replicaDetach, {replicaId:registration?.currentId ?? replicaId});\n this.replicas.delete(replicaId);\n }\n\n async resolveConflict(params:ReplicaConflictResolutionParams):Promise<void> {\n const registration = this.replicas.get(params.replicaId);\n await this.request(RPC_METHOD.replicaResolveConflict, {\n ...params,\n replicaId:registration?.currentId ?? params.replicaId,\n });\n }\n\n async retry(replicaId:string, path:string):Promise<void> {\n const registration = this.replicas.get(replicaId);\n await this.request(RPC_METHOD.replicaRetry, {replicaId:registration?.currentId ?? replicaId, path});\n }\n\n onLog(handler:(event:LogNotification) => void):DaemonClientListener {\n return addListener(this.logListeners, handler);\n }\n\n onReplicaStatus(handler:(event:ReplicaStatusNotification) => void):DaemonClientListener {\n return addListener(this.statusListeners, handler);\n }\n\n onReplicaConflict(handler:(event:ReplicaConflictNotification) => void):DaemonClientListener {\n return addListener(this.conflictListeners, handler);\n }\n\n listServers():Promise<ServerDescriptor[]> {\n return this.request(RPC_METHOD.serverList);\n }\n\n async addServer(name:string, url:string):Promise<void> {\n await this.request(RPC_METHOD.serverAdd, {name, url});\n }\n\n async removeServer(server:string):Promise<void> {\n await this.request(RPC_METHOD.serverRemove, {server});\n }\n\n login(params:ServerLoginParams):Promise<{userId:string; userEmail:string}> {\n return this.request(RPC_METHOD.sessionLogin, params);\n }\n\n importSession(params:ServerImportParams):Promise<{userId:string; userEmail:string}> {\n return this.request(RPC_METHOD.sessionImport, params);\n }\n\n async logout(server:string):Promise<void> {\n await this.request(RPC_METHOD.sessionLogout, {server});\n }\n\n async callServer<T=unknown>(server:string, operation:string, args:unknown[]=[]):Promise<T> {\n const result = await this.request(RPC_METHOD.serverCall, {server, operation, args:encodeRpcValue(args)});\n return decodeRpcValue(result) as T;\n }\n\n async openProject(server:string, projectId:string):Promise<ProjectOpenResult> {\n const result = await this.request<ProjectOpenResult>(RPC_METHOD.projectOpen, {server, projectId});\n this.projects.set(result.projectKey, {server, projectId, currentKey:result.projectKey});\n return result;\n }\n\n async closeProject(projectKey:string):Promise<void> {\n const registration = this.projects.get(projectKey);\n await this.request(RPC_METHOD.projectClose, {projectKey:registration?.currentKey ?? projectKey});\n this.projects.delete(projectKey);\n }\n\n async callProject<T=unknown>(projectKey:string, operation:string, args:unknown[]=[]):Promise<T> {\n const registration = this.projects.get(projectKey);\n const result = await this.request(RPC_METHOD.projectCall, {\n projectKey:registration?.currentKey ?? projectKey,\n operation,\n args:encodeRpcValue(args),\n });\n return decodeRpcValue(result) as T;\n }\n\n onProjectEvent(handler:(event:ProjectEventNotification) => void):DaemonClientListener {\n return addListener(this.projectListeners, handler);\n }\n\n async shutdownDaemon():Promise<void> {\n this.closing = true;\n await this.rawRequest(RPC_METHOD.daemonShutdown);\n }\n\n close():void {\n this.closing = true;\n this.connected = false;\n this.rpc?.dispose();\n this.socket?.destroy();\n this.rpc = undefined;\n this.socket = undefined;\n }\n\n private async request<T>(method:string, params?:unknown):Promise<T> {\n if (!this.connected) { await this.ensureReconnected(); }\n try {\n return await this.rawRequest<T>(method, params);\n } catch (requestError) {\n if (this.connected || this.closing) { throw requestError; }\n await this.ensureReconnected();\n return this.rawRequest<T>(method, params);\n }\n }\n\n private rawRequest<T>(method:string, params?:unknown):Promise<T> {\n if (!this.rpc) { return Promise.reject(new Error('LeafRelay daemon is disconnected.')); }\n const response = params===undefined ? this.rpc.sendRequest<T>(method) : this.rpc.sendRequest<T>(method, params);\n return Promise.race([\n response,\n this.connectionClosed.then(() => Promise.reject(new Error('LeafRelay daemon connection closed.'))),\n ]);\n }\n\n private async ensureReconnected():Promise<void> {\n if (this.closing) { throw new Error('LeafRelay daemon client is closed.'); }\n this.reconnecting ??= this.connectTransport().finally(() => { this.reconnecting = undefined; });\n return this.reconnecting;\n }\n\n private async connectTransport():Promise<void> {\n const metadata = await this.findOrStartDaemon();\n const socket = await tryConnect(metadata);\n if (!socket) { throw new Error(`LeafRelay daemon is not running at ${this.paths.socketPath}.`); }\n const rpc = createSocketRpcConnection(socket);\n let signalClosed!:() => void;\n this.connectionClosed = new Promise(resolveClosed => { signalClosed = resolveClosed; });\n this.socket = socket;\n this.rpc = rpc;\n this.registerNotifications(rpc);\n rpc.onClose(() => {\n signalClosed();\n if (this.rpc!==rpc) { return; }\n this.connected = false;\n this.rpc = undefined;\n this.socket = undefined;\n if (!this.closing) { void this.ensureReconnected(); }\n });\n rpc.listen();\n try {\n this.initializeState = await rpc.sendRequest<InitializeResult>(RPC_METHOD.initialize, {\n token:metadata.token,\n clientId:this.clientId,\n clientName:this.options.clientName,\n clientVersion:this.options.clientVersion,\n protocolVersion:LEAFRELAY_PROTOCOL_VERSION,\n } satisfies InitializeParams);\n this.connected = true;\n await this.restoreRegistrations(rpc);\n } catch (connectError) {\n rpc.dispose();\n socket.destroy();\n if (this.rpc===rpc) { this.rpc = undefined; this.socket = undefined; }\n throw connectError;\n }\n }\n\n private async restoreRegistrations(rpc:MessageConnection):Promise<void> {\n for (const registration of this.projects.values()) {\n const result = await rpc.sendRequest<ProjectOpenResult>(RPC_METHOD.projectOpen, {\n server:registration.server,\n projectId:registration.projectId,\n });\n registration.currentKey = result.projectKey;\n }\n for (const registration of this.replicas.values()) {\n const result = await rpc.sendRequest<ReplicaAttachResult>(RPC_METHOD.replicaAttach, registration.params);\n registration.currentId = result.replicaId;\n }\n }\n\n private registerNotifications(rpc:MessageConnection):void {\n rpc.onNotification(RPC_NOTIFICATION.log, event => dispatch(this.logListeners, event));\n rpc.onNotification(RPC_NOTIFICATION.replicaStatus, (event:ReplicaStatusNotification) => {\n dispatch(this.statusListeners, {...event, replicaId:this.stableReplicaId(event.replicaId)});\n });\n rpc.onNotification(RPC_NOTIFICATION.replicaConflict, (event:ReplicaConflictNotification) => {\n dispatch(this.conflictListeners, {...event, replicaId:this.stableReplicaId(event.replicaId)});\n });\n rpc.onNotification(RPC_NOTIFICATION.projectEvent, (event:ProjectEventNotification) => {\n dispatch(this.projectListeners, {...event, projectKey:this.stableProjectKey(event.projectKey)});\n });\n }\n\n private stableReplicaId(currentId:string):string {\n return [...this.replicas].find(([, registration]) => registration.currentId===currentId)?.[0] ?? currentId;\n }\n\n private stableProjectKey(currentKey:string):string {\n return [...this.projects].find(([, registration]) => registration.currentKey===currentKey)?.[0] ?? currentKey;\n }\n\n private async findOrStartDaemon():Promise<DaemonMetadata> {\n let metadata = await readMetadata(this.paths);\n if (metadata && await tryConnect(metadata).then(socket => {\n socket?.destroy();\n return Boolean(socket);\n })) { return metadata; }\n if (this.options.autoStart===false) {\n throw new Error(`LeafRelay daemon is not running at ${this.paths.socketPath}.`);\n }\n metadata = await startDaemon(this.paths, this.options, this.environment);\n return metadata;\n }\n}\n\nfunction addListener<T>(listeners:Set<(event:T) => void>, handler:(event:T) => void):DaemonClientListener {\n listeners.add(handler);\n return {dispose:() => listeners.delete(handler)};\n}\n\nfunction dispatch<T>(listeners:ReadonlySet<(event:T) => void>, event:T):void {\n for (const listener of listeners) { listener(event); }\n}\n\nasync function startDaemon(paths:DaemonPaths, options:DaemonClientOptions, environment:NodeJS.ProcessEnv):Promise<DaemonMetadata> {\n await mkdir(paths.home, {recursive:true, mode:0o700});\n let ownsLock = false;\n try {\n await mkdir(paths.startupLockPath, {mode:0o700});\n ownsLock = true;\n } catch (lockError) {\n if ((lockError as NodeJS.ErrnoException).code!=='EEXIST') { throw lockError; }\n const lockStat = await stat(paths.startupLockPath).catch(() => undefined);\n if (lockStat && Date.now()-lockStat.mtimeMs>START_TIMEOUT_MS) {\n await rm(paths.startupLockPath, {recursive:true, force:true});\n return startDaemon(paths, options, environment);\n }\n }\n\n if (ownsLock) {\n try {\n const entrypoint = options.daemonEntrypoint ?? new URL('./daemon.js', import.meta.url);\n const childEnvironment = {...environment};\n childEnvironment.LEAFRELAY_HOME = paths.home;\n const child = spawn(process.execPath, [typeof entrypoint==='string' ? entrypoint : fileURLToPath(entrypoint)], {\n detached:true,\n stdio:'ignore',\n env:childEnvironment,\n });\n child.unref();\n return await waitForDaemon(paths);\n } finally {\n await rm(paths.startupLockPath, {recursive:true, force:true});\n }\n }\n return waitForDaemon(paths);\n}\n\nasync function waitForDaemon(paths:DaemonPaths):Promise<DaemonMetadata> {\n const deadline = Date.now()+START_TIMEOUT_MS;\n let lastError:unknown;\n while (Date.now()<deadline) {\n try {\n const metadata = await readMetadata(paths);\n if (metadata && await tryConnect(metadata).then(socket => {\n socket?.destroy();\n return Boolean(socket);\n })) { return metadata; }\n } catch (pollError) {\n lastError = pollError;\n }\n await new Promise(resolveWait => setTimeout(resolveWait, START_POLL_MS));\n }\n throw new Error(`LeafRelay daemon did not start within ${START_TIMEOUT_MS}ms.`, {cause:lastError});\n}\n\nasync function readMetadata(paths:DaemonPaths):Promise<DaemonMetadata|undefined> {\n try {\n return JSON.parse(await readFile(paths.metadataPath, 'utf8')) as DaemonMetadata;\n } catch (readError) {\n if ((readError as NodeJS.ErrnoException).code==='ENOENT') { return undefined; }\n throw readError;\n }\n}\n\nasync function tryConnect(metadata:DaemonMetadata):Promise<Socket|undefined> {\n return new Promise(resolveConnection => {\n const socket = connect(metadata.socketPath);\n socket.once('connect', () => resolveConnection(socket));\n socket.once('error', () => {\n socket.destroy();\n resolveConnection(undefined);\n });\n });\n}\n","import {LeafRelayDaemonClient} from '@leafrelay/daemon';\n\ndeclare const LEAFRELAY_VERSION:string;\n\nexport function connectCliDaemon(autoStart=true):Promise<LeafRelayDaemonClient> {\n return LeafRelayDaemonClient.connect({\n clientName:'cli',\n clientVersion:LEAFRELAY_VERSION,\n daemonEntrypoint:new URL('./daemon.js', import.meta.url),\n autoStart,\n });\n}\n","import {LeafRelayDaemonClient} from '@leafrelay/daemon';\nimport type {ReplicaAttachResult, ReplicaConflictNotification, ReplicaStatusNotification} from '@leafrelay/protocol';\nimport {connectCliDaemon} from './daemonClient';\n\nexport interface RunningServe {\n readonly replica:ReplicaAttachResult;\n stop():Promise<void>;\n}\n\nexport async function startServe(directory=process.cwd()):Promise<RunningServe> {\n const client = await connectCliDaemon();\n client.onLog(event => console.log(`${event.timestamp} [${event.level}] ${event.message}`));\n client.onReplicaStatus((event:ReplicaStatusNotification) => {\n console.log(`Replica ${event.replicaId}: ${event.status.state}${event.status.message ? ` (${event.status.message})` : ''}`);\n });\n client.onReplicaConflict((event:ReplicaConflictNotification) => {\n console.error(`Conflict in ${event.path}: ${event.reason}`);\n });\n try {\n const replica = await client.attachReplica({directory});\n return {\n replica,\n stop:async () => {\n await client.detachReplica(replica.replicaId);\n client.close();\n },\n };\n } catch (error) {\n client.close();\n throw error;\n }\n}\n\nexport async function serve(directory=process.cwd()):Promise<void> {\n const running = await startServe(directory);\n console.log(`${running.replica.shared ? 'Attached to' : 'Started'} ${running.replica.projectName} at ${running.replica.root}.`);\n await new Promise<void>((resolveStop) => {\n const stop = () => {\n process.off('SIGINT', stop);\n process.off('SIGTERM', stop);\n running.stop().then(resolveStop, error => {\n console.error(error);\n resolveStop();\n });\n };\n process.on('SIGINT', stop);\n process.on('SIGTERM', stop);\n });\n}\n\nexport async function daemonStatus():Promise<void> {\n let client:LeafRelayDaemonClient|undefined;\n try {\n client = await connectCliDaemon(false);\n console.log(JSON.stringify(await client.status(), null, 2));\n } catch {\n console.log('LeafRelay daemon is not running.');\n } finally {\n client?.close();\n }\n}\n\nexport async function daemonStop():Promise<void> {\n let client:LeafRelayDaemonClient|undefined;\n try {\n client = await connectCliDaemon(false);\n await client.shutdownDaemon();\n console.log('LeafRelay daemon stopped.');\n } catch {\n console.log('LeafRelay daemon is not running.');\n } finally {\n client?.close();\n }\n}\n\nexport async function daemonRestart():Promise<void> {\n await daemonStop();\n const client = await connectCliDaemon();\n const status = await client.status();\n console.log(`LeafRelay daemon restarted (pid ${status.pid}).`);\n client.close();\n}\n"],"mappings":"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","names":["longtext","shorttext","types","ext","path","types","pl","i","acc","ext","start","final","qmark","star","regExpEscape","open","error","path"]}