trzsz2 1.0.0 → 1.0.1

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.
package/dist/cjs/comm.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const pako_esm = require("./node_modules/pako/dist/pako.esm.cjs");
3
+ const Pako = require("pako");
4
4
  const trzszVersion = "2.0.0";
5
5
  function strToUint8(str) {
6
6
  return Uint8Array.from(str, (v) => v.charCodeAt(0));
@@ -68,7 +68,7 @@ function deflate(data) {
68
68
  const result = zlib.deflateSync(input);
69
69
  return new Uint8Array(result);
70
70
  }
71
- return pako_esm.default.deflate(input);
71
+ return Pako.deflate(input);
72
72
  }
73
73
  function inflate(data) {
74
74
  const zlib = getNodeZlib();
@@ -76,7 +76,7 @@ function inflate(data) {
76
76
  const result = zlib.inflateSync(data);
77
77
  return new Uint8Array(result);
78
78
  }
79
- return pako_esm.default.inflate(data);
79
+ return Pako.inflate(data);
80
80
  }
81
81
  function encodeBuffer(buf) {
82
82
  const buffer = deflate(buf);
@@ -1 +1 @@
1
- {"version":3,"file":"comm.cjs","sources":["../../src/comm.ts"],"sourcesContent":["/**\n * trzsz2: https://github.com/zxdong262/trzsz2\n * Copyright(c) 2024 Lonny Wong\n * @license MIT\n *\n * Pure protocol implementation without fs/browser dependencies.\n */\n\nimport Pako from 'pako'\n\n/**\n * trzsz version\n */\nexport const trzszVersion = '2.0.0'\n\n/**\n * Convert a string to Uint8Array.\n * @param {string} str - The input string.\n * @return {Uint8Array} The resulting Uint8Array.\n */\nexport function strToUint8 (str: string): Uint8Array {\n return Uint8Array.from(str, (v) => v.charCodeAt(0))\n}\n\n/**\n * Convert a Uint8Array to string.\n * @param {Uint8Array} buf - The input buffer.\n * @param {string} encoding - The encoding to use.\n * @return {Promise<string>} The resulting string.\n */\nexport async function uint8ToStr (buf: Uint8Array, encoding: string = 'binary'): Promise<string> {\n if (typeof Buffer === 'function') {\n return Buffer.from(buf).toString(encoding as BufferEncoding)\n }\n return await new Promise<string>((resolve) => {\n const reader = new FileReader()\n reader.onloadend = () => resolve(reader.result as string)\n // Create a new ArrayBuffer copy to avoid SharedArrayBuffer issues\n const arrayBuffer = new ArrayBuffer(buf.byteLength)\n new Uint8Array(arrayBuffer).set(buf)\n const blob = new Blob([arrayBuffer])\n if (encoding === 'binary') {\n reader.readAsBinaryString(blob)\n } else {\n reader.readAsText(blob, encoding)\n }\n })\n}\n\n/**\n * Convert a string to ArrayBuffer.\n * @param {string} str - The input string.\n * @return {ArrayBuffer} The resulting ArrayBuffer.\n */\nexport function strToArrBuf (str: string): ArrayBuffer {\n const arr = strToUint8(str)\n // Create a new ArrayBuffer copy to avoid SharedArrayBuffer issues\n const buffer = new ArrayBuffer(arr.byteLength)\n new Uint8Array(buffer).set(arr)\n return buffer\n}\n\nconst _hasBuffer = typeof Buffer === 'function'\n\n// Lazy load Node.js zlib module\nlet _nodeZlib: typeof import('zlib') | null | undefined\n\n/**\n * Get Node.js zlib module if available.\n * @return {typeof import('zlib') | null} The zlib module or null if not available.\n */\nfunction getNodeZlib (): typeof import('zlib') | null {\n if (_nodeZlib === undefined) {\n try {\n // Use dynamic require for Node.js environment\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n _nodeZlib = require('zlib')\n } catch {\n _nodeZlib = null\n }\n }\n return _nodeZlib ?? null\n}\n\n/**\n * Encode Uint8Array to base64 string using native functions.\n * @param {Uint8Array} buffer - The input buffer.\n * @return {string} The base64 encoded string.\n */\nfunction uint8ToBase64 (buffer: Uint8Array): string {\n if (_hasBuffer) {\n return Buffer.from(buffer).toString('base64')\n }\n // Browser: use btoa with binary string\n let binary = ''\n for (let i = 0; i < buffer.length; i++) {\n binary += String.fromCharCode(buffer[i])\n }\n return btoa(binary)\n}\n\n/**\n * Decode base64 string to Uint8Array using native functions.\n * @param {string} base64 - The base64 encoded string.\n * @return {Uint8Array} The decoded buffer.\n */\nfunction base64ToUint8 (base64: string): Uint8Array {\n if (_hasBuffer) {\n return Buffer.from(base64, 'base64')\n }\n // Browser: use atob and convert to Uint8Array\n const binary = atob(base64)\n const buffer = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) {\n buffer[i] = binary.charCodeAt(i)\n }\n return buffer\n}\n\n/**\n * Compress data using deflate algorithm.\n * Uses Node.js native zlib in Node.js, pako in browser.\n * @param {string | Uint8Array} data - The data to compress.\n * @return {Uint8Array} The compressed data.\n */\nfunction deflate (data: string | Uint8Array): Uint8Array {\n const input = typeof data === 'string' ? strToUint8(data) : data\n\n // Try Node.js native zlib first\n const zlib = getNodeZlib()\n if (zlib != null) {\n // Use deflateSync (zlib format) to match pako's default behavior\n const result = zlib.deflateSync(input)\n // Convert Buffer to Uint8Array for consistency\n return new Uint8Array(result)\n }\n\n // Fall back to pako for browser\n return Pako.deflate(input)\n}\n\n/**\n * Decompress data using inflate algorithm.\n * Uses Node.js native zlib in Node.js, pako in browser.\n * @param {Uint8Array} data - The compressed data.\n * @return {Uint8Array} The decompressed data.\n */\nfunction inflate (data: Uint8Array): Uint8Array {\n // Try Node.js native zlib first\n const zlib = getNodeZlib()\n if (zlib != null) {\n // Use inflateSync (zlib format) to match pako's default behavior\n const result = zlib.inflateSync(data)\n // Convert Buffer to Uint8Array for consistency\n return new Uint8Array(result)\n }\n\n // Fall back to pako for browser\n return Pako.inflate(data)\n}\n\n/**\n * Encode a buffer (compress and base64).\n * @param {string | Uint8Array} buf - The input buffer.\n * @return {string} The encoded string.\n */\nexport function encodeBuffer (buf: string | Uint8Array): string {\n const buffer = deflate(buf)\n return uint8ToBase64(buffer)\n}\n\n/**\n * Decode a buffer (base64 and decompress).\n * @param {string} buf - The encoded string.\n * @return {Uint8Array} The decoded buffer.\n */\nexport function decodeBuffer (buf: string): Uint8Array {\n const buffer = base64ToUint8(buf)\n return inflate(buffer)\n}\n\n/**\n * Custom error class for trzsz operations.\n */\nexport class TrzszError extends Error {\n private readonly type: string | null\n private readonly trace: boolean\n\n constructor (message: string, type: string | null = null, trace: boolean = false) {\n if (type === 'fail' || type === 'FAIL' || type === 'EXIT') {\n try {\n message = new TextDecoder().decode(decodeBuffer(message))\n } catch {\n message = `decode [${message}] error`\n }\n } else if (type !== null) {\n message = `[TrzszError] ${type}: ${message}`\n }\n\n super(message)\n Object.setPrototypeOf(this, TrzszError.prototype)\n if (typeof Error.captureStackTrace === 'function') {\n Error.captureStackTrace(this, TrzszError)\n }\n\n this.name = 'TrzszError'\n this.type = type\n this.trace = trace\n }\n\n /**\n * Check if the error should include traceback.\n * @return {boolean} True if traceback should be included.\n */\n public isTraceBack (): boolean {\n if (this.type === 'fail' || this.type === 'EXIT') {\n return false\n }\n return this.trace\n }\n\n /**\n * Check if the error is a remote exit.\n * @return {boolean} True if remote exit.\n */\n public isRemoteExit (): boolean {\n return this.type === 'EXIT'\n }\n\n /**\n * Check if the error is a remote failure.\n * @return {boolean} True if remote failure.\n */\n public isRemoteFail (): boolean {\n return this.type === 'fail' || this.type === 'FAIL'\n }\n\n /**\n * Check if the error indicates stop and delete.\n * @return {boolean} True if stop and delete.\n */\n public isStopAndDelete (): boolean {\n if (this.type !== 'fail') {\n return false\n }\n return this.message === 'Stopped and deleted'\n }\n\n /**\n * Get the error message.\n * @param {Error} err - The error object.\n * @return {string} The error message.\n */\n public static getErrorMessage (err: Error): string {\n if (err instanceof TrzszError && !err.isTraceBack()) {\n return err.message\n }\n if (typeof err.stack === 'string' && err.stack.length > 0) {\n return err.stack.replace('TrzszError: ', '')\n }\n return err.toString()\n }\n}\n\n/**\n * Interface for trzsz file operations.\n */\nexport interface TrzszFile {\n closeFile: () => void\n}\n\n/**\n * Interface for trzsz file reader.\n */\nexport interface TrzszFileReader extends TrzszFile {\n getPathId: () => number\n getRelPath: () => string[]\n isDir: () => boolean\n getSize: () => number\n readFile: (buf: ArrayBuffer) => Promise<Uint8Array>\n}\n\n/**\n * Interface for trzsz file writer.\n */\nexport interface TrzszFileWriter extends TrzszFile {\n getFileName: () => string\n getLocalName: () => string\n isDir: () => boolean\n writeFile: (buf: Uint8Array) => Promise<void>\n deleteFile: () => Promise<string>\n}\n\n/**\n * Type for opening save file.\n */\nexport type OpenSaveFile = (\n saveParam: any,\n fileName: string,\n directory: boolean,\n overwrite: boolean,\n) => Promise<TrzszFileWriter>\n\n/**\n * Interface for progress callback.\n */\nexport interface ProgressCallback {\n onNum: (num: number) => void\n onName: (name: string) => void\n onSize: (size: number) => void\n onStep: (step: number) => void\n onDone: () => void\n}\n\n/**\n * Check for duplicate file names.\n * @param {TrzszFileReader[]} files - The files to check.\n */\nexport function checkDuplicateNames (files: TrzszFileReader[]): void {\n const names = new Set<string>()\n for (const file of files) {\n const path = file.getRelPath().join('/')\n if (names.has(path)) {\n throw new TrzszError(`Duplicate name: ${path}`)\n }\n names.add(path)\n }\n}\n\n/**\n * Check if an array contains only elements of a specific type.\n * @param {any} arr - The array to check.\n * @param {string} type - The type to check for.\n * @return {boolean} True if all elements are of the specified type.\n */\nexport function isArrayOfType (arr: any, type: string): boolean {\n if (!Array.isArray(arr)) {\n return false\n }\n for (const a of arr) {\n switch (type) {\n case 'string':\n if (typeof a !== 'string') return false\n break\n case 'number':\n if (typeof a !== 'number') return false\n break\n case 'boolean':\n if (typeof a !== 'boolean') return false\n break\n case 'object':\n if (typeof a !== 'object') return false\n break\n case 'function':\n if (typeof a !== 'function') return false\n break\n case 'undefined':\n if (typeof a !== 'undefined') return false\n break\n default:\n return false\n }\n }\n return true\n}\n\n/**\n * Check if a character is a VT100 end character.\n * @param {number} c - The character code.\n * @return {boolean} True if it's a VT100 end character.\n */\nexport function isVT100End (c: number): boolean {\n if (c >= 0x61 && c <= 0x7a) {\n // 'a' <= c && c <= 'z'\n return true\n }\n if (c >= 0x41 && c <= 0x5a) {\n // 'A' <= c && c <= 'Z'\n return true\n }\n return false\n}\n\n/**\n * Strip VT100 escape sequences from server output.\n * @param {string | ArrayBuffer | Uint8Array | Blob} output - The server output.\n * @return {string | ArrayBuffer | Uint8Array | Blob} The stripped output.\n */\nexport function stripServerOutput (output: string | ArrayBuffer | Uint8Array | Blob): string | ArrayBuffer | Uint8Array | Blob {\n let uint8: Uint8Array\n if (typeof output === 'string') {\n uint8 = strToUint8(output)\n } else if (output instanceof ArrayBuffer) {\n uint8 = new Uint8Array(output)\n } else if (output instanceof Uint8Array) {\n uint8 = output\n } else {\n return output\n }\n const buf = new Uint8Array(uint8.length)\n let skipVT100 = false\n let idx = 0\n for (let i = 0; i < uint8.length; i++) {\n const c = uint8[i]\n if (skipVT100) {\n if (isVT100End(c)) {\n skipVT100 = false\n }\n } else if (c === 0x1b) {\n skipVT100 = true\n } else {\n buf[idx++] = c\n }\n }\n while (idx > 0) {\n const c = buf[idx - 1]\n if (c !== 0x0d && c !== 0x0a) {\n // not \\r\\n\n break\n }\n idx--\n }\n const result = buf.subarray(0, idx)\n if (result.length > 100) {\n return output\n }\n return String.fromCharCode.apply(null, Array.from(result))\n}\n\n/**\n * Tmux mode constants.\n */\nexport const TmuxMode = {\n NoTmux: 0,\n TmuxNormalMode: 1,\n TmuxControlMode: 2\n} as const\n\nexport type TmuxModeType = (typeof TmuxMode)[keyof typeof TmuxMode]\n\n/**\n * Format saved files message.\n * @param {string[]} fileNames - The file names.\n * @param {string} destPath - The destination path.\n * @return {string} The formatted message.\n */\nexport function formatSavedFiles (fileNames: string[], destPath: string): string {\n let msg = `Saved ${fileNames.length} ${fileNames.length > 1 ? 'files/directories' : 'file/directory'}`\n if (destPath.length > 0) {\n msg += ` to ${destPath}`\n }\n return [msg].concat(fileNames).join('\\r\\n- ')\n}\n\n/**\n * Strip tmux status line from buffer.\n * @param {string} buf - The input buffer.\n * @return {string} The stripped buffer.\n */\nexport function stripTmuxStatusLine (buf: string): string {\n while (true) {\n const beginIdx = buf.indexOf('\\x1bP=')\n if (beginIdx < 0) {\n return buf\n }\n let bufIdx = beginIdx + 3\n const midIdx = buf.substring(bufIdx).indexOf('\\x1bP=')\n if (midIdx < 0) {\n return buf.substring(0, beginIdx)\n }\n bufIdx += midIdx + 3\n const endIdx = buf.substring(bufIdx).indexOf('\\x1b\\\\')\n if (endIdx < 0) {\n return buf.substring(0, beginIdx)\n }\n bufIdx += endIdx + 2\n buf = buf.substring(0, beginIdx) + buf.substring(bufIdx)\n }\n}\n"],"names":["Pako"],"mappings":";;;AAaO,MAAM,eAAe;AAOrB,SAAS,WAAY,KAAyB;AACnD,SAAO,WAAW,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AACpD;AAQA,eAAsB,WAAY,KAAiB,WAAmB,UAA2B;AAC/F,MAAI,OAAO,WAAW,YAAY;AAChC,WAAO,OAAO,KAAK,GAAG,EAAE,SAAS,QAA0B;AAAA,EAC7D;AACA,SAAO,MAAM,IAAI,QAAgB,CAAC,YAAY;AAC5C,UAAM,SAAS,IAAI,WAAA;AACnB,WAAO,YAAY,MAAM,QAAQ,OAAO,MAAgB;AAExD,UAAM,cAAc,IAAI,YAAY,IAAI,UAAU;AAClD,QAAI,WAAW,WAAW,EAAE,IAAI,GAAG;AACnC,UAAM,OAAO,IAAI,KAAK,CAAC,WAAW,CAAC;AACnC,QAAI,aAAa,UAAU;AACzB,aAAO,mBAAmB,IAAI;AAAA,IAChC,OAAO;AACL,aAAO,WAAW,MAAM,QAAQ;AAAA,IAClC;AAAA,EACF,CAAC;AACH;AAOO,SAAS,YAAa,KAA0B;AACrD,QAAM,MAAM,WAAW,GAAG;AAE1B,QAAM,SAAS,IAAI,YAAY,IAAI,UAAU;AAC7C,MAAI,WAAW,MAAM,EAAE,IAAI,GAAG;AAC9B,SAAO;AACT;AAEA,MAAM,aAAa,OAAO,WAAW;AAGrC,IAAI;AAMJ,SAAS,cAA6C;AACpD,MAAI,cAAc,QAAW;AAC3B,QAAI;AAGF,kBAAY,QAAQ,MAAM;AAAA,IAC5B,QAAQ;AACN,kBAAY;AAAA,IACd;AAAA,EACF;AACA,SAAO,aAAa;AACtB;AAOA,SAAS,cAAe,QAA4B;AAClD,MAAI,YAAY;AACd,WAAO,OAAO,KAAK,MAAM,EAAE,SAAS,QAAQ;AAAA,EAC9C;AAEA,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,cAAU,OAAO,aAAa,OAAO,CAAC,CAAC;AAAA,EACzC;AACA,SAAO,KAAK,MAAM;AACpB;AAOA,SAAS,cAAe,QAA4B;AAClD,MAAI,YAAY;AACd,WAAO,OAAO,KAAK,QAAQ,QAAQ;AAAA,EACrC;AAEA,QAAM,SAAS,KAAK,MAAM;AAC1B,QAAM,SAAS,IAAI,WAAW,OAAO,MAAM;AAC3C,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,WAAO,CAAC,IAAI,OAAO,WAAW,CAAC;AAAA,EACjC;AACA,SAAO;AACT;AAQA,SAAS,QAAS,MAAuC;AACvD,QAAM,QAAQ,OAAO,SAAS,WAAW,WAAW,IAAI,IAAI;AAG5D,QAAM,OAAO,YAAA;AACb,MAAI,QAAQ,MAAM;AAEhB,UAAM,SAAS,KAAK,YAAY,KAAK;AAErC,WAAO,IAAI,WAAW,MAAM;AAAA,EAC9B;AAGA,SAAOA,SAAAA,QAAK,QAAQ,KAAK;AAC3B;AAQA,SAAS,QAAS,MAA8B;AAE9C,QAAM,OAAO,YAAA;AACb,MAAI,QAAQ,MAAM;AAEhB,UAAM,SAAS,KAAK,YAAY,IAAI;AAEpC,WAAO,IAAI,WAAW,MAAM;AAAA,EAC9B;AAGA,SAAOA,SAAAA,QAAK,QAAQ,IAAI;AAC1B;AAOO,SAAS,aAAc,KAAkC;AAC9D,QAAM,SAAS,QAAQ,GAAG;AAC1B,SAAO,cAAc,MAAM;AAC7B;AAOO,SAAS,aAAc,KAAyB;AACrD,QAAM,SAAS,cAAc,GAAG;AAChC,SAAO,QAAQ,MAAM;AACvB;AAKO,MAAM,mBAAmB,MAAM;AAAA,EAIpC,YAAa,SAAiB,OAAsB,MAAM,QAAiB,OAAO;AAChF,QAAI,SAAS,UAAU,SAAS,UAAU,SAAS,QAAQ;AACzD,UAAI;AACF,kBAAU,IAAI,YAAA,EAAc,OAAO,aAAa,OAAO,CAAC;AAAA,MAC1D,QAAQ;AACN,kBAAU,WAAW,OAAO;AAAA,MAC9B;AAAA,IACF,WAAW,SAAS,MAAM;AACxB,gBAAU,gBAAgB,IAAI,KAAK,OAAO;AAAA,IAC5C;AAEA,UAAM,OAAO;AACb,WAAO,eAAe,MAAM,WAAW,SAAS;AAChD,QAAI,OAAO,MAAM,sBAAsB,YAAY;AACjD,YAAM,kBAAkB,MAAM,UAAU;AAAA,IAC1C;AAEA,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,cAAwB;AAC7B,QAAI,KAAK,SAAS,UAAU,KAAK,SAAS,QAAQ;AAChD,aAAO;AAAA,IACT;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,eAAyB;AAC9B,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,eAAyB;AAC9B,WAAO,KAAK,SAAS,UAAU,KAAK,SAAS;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,kBAA4B;AACjC,QAAI,KAAK,SAAS,QAAQ;AACxB,aAAO;AAAA,IACT;AACA,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,gBAAiB,KAAoB;AACjD,QAAI,eAAe,cAAc,CAAC,IAAI,eAAe;AACnD,aAAO,IAAI;AAAA,IACb;AACA,QAAI,OAAO,IAAI,UAAU,YAAY,IAAI,MAAM,SAAS,GAAG;AACzD,aAAO,IAAI,MAAM,QAAQ,gBAAgB,EAAE;AAAA,IAC7C;AACA,WAAO,IAAI,SAAA;AAAA,EACb;AACF;AAwDO,SAAS,oBAAqB,OAAgC;AACnE,QAAM,4BAAY,IAAA;AAClB,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,KAAK,WAAA,EAAa,KAAK,GAAG;AACvC,QAAI,MAAM,IAAI,IAAI,GAAG;AACnB,YAAM,IAAI,WAAW,mBAAmB,IAAI,EAAE;AAAA,IAChD;AACA,UAAM,IAAI,IAAI;AAAA,EAChB;AACF;AAQO,SAAS,cAAe,KAAU,MAAuB;AAC9D,MAAI,CAAC,MAAM,QAAQ,GAAG,GAAG;AACvB,WAAO;AAAA,EACT;AACA,aAAW,KAAK,KAAK;AACnB,YAAQ,MAAA;AAAA,MACN,KAAK;AACH,YAAI,OAAO,MAAM,SAAU,QAAO;AAClC;AAAA,MACF,KAAK;AACH,YAAI,OAAO,MAAM,SAAU,QAAO;AAClC;AAAA,MACF,KAAK;AACH,YAAI,OAAO,MAAM,UAAW,QAAO;AACnC;AAAA,MACF,KAAK;AACH,YAAI,OAAO,MAAM,SAAU,QAAO;AAClC;AAAA,MACF,KAAK;AACH,YAAI,OAAO,MAAM,WAAY,QAAO;AACpC;AAAA,MACF,KAAK;AACH,YAAI,OAAO,MAAM,YAAa,QAAO;AACrC;AAAA,MACF;AACE,eAAO;AAAA,IAAA;AAAA,EAEb;AACA,SAAO;AACT;AAOO,SAAS,WAAY,GAAoB;AAC9C,MAAI,KAAK,MAAQ,KAAK,KAAM;AAE1B,WAAO;AAAA,EACT;AACA,MAAI,KAAK,MAAQ,KAAK,IAAM;AAE1B,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAOO,SAAS,kBAAmB,QAA4F;AAC7H,MAAI;AACJ,MAAI,OAAO,WAAW,UAAU;AAC9B,YAAQ,WAAW,MAAM;AAAA,EAC3B,WAAW,kBAAkB,aAAa;AACxC,YAAQ,IAAI,WAAW,MAAM;AAAA,EAC/B,WAAW,kBAAkB,YAAY;AACvC,YAAQ;AAAA,EACV,OAAO;AACL,WAAO;AAAA,EACT;AACA,QAAM,MAAM,IAAI,WAAW,MAAM,MAAM;AACvC,MAAI,YAAY;AAChB,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,IAAI,MAAM,CAAC;AACjB,QAAI,WAAW;AACb,UAAI,WAAW,CAAC,GAAG;AACjB,oBAAY;AAAA,MACd;AAAA,IACF,WAAW,MAAM,IAAM;AACrB,kBAAY;AAAA,IACd,OAAO;AACL,UAAI,KAAK,IAAI;AAAA,IACf;AAAA,EACF;AACA,SAAO,MAAM,GAAG;AACd,UAAM,IAAI,IAAI,MAAM,CAAC;AACrB,QAAI,MAAM,MAAQ,MAAM,IAAM;AAE5B;AAAA,IACF;AACA;AAAA,EACF;AACA,QAAM,SAAS,IAAI,SAAS,GAAG,GAAG;AAClC,MAAI,OAAO,SAAS,KAAK;AACvB,WAAO;AAAA,EACT;AACA,SAAO,OAAO,aAAa,MAAM,MAAM,MAAM,KAAK,MAAM,CAAC;AAC3D;AAKO,MAAM,WAAW;AAAA,EACtB,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,iBAAiB;AACnB;AAUO,SAAS,iBAAkB,WAAqB,UAA0B;AAC/E,MAAI,MAAM,SAAS,UAAU,MAAM,IAAI,UAAU,SAAS,IAAI,sBAAsB,gBAAgB;AACpG,MAAI,SAAS,SAAS,GAAG;AACvB,WAAO,OAAO,QAAQ;AAAA,EACxB;AACA,SAAO,CAAC,GAAG,EAAE,OAAO,SAAS,EAAE,KAAK,QAAQ;AAC9C;AAOO,SAAS,oBAAqB,KAAqB;AACxD,SAAO,MAAM;AACX,UAAM,WAAW,IAAI,QAAQ,QAAQ;AACrC,QAAI,WAAW,GAAG;AAChB,aAAO;AAAA,IACT;AACA,QAAI,SAAS,WAAW;AACxB,UAAM,SAAS,IAAI,UAAU,MAAM,EAAE,QAAQ,QAAQ;AACrD,QAAI,SAAS,GAAG;AACd,aAAO,IAAI,UAAU,GAAG,QAAQ;AAAA,IAClC;AACA,cAAU,SAAS;AACnB,UAAM,SAAS,IAAI,UAAU,MAAM,EAAE,QAAQ,QAAQ;AACrD,QAAI,SAAS,GAAG;AACd,aAAO,IAAI,UAAU,GAAG,QAAQ;AAAA,IAClC;AACA,cAAU,SAAS;AACnB,UAAM,IAAI,UAAU,GAAG,QAAQ,IAAI,IAAI,UAAU,MAAM;AAAA,EACzD;AACF;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"comm.cjs","sources":["../../src/comm.ts"],"sourcesContent":["/**\n * trzsz2: https://github.com/zxdong262/trzsz2\n * Copyright(c) 2024 Lonny Wong\n * @license MIT\n *\n * Pure protocol implementation without fs/browser dependencies.\n */\n\nimport Pako from 'pako'\n\n/**\n * trzsz version\n */\nexport const trzszVersion = '2.0.0'\n\n/**\n * Convert a string to Uint8Array.\n * @param {string} str - The input string.\n * @return {Uint8Array} The resulting Uint8Array.\n */\nexport function strToUint8 (str: string): Uint8Array {\n return Uint8Array.from(str, (v) => v.charCodeAt(0))\n}\n\n/**\n * Convert a Uint8Array to string.\n * @param {Uint8Array} buf - The input buffer.\n * @param {string} encoding - The encoding to use.\n * @return {Promise<string>} The resulting string.\n */\nexport async function uint8ToStr (buf: Uint8Array, encoding: string = 'binary'): Promise<string> {\n if (typeof Buffer === 'function') {\n return Buffer.from(buf).toString(encoding as BufferEncoding)\n }\n return await new Promise<string>((resolve) => {\n const reader = new FileReader()\n reader.onloadend = () => resolve(reader.result as string)\n // Create a new ArrayBuffer copy to avoid SharedArrayBuffer issues\n const arrayBuffer = new ArrayBuffer(buf.byteLength)\n new Uint8Array(arrayBuffer).set(buf)\n const blob = new Blob([arrayBuffer])\n if (encoding === 'binary') {\n reader.readAsBinaryString(blob)\n } else {\n reader.readAsText(blob, encoding)\n }\n })\n}\n\n/**\n * Convert a string to ArrayBuffer.\n * @param {string} str - The input string.\n * @return {ArrayBuffer} The resulting ArrayBuffer.\n */\nexport function strToArrBuf (str: string): ArrayBuffer {\n const arr = strToUint8(str)\n // Create a new ArrayBuffer copy to avoid SharedArrayBuffer issues\n const buffer = new ArrayBuffer(arr.byteLength)\n new Uint8Array(buffer).set(arr)\n return buffer\n}\n\nconst _hasBuffer = typeof Buffer === 'function'\n\n// Lazy load Node.js zlib module\nlet _nodeZlib: typeof import('zlib') | null | undefined\n\n/**\n * Get Node.js zlib module if available.\n * @return {typeof import('zlib') | null} The zlib module or null if not available.\n */\nfunction getNodeZlib (): typeof import('zlib') | null {\n if (_nodeZlib === undefined) {\n try {\n // Use dynamic require for Node.js environment\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n _nodeZlib = require('zlib')\n } catch {\n _nodeZlib = null\n }\n }\n return _nodeZlib ?? null\n}\n\n/**\n * Encode Uint8Array to base64 string using native functions.\n * @param {Uint8Array} buffer - The input buffer.\n * @return {string} The base64 encoded string.\n */\nfunction uint8ToBase64 (buffer: Uint8Array): string {\n if (_hasBuffer) {\n return Buffer.from(buffer).toString('base64')\n }\n // Browser: use btoa with binary string\n let binary = ''\n for (let i = 0; i < buffer.length; i++) {\n binary += String.fromCharCode(buffer[i])\n }\n return btoa(binary)\n}\n\n/**\n * Decode base64 string to Uint8Array using native functions.\n * @param {string} base64 - The base64 encoded string.\n * @return {Uint8Array} The decoded buffer.\n */\nfunction base64ToUint8 (base64: string): Uint8Array {\n if (_hasBuffer) {\n return Buffer.from(base64, 'base64')\n }\n // Browser: use atob and convert to Uint8Array\n const binary = atob(base64)\n const buffer = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) {\n buffer[i] = binary.charCodeAt(i)\n }\n return buffer\n}\n\n/**\n * Compress data using deflate algorithm.\n * Uses Node.js native zlib in Node.js, pako in browser.\n * @param {string | Uint8Array} data - The data to compress.\n * @return {Uint8Array} The compressed data.\n */\nfunction deflate (data: string | Uint8Array): Uint8Array {\n const input = typeof data === 'string' ? strToUint8(data) : data\n\n // Try Node.js native zlib first\n const zlib = getNodeZlib()\n if (zlib != null) {\n // Use deflateSync (zlib format) to match pako's default behavior\n const result = zlib.deflateSync(input)\n // Convert Buffer to Uint8Array for consistency\n return new Uint8Array(result)\n }\n\n // Fall back to pako for browser\n return Pako.deflate(input)\n}\n\n/**\n * Decompress data using inflate algorithm.\n * Uses Node.js native zlib in Node.js, pako in browser.\n * @param {Uint8Array} data - The compressed data.\n * @return {Uint8Array} The decompressed data.\n */\nfunction inflate (data: Uint8Array): Uint8Array {\n // Try Node.js native zlib first\n const zlib = getNodeZlib()\n if (zlib != null) {\n // Use inflateSync (zlib format) to match pako's default behavior\n const result = zlib.inflateSync(data)\n // Convert Buffer to Uint8Array for consistency\n return new Uint8Array(result)\n }\n\n // Fall back to pako for browser\n return Pako.inflate(data)\n}\n\n/**\n * Encode a buffer (compress and base64).\n * @param {string | Uint8Array} buf - The input buffer.\n * @return {string} The encoded string.\n */\nexport function encodeBuffer (buf: string | Uint8Array): string {\n const buffer = deflate(buf)\n return uint8ToBase64(buffer)\n}\n\n/**\n * Decode a buffer (base64 and decompress).\n * @param {string} buf - The encoded string.\n * @return {Uint8Array} The decoded buffer.\n */\nexport function decodeBuffer (buf: string): Uint8Array {\n const buffer = base64ToUint8(buf)\n return inflate(buffer)\n}\n\n/**\n * Custom error class for trzsz operations.\n */\nexport class TrzszError extends Error {\n private readonly type: string | null\n private readonly trace: boolean\n\n constructor (message: string, type: string | null = null, trace: boolean = false) {\n if (type === 'fail' || type === 'FAIL' || type === 'EXIT') {\n try {\n message = new TextDecoder().decode(decodeBuffer(message))\n } catch {\n message = `decode [${message}] error`\n }\n } else if (type !== null) {\n message = `[TrzszError] ${type}: ${message}`\n }\n\n super(message)\n Object.setPrototypeOf(this, TrzszError.prototype)\n if (typeof Error.captureStackTrace === 'function') {\n Error.captureStackTrace(this, TrzszError)\n }\n\n this.name = 'TrzszError'\n this.type = type\n this.trace = trace\n }\n\n /**\n * Check if the error should include traceback.\n * @return {boolean} True if traceback should be included.\n */\n public isTraceBack (): boolean {\n if (this.type === 'fail' || this.type === 'EXIT') {\n return false\n }\n return this.trace\n }\n\n /**\n * Check if the error is a remote exit.\n * @return {boolean} True if remote exit.\n */\n public isRemoteExit (): boolean {\n return this.type === 'EXIT'\n }\n\n /**\n * Check if the error is a remote failure.\n * @return {boolean} True if remote failure.\n */\n public isRemoteFail (): boolean {\n return this.type === 'fail' || this.type === 'FAIL'\n }\n\n /**\n * Check if the error indicates stop and delete.\n * @return {boolean} True if stop and delete.\n */\n public isStopAndDelete (): boolean {\n if (this.type !== 'fail') {\n return false\n }\n return this.message === 'Stopped and deleted'\n }\n\n /**\n * Get the error message.\n * @param {Error} err - The error object.\n * @return {string} The error message.\n */\n public static getErrorMessage (err: Error): string {\n if (err instanceof TrzszError && !err.isTraceBack()) {\n return err.message\n }\n if (typeof err.stack === 'string' && err.stack.length > 0) {\n return err.stack.replace('TrzszError: ', '')\n }\n return err.toString()\n }\n}\n\n/**\n * Interface for trzsz file operations.\n */\nexport interface TrzszFile {\n closeFile: () => void\n}\n\n/**\n * Interface for trzsz file reader.\n */\nexport interface TrzszFileReader extends TrzszFile {\n getPathId: () => number\n getRelPath: () => string[]\n isDir: () => boolean\n getSize: () => number\n readFile: (buf: ArrayBuffer) => Promise<Uint8Array>\n}\n\n/**\n * Interface for trzsz file writer.\n */\nexport interface TrzszFileWriter extends TrzszFile {\n getFileName: () => string\n getLocalName: () => string\n isDir: () => boolean\n writeFile: (buf: Uint8Array) => Promise<void>\n deleteFile: () => Promise<string>\n}\n\n/**\n * Type for opening save file.\n */\nexport type OpenSaveFile = (\n saveParam: any,\n fileName: string,\n directory: boolean,\n overwrite: boolean,\n) => Promise<TrzszFileWriter>\n\n/**\n * Interface for progress callback.\n */\nexport interface ProgressCallback {\n onNum: (num: number) => void\n onName: (name: string) => void\n onSize: (size: number) => void\n onStep: (step: number) => void\n onDone: () => void\n}\n\n/**\n * Check for duplicate file names.\n * @param {TrzszFileReader[]} files - The files to check.\n */\nexport function checkDuplicateNames (files: TrzszFileReader[]): void {\n const names = new Set<string>()\n for (const file of files) {\n const path = file.getRelPath().join('/')\n if (names.has(path)) {\n throw new TrzszError(`Duplicate name: ${path}`)\n }\n names.add(path)\n }\n}\n\n/**\n * Check if an array contains only elements of a specific type.\n * @param {any} arr - The array to check.\n * @param {string} type - The type to check for.\n * @return {boolean} True if all elements are of the specified type.\n */\nexport function isArrayOfType (arr: any, type: string): boolean {\n if (!Array.isArray(arr)) {\n return false\n }\n for (const a of arr) {\n switch (type) {\n case 'string':\n if (typeof a !== 'string') return false\n break\n case 'number':\n if (typeof a !== 'number') return false\n break\n case 'boolean':\n if (typeof a !== 'boolean') return false\n break\n case 'object':\n if (typeof a !== 'object') return false\n break\n case 'function':\n if (typeof a !== 'function') return false\n break\n case 'undefined':\n if (typeof a !== 'undefined') return false\n break\n default:\n return false\n }\n }\n return true\n}\n\n/**\n * Check if a character is a VT100 end character.\n * @param {number} c - The character code.\n * @return {boolean} True if it's a VT100 end character.\n */\nexport function isVT100End (c: number): boolean {\n if (c >= 0x61 && c <= 0x7a) {\n // 'a' <= c && c <= 'z'\n return true\n }\n if (c >= 0x41 && c <= 0x5a) {\n // 'A' <= c && c <= 'Z'\n return true\n }\n return false\n}\n\n/**\n * Strip VT100 escape sequences from server output.\n * @param {string | ArrayBuffer | Uint8Array | Blob} output - The server output.\n * @return {string | ArrayBuffer | Uint8Array | Blob} The stripped output.\n */\nexport function stripServerOutput (output: string | ArrayBuffer | Uint8Array | Blob): string | ArrayBuffer | Uint8Array | Blob {\n let uint8: Uint8Array\n if (typeof output === 'string') {\n uint8 = strToUint8(output)\n } else if (output instanceof ArrayBuffer) {\n uint8 = new Uint8Array(output)\n } else if (output instanceof Uint8Array) {\n uint8 = output\n } else {\n return output\n }\n const buf = new Uint8Array(uint8.length)\n let skipVT100 = false\n let idx = 0\n for (let i = 0; i < uint8.length; i++) {\n const c = uint8[i]\n if (skipVT100) {\n if (isVT100End(c)) {\n skipVT100 = false\n }\n } else if (c === 0x1b) {\n skipVT100 = true\n } else {\n buf[idx++] = c\n }\n }\n while (idx > 0) {\n const c = buf[idx - 1]\n if (c !== 0x0d && c !== 0x0a) {\n // not \\r\\n\n break\n }\n idx--\n }\n const result = buf.subarray(0, idx)\n if (result.length > 100) {\n return output\n }\n return String.fromCharCode.apply(null, Array.from(result))\n}\n\n/**\n * Tmux mode constants.\n */\nexport const TmuxMode = {\n NoTmux: 0,\n TmuxNormalMode: 1,\n TmuxControlMode: 2\n} as const\n\nexport type TmuxModeType = (typeof TmuxMode)[keyof typeof TmuxMode]\n\n/**\n * Format saved files message.\n * @param {string[]} fileNames - The file names.\n * @param {string} destPath - The destination path.\n * @return {string} The formatted message.\n */\nexport function formatSavedFiles (fileNames: string[], destPath: string): string {\n let msg = `Saved ${fileNames.length} ${fileNames.length > 1 ? 'files/directories' : 'file/directory'}`\n if (destPath.length > 0) {\n msg += ` to ${destPath}`\n }\n return [msg].concat(fileNames).join('\\r\\n- ')\n}\n\n/**\n * Strip tmux status line from buffer.\n * @param {string} buf - The input buffer.\n * @return {string} The stripped buffer.\n */\nexport function stripTmuxStatusLine (buf: string): string {\n while (true) {\n const beginIdx = buf.indexOf('\\x1bP=')\n if (beginIdx < 0) {\n return buf\n }\n let bufIdx = beginIdx + 3\n const midIdx = buf.substring(bufIdx).indexOf('\\x1bP=')\n if (midIdx < 0) {\n return buf.substring(0, beginIdx)\n }\n bufIdx += midIdx + 3\n const endIdx = buf.substring(bufIdx).indexOf('\\x1b\\\\')\n if (endIdx < 0) {\n return buf.substring(0, beginIdx)\n }\n bufIdx += endIdx + 2\n buf = buf.substring(0, beginIdx) + buf.substring(bufIdx)\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const md5 = require("./node_modules/ts-md5/dist/esm/md5.cjs");
3
+ const tsMd5 = require("ts-md5");
4
4
  const buffer = require("./buffer.cjs");
5
5
  const escape = require("./escape.cjs");
6
6
  const comm = require("./comm.cjs");
@@ -496,12 +496,12 @@ class TrzszTransfer {
496
496
  }
497
497
  let bufSize = 1024;
498
498
  let buffer2 = new ArrayBuffer(bufSize);
499
- const md5$1 = new md5.Md5();
499
+ const md5 = new tsMd5.Md5();
500
500
  while (step < size) {
501
501
  const beginTime = Date.now();
502
502
  const data = await file.readFile(buffer2);
503
503
  await this.sendData(data, binary, escapeCodes);
504
- md5$1.appendByteArray(data);
504
+ md5.appendByteArray(data);
505
505
  await this.checkInteger(data.length);
506
506
  step += data.length;
507
507
  if (progressCallback != null) {
@@ -519,7 +519,7 @@ class TrzszTransfer {
519
519
  this.maxChunkTimeInMilliseconds = chunkTime;
520
520
  }
521
521
  }
522
- return new Uint8Array(md5$1.end(true).buffer);
522
+ return new Uint8Array(md5.end(true).buffer);
523
523
  }
524
524
  /**
525
525
  * Send file MD5.
@@ -619,7 +619,7 @@ class TrzszTransfer {
619
619
  if (progressCallback != null) {
620
620
  progressCallback.onStep(step);
621
621
  }
622
- const md5$1 = new md5.Md5();
622
+ const md5 = new tsMd5.Md5();
623
623
  while (step < size) {
624
624
  const beginTime = Date.now();
625
625
  const data = await this.recvData(binary, escapeCodes, timeoutInMilliseconds);
@@ -629,13 +629,13 @@ class TrzszTransfer {
629
629
  progressCallback.onStep(step);
630
630
  }
631
631
  await this.sendInteger("SUCC", data.length);
632
- md5$1.appendByteArray(data);
632
+ md5.appendByteArray(data);
633
633
  const chunkTime = Date.now() - beginTime;
634
634
  if (chunkTime > this.maxChunkTimeInMilliseconds) {
635
635
  this.maxChunkTimeInMilliseconds = chunkTime;
636
636
  }
637
637
  }
638
- return new Uint8Array(md5$1.end(true).buffer);
638
+ return new Uint8Array(md5.end(true).buffer);
639
639
  }
640
640
  /**
641
641
  * Receive file MD5.
@@ -1 +1 @@
1
- {"version":3,"file":"transfer.cjs","sources":["../../src/transfer.ts"],"sourcesContent":["/**\n * trzsz2: https://github.com/zxdong262/trzsz2\n * Copyright(c) 2024 Lonny Wong\n * @license MIT\n *\n * Pure protocol implementation without fs/browser dependencies.\n */\n\nimport { Md5 } from 'ts-md5'\nimport { TrzszBuffer } from './buffer'\nimport { escapeCharsToCodes, escapeData, unescapeData } from './escape'\nimport {\n trzszVersion,\n uint8ToStr,\n encodeBuffer,\n decodeBuffer,\n TmuxMode,\n TrzszError,\n type TrzszFile,\n type OpenSaveFile,\n type TrzszFileReader,\n type TrzszFileWriter,\n type ProgressCallback,\n stripTmuxStatusLine\n} from './comm'\n\n/**\n * TrzszTransfer class for handling file transfer protocol.\n */\nexport class TrzszTransfer {\n private readonly buffer: TrzszBuffer = new TrzszBuffer()\n private readonly writer: (data: string | Uint8Array) => void\n private readonly isWindowsShell: boolean\n private remoteIsWindows: boolean = false\n private lastInputTime: number = 0\n private readonly openedFiles: TrzszFile[] = []\n private readonly createdFiles: TrzszFileWriter[] = []\n private tmuxOutputJunk: boolean = false\n private cleanTimeoutInMilliseconds: number = 100\n private transferConfig: Record<string, unknown> = {}\n private stopped: boolean = false\n private maxChunkTimeInMilliseconds: number = 0\n private protocolNewline: string = '\\n'\n\n /**\n * Create a TrzszTransfer.\n * @param writer - The output writer function.\n * @param isWindowsShell - Whether the shell is Windows.\n */\n public constructor (writer: (data: string | Uint8Array) => void, isWindowsShell: boolean = false) {\n this.writer = writer\n this.isWindowsShell = isWindowsShell\n }\n\n /**\n * Cleanup resources.\n */\n public cleanup (): void {\n for (const file of this.openedFiles) {\n file.closeFile()\n }\n }\n\n /**\n * Add received data to the buffer.\n * @param data - The received data.\n */\n public addReceivedData (data: string | ArrayBuffer | Uint8Array | Blob): void {\n if (!this.stopped) {\n this.buffer.addBuffer(data)\n }\n this.lastInputTime = Date.now()\n }\n\n /**\n * Stop transferring.\n */\n public async stopTransferring (): Promise<void> {\n this.cleanTimeoutInMilliseconds = Math.max(this.maxChunkTimeInMilliseconds * 2, 500)\n this.stopped = true\n this.buffer.stopBuffer()\n }\n\n /**\n * Clean input buffer.\n * @param timeoutInMilliseconds - The timeout in milliseconds.\n */\n private async cleanInput (timeoutInMilliseconds: number): Promise<void> {\n this.stopped = true\n this.buffer.drainBuffer()\n this.lastInputTime = Date.now()\n while (true) {\n const sleepTime = timeoutInMilliseconds - (Date.now() - this.lastInputTime)\n if (sleepTime <= 0) {\n return\n }\n await new Promise((resolve) => setTimeout(resolve, sleepTime))\n }\n }\n\n /**\n * Send a line.\n * @param typ - The type.\n * @param buf - The buffer.\n */\n private async sendLine (typ: string, buf: string): Promise<void> {\n this.writer(`#${typ}:${buf}${this.protocolNewline}`)\n }\n\n /**\n * Receive a line.\n * @param expectType - The expected type.\n * @param mayHasJunk - Whether there may be junk.\n */\n private async recvLine (expectType: string, mayHasJunk: boolean = false): Promise<string> {\n if (this.stopped) {\n throw new TrzszError('Stopped')\n }\n\n if (this.isWindowsShell || this.remoteIsWindows) {\n let line = await this.buffer.readLineOnWindows()\n const idx = line.lastIndexOf('#' + expectType + ':')\n if (idx >= 0) {\n line = line.substring(idx)\n } else {\n const idx = line.lastIndexOf('#')\n if (idx > 0) {\n line = line.substring(idx)\n }\n }\n return line\n }\n\n let line = await this.buffer.readLine()\n\n if (this.tmuxOutputJunk || mayHasJunk) {\n if (line.length > 0) {\n while (line[line.length - 1] === '\\r') {\n line = line.substring(0, line.length - 1) + (await this.buffer.readLine())\n }\n }\n const idx = line.lastIndexOf('#' + expectType + ':')\n if (idx >= 0) {\n line = line.substring(idx)\n } else {\n const idx = line.lastIndexOf('#')\n if (idx > 0) {\n line = line.substring(idx)\n }\n }\n line = stripTmuxStatusLine(line)\n }\n\n return line\n }\n\n /**\n * Receive and check a line.\n * @param expectType - The expected type.\n * @param mayHasJunk - Whether there may be junk.\n */\n private async recvCheck (expectType: string, mayHasJunk: boolean = false): Promise<string> {\n const line = await this.recvLine(expectType, mayHasJunk)\n const idx = line.indexOf(':')\n if (idx < 1) {\n throw new TrzszError(encodeBuffer(line), 'colon', true)\n }\n const typ = line.substring(1, idx)\n const buf = line.substring(idx + 1)\n if (typ !== expectType) {\n throw new TrzszError(buf, typ, true)\n }\n return buf\n }\n\n /**\n * Send an integer.\n * @param typ - The type.\n * @param val - The value.\n */\n private async sendInteger (typ: string, val: number): Promise<void> {\n await this.sendLine(typ, val.toString())\n }\n\n /**\n * Receive an integer.\n * @param typ - The type.\n * @param mayHasJunk - Whether there may be junk.\n */\n private async recvInteger (typ: string, mayHasJunk: boolean = false): Promise<number> {\n const buf = await this.recvCheck(typ, mayHasJunk)\n return Number(buf)\n }\n\n /**\n * Check an integer.\n * @param expect - The expected value.\n */\n private async checkInteger (expect: number): Promise<void> {\n const result = await this.recvInteger('SUCC')\n if (result !== expect) {\n throw new TrzszError(`Integer check [${result}] <> [${expect}]`, null, true)\n }\n }\n\n /**\n * Send a string.\n * @param typ - The type.\n * @param str - The string.\n */\n private async sendString (typ: string, str: string): Promise<void> {\n await this.sendLine(typ, encodeBuffer(str))\n }\n\n /**\n * Receive a string.\n * @param typ - The type.\n * @param mayHasJunk - Whether there may be junk.\n */\n private async recvString (typ: string, mayHasJunk: boolean = false): Promise<string> {\n const buf = await this.recvCheck(typ, mayHasJunk)\n return await uint8ToStr(decodeBuffer(buf), 'utf8')\n }\n\n /**\n * Check a string.\n * @param expect - The expected string.\n */\n protected async checkString (expect: string): Promise<void> {\n const result = await this.recvString('SUCC')\n if (result !== expect) {\n throw new TrzszError(`String check [${result}] <> [${expect}]`, null, true)\n }\n }\n\n /**\n * Send binary data.\n * @param typ - The type.\n * @param buf - The buffer.\n */\n private async sendBinary (typ: string, buf: Uint8Array): Promise<void> {\n await this.sendLine(typ, encodeBuffer(buf))\n }\n\n /**\n * Receive binary data.\n * @param typ - The type.\n * @param mayHasJunk - Whether there may be junk.\n */\n private async recvBinary (typ: string, mayHasJunk: boolean = false): Promise<Uint8Array> {\n const buf = await this.recvCheck(typ, mayHasJunk)\n return decodeBuffer(buf)\n }\n\n /**\n * Check binary data.\n * @param expect - The expected buffer.\n */\n private async checkBinary (expect: Uint8Array): Promise<void> {\n const result = await this.recvBinary('SUCC')\n if (result.length !== expect.length) {\n throw new TrzszError(\n `Binary length check [${result.length}] <> [${expect.length}]`,\n null,\n true\n )\n }\n for (let i = 0; i < result.length; i++) {\n if (result[i] !== expect[i]) {\n throw new TrzszError(`Binary check [${result[i]}] <> [${expect[i]}]`, null, true)\n }\n }\n }\n\n /**\n * Send data.\n * @param data - The data.\n * @param binary - Whether to use binary mode.\n * @param escapeCodes - The escape codes.\n */\n private async sendData (\n data: Uint8Array,\n binary: boolean,\n escapeCodes: number[][]\n ): Promise<void> {\n if (!binary) {\n await this.sendBinary('DATA', data)\n return\n }\n\n const buf = escapeData(data, escapeCodes)\n this.writer(`#DATA:${buf.length}\\n`)\n this.writer(buf)\n }\n\n /**\n * Receive data.\n * @param binary - Whether to use binary mode.\n * @param escapeCodes - The escape codes.\n * @param timeoutInMilliseconds - The timeout in milliseconds.\n */\n private async recvData (\n binary: boolean,\n escapeCodes: number[][],\n timeoutInMilliseconds: number\n ): Promise<Uint8Array> {\n return await Promise.race<Uint8Array>([\n new Promise<Uint8Array>((_resolve, reject) =>\n setTimeout(() => {\n this.cleanTimeoutInMilliseconds = 3000\n reject(new TrzszError('Receive data timeout'))\n }, timeoutInMilliseconds)\n ),\n (async () => {\n if (!binary) {\n return await this.recvBinary('DATA')\n }\n const size = await this.recvInteger('DATA')\n const data = await this.buffer.readBinary(size)\n return unescapeData(data, escapeCodes)\n })()\n ])\n }\n\n /**\n * Send action.\n * @param confirm - Whether to confirm.\n * @param remoteIsWindows - Whether the remote is Windows.\n */\n public async sendAction (confirm: boolean, remoteIsWindows: boolean): Promise<void> {\n const action: Record<string, unknown> = {\n lang: 'js',\n confirm,\n version: trzszVersion,\n support_dir: true\n }\n if (this.isWindowsShell || remoteIsWindows) {\n action.binary = false\n action.newline = '!\\n'\n }\n if (remoteIsWindows) {\n this.remoteIsWindows = true\n this.protocolNewline = '!\\n'\n }\n await this.sendString('ACT', JSON.stringify(action))\n }\n\n /**\n * Receive action.\n */\n public async recvAction (): Promise<Record<string, unknown>> {\n const buf = await this.recvString('ACT', true)\n const action = JSON.parse(buf)\n const newline = (action as Record<string, unknown>).newline as string | undefined\n if (typeof newline === 'string' && newline.length > 0) {\n this.protocolNewline = newline\n }\n return action\n }\n\n /**\n * Send config.\n * @param args - The config arguments.\n * @param escapeChars - The escape characters.\n * @param tmuxMode - The tmux mode.\n * @param tmuxPaneWidth - The tmux pane width.\n */\n public async sendConfig (\n args: Record<string, unknown>,\n escapeChars: string[][],\n tmuxMode: number,\n tmuxPaneWidth: number\n ): Promise<void> {\n const config: Record<string, unknown> = { lang: 'js' }\n if ((args).quiet === true) {\n config.quiet = true\n }\n if ((args).binary === true) {\n config.binary = true\n config.escape_chars = escapeChars\n }\n if ((args).directory === true) {\n config.directory = true\n }\n if (typeof (args).bufsize === 'number') {\n config.bufsize = (args).bufsize\n }\n if (typeof (args).timeout === 'number') {\n config.timeout = (args).timeout\n }\n if ((args).overwrite === true) {\n config.overwrite = true\n }\n if (tmuxMode === TmuxMode.TmuxNormalMode) {\n config.tmux_output_junk = true\n }\n if (tmuxPaneWidth > 0) {\n config.tmux_pane_width = tmuxPaneWidth\n }\n let jsonStr = JSON.stringify(config)\n jsonStr = jsonStr.replace(/[\\u007F-\\uFFFF]/g, function (chr) {\n return '\\\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4)\n })\n this.transferConfig = config\n await this.sendString('CFG', jsonStr)\n }\n\n /**\n * Receive config.\n */\n public async recvConfig (): Promise<Record<string, unknown>> {\n const buf = await this.recvString('CFG', true)\n this.transferConfig = JSON.parse(buf)\n this.tmuxOutputJunk = this.transferConfig.tmux_output_junk === true\n return this.transferConfig\n }\n\n /**\n * Send client exit.\n * @param msg - The message.\n */\n public async clientExit (msg: string): Promise<void> {\n await this.sendString('EXIT', msg)\n }\n\n /**\n * Receive exit.\n */\n public async recvExit (): Promise<string> {\n return await this.recvString('EXIT')\n }\n\n /**\n * Delete created files.\n */\n private async deleteCreatedFiles (): Promise<string[]> {\n const deletedFiles: string[] = []\n for (const file of this.createdFiles) {\n const path = await file.deleteFile()\n if (typeof path === 'string' && path.length > 0) {\n deletedFiles.push(path)\n }\n }\n return deletedFiles\n }\n\n /**\n * Handle client error.\n * @param err - The error.\n */\n public async clientError (err: Error): Promise<void> {\n await this.cleanInput(this.cleanTimeoutInMilliseconds)\n\n const errMsg = TrzszError.getErrorMessage(err)\n let trace = true\n if (err instanceof TrzszError) {\n trace = err.isTraceBack()\n if (err.isRemoteExit()) {\n return\n }\n if (err.isRemoteFail()) {\n if (trace) {\n console.log(errMsg)\n }\n return\n }\n }\n\n await this.sendString(trace ? 'FAIL' : 'fail', errMsg)\n if (trace) {\n console.log(errMsg)\n }\n }\n\n /**\n * Handle server error.\n * @param err - The error.\n */\n public async serverError (err: Error): Promise<void> {\n await this.cleanInput(this.cleanTimeoutInMilliseconds)\n\n const errMsg = TrzszError.getErrorMessage(err)\n let trace = true\n if (err instanceof TrzszError) {\n if (err.isStopAndDelete()) {\n const deletedFiles = await this.deleteCreatedFiles()\n if (deletedFiles.length > 0) {\n await this.serverExit([err.message + ':'].concat(deletedFiles).join('\\r\\n- '))\n return\n }\n }\n trace = err.isTraceBack()\n if (err.isRemoteExit() || err.isRemoteFail()) {\n await this.serverExit(errMsg)\n return\n }\n }\n\n await this.sendString(trace ? 'FAIL' : 'fail', errMsg)\n await this.serverExit(errMsg)\n }\n\n /**\n * Server exit - to be implemented by subclass or user.\n * @param msg - The message.\n */\n public async serverExit (_msg: string): Promise<void> {\n // Base implementation does nothing\n // Subclasses or users should override this\n }\n\n /**\n * Send file number.\n * @param num - The number of files.\n * @param progressCallback - The progress callback.\n */\n private async sendFileNum (num: number, progressCallback: ProgressCallback | null): Promise<void> {\n await this.sendInteger('NUM', num)\n await this.checkInteger(num)\n if (progressCallback != null) {\n progressCallback.onNum(num)\n }\n }\n\n /**\n * Send file name.\n * @param file - The file reader.\n * @param directory - Whether it's a directory.\n * @param progressCallback - The progress callback.\n */\n private async sendFileName (\n file: TrzszFileReader,\n directory: boolean,\n progressCallback: ProgressCallback | null\n ): Promise<string> {\n const relPath = file.getRelPath()\n const fileName = relPath[relPath.length - 1]\n if (directory) {\n const jsonName = {\n path_id: file.getPathId(),\n path_name: relPath,\n is_dir: file.isDir()\n }\n await this.sendString('NAME', JSON.stringify(jsonName))\n } else {\n await this.sendString('NAME', fileName)\n }\n const remoteName = await this.recvString('SUCC')\n if (progressCallback != null) {\n progressCallback.onName(fileName)\n }\n return remoteName\n }\n\n /**\n * Send file size.\n * @param size - The file size.\n * @param progressCallback - The progress callback.\n */\n private async sendFileSize (\n size: number,\n progressCallback: ProgressCallback | null\n ): Promise<void> {\n await this.sendInteger('SIZE', size)\n await this.checkInteger(size)\n if (progressCallback != null) {\n progressCallback.onSize(size)\n }\n }\n\n /**\n * Send file data.\n * @param file - The file reader.\n * @param size - The file size.\n * @param binary - Whether to use binary mode.\n * @param escapeCodes - The escape codes.\n * @param maxBufSize - The maximum buffer size.\n * @param progressCallback - The progress callback.\n */\n private async sendFileData (\n file: TrzszFileReader,\n size: number,\n binary: boolean,\n escapeCodes: number[][],\n maxBufSize: number,\n progressCallback: ProgressCallback | null\n ): Promise<Uint8Array> {\n let step = 0\n if (progressCallback != null) {\n progressCallback.onStep(step)\n }\n let bufSize = 1024\n let buffer = new ArrayBuffer(bufSize)\n const md5 = new Md5()\n while (step < size) {\n const beginTime = Date.now()\n const data = await file.readFile(buffer)\n await this.sendData(data, binary, escapeCodes)\n md5.appendByteArray(data)\n await this.checkInteger(data.length)\n step += data.length\n if (progressCallback != null) {\n progressCallback.onStep(step)\n }\n const chunkTime = Date.now() - beginTime\n if (data.length === bufSize && chunkTime < 500 && bufSize < maxBufSize) {\n bufSize = Math.min(bufSize * 2, maxBufSize)\n buffer = new ArrayBuffer(bufSize)\n } else if (chunkTime >= 2000 && bufSize > 1024) {\n bufSize = 1024\n buffer = new ArrayBuffer(bufSize)\n }\n if (chunkTime > this.maxChunkTimeInMilliseconds) {\n this.maxChunkTimeInMilliseconds = chunkTime\n }\n }\n return new Uint8Array((md5.end(true) as Int32Array).buffer)\n }\n\n /**\n * Send file MD5.\n * @param digest - The MD5 digest.\n * @param progressCallback - The progress callback.\n */\n private async sendFileMD5 (\n digest: Uint8Array,\n progressCallback: ProgressCallback | null\n ): Promise<void> {\n await this.sendBinary('MD5', digest)\n await this.checkBinary(digest)\n if (progressCallback != null) {\n progressCallback.onDone()\n }\n }\n\n /**\n * Send files.\n * @param files - The file readers.\n * @param progressCallback - The progress callback.\n */\n public async sendFiles (\n files: TrzszFileReader[],\n progressCallback: ProgressCallback | null\n ): Promise<string[]> {\n this.openedFiles.push(...files)\n\n const binary = this.transferConfig.binary === true\n const directory = this.transferConfig.directory === true\n const bufsizeVal = this.transferConfig.bufsize as number | undefined\n const maxBufSize = typeof bufsizeVal === 'number' ? bufsizeVal : 10 * 1024 * 1024\n const escapeCodes = Array.isArray(this.transferConfig.escape_chars)\n ? escapeCharsToCodes(this.transferConfig.escape_chars as string[][])\n : []\n\n await this.sendFileNum(files.length, progressCallback)\n\n const remoteNames: string[] = []\n for (const file of files) {\n const remoteName = await this.sendFileName(file, directory, progressCallback)\n\n if (!remoteNames.includes(remoteName)) {\n remoteNames.push(remoteName)\n }\n\n if (file.isDir()) {\n continue\n }\n\n const size = file.getSize()\n await this.sendFileSize(size, progressCallback)\n\n const digest = await this.sendFileData(file, size, binary, escapeCodes, maxBufSize, progressCallback)\n file.closeFile()\n\n await this.sendFileMD5(digest, progressCallback)\n }\n\n return remoteNames\n }\n\n /**\n * Receive file number.\n * @param progressCallback - The progress callback.\n */\n private async recvFileNum (progressCallback: ProgressCallback | null): Promise<number> {\n const num = await this.recvInteger('NUM')\n await this.sendInteger('SUCC', num)\n if (progressCallback != null) {\n progressCallback.onNum(num)\n }\n return num\n }\n\n /**\n * Receive file name.\n * @param saveParam - The save parameter.\n * @param openSaveFile - The open save file function.\n * @param directory - Whether it's a directory.\n * @param overwrite - Whether to overwrite.\n * @param progressCallback - The progress callback.\n */\n private async recvFileName (\n saveParam: unknown,\n openSaveFile: OpenSaveFile,\n directory: boolean,\n overwrite: boolean,\n progressCallback: ProgressCallback | null\n ): Promise<TrzszFileWriter> {\n const fileName = await this.recvString('NAME')\n const file = await openSaveFile(saveParam, fileName, directory, overwrite)\n this.createdFiles.push(file)\n await this.sendString('SUCC', file.getLocalName())\n if (progressCallback != null) {\n progressCallback.onName(file.getFileName())\n }\n return file\n }\n\n /**\n * Receive file size.\n * @param progressCallback - The progress callback.\n */\n private async recvFileSize (progressCallback: ProgressCallback | null): Promise<number> {\n const fileSize = await this.recvInteger('SIZE')\n await this.sendInteger('SUCC', fileSize)\n if (progressCallback != null) {\n progressCallback.onSize(fileSize)\n }\n return fileSize\n }\n\n /**\n * Receive file data.\n * @param file - The file writer.\n * @param size - The file size.\n * @param binary - Whether to use binary mode.\n * @param escapeCodes - The escape codes.\n * @param timeoutInMilliseconds - The timeout in milliseconds.\n * @param progressCallback - The progress callback.\n */\n private async recvFileData (\n file: TrzszFileWriter,\n size: number,\n binary: boolean,\n escapeCodes: number[][],\n timeoutInMilliseconds: number,\n progressCallback: ProgressCallback | null\n ): Promise<Uint8Array> {\n let step = 0\n if (progressCallback != null) {\n progressCallback.onStep(step)\n }\n const md5 = new Md5()\n while (step < size) {\n const beginTime = Date.now()\n const data = await this.recvData(binary, escapeCodes, timeoutInMilliseconds)\n await file.writeFile(data)\n step += data.length\n if (progressCallback != null) {\n progressCallback.onStep(step)\n }\n await this.sendInteger('SUCC', data.length)\n md5.appendByteArray(data)\n const chunkTime = Date.now() - beginTime\n if (chunkTime > this.maxChunkTimeInMilliseconds) {\n this.maxChunkTimeInMilliseconds = chunkTime\n }\n }\n return new Uint8Array((md5.end(true) as Int32Array).buffer)\n }\n\n /**\n * Receive file MD5.\n * @param digest - The MD5 digest.\n * @param progressCallback - The progress callback.\n */\n private async recvFileMD5 (\n digest: Uint8Array,\n progressCallback: ProgressCallback | null\n ): Promise<void> {\n const expectDigest = await this.recvBinary('MD5')\n if (digest.length !== expectDigest.length) {\n throw new TrzszError('Check MD5 failed')\n }\n for (let j = 0; j < digest.length; j++) {\n if (digest[j] !== expectDigest[j]) {\n throw new TrzszError('Check MD5 failed')\n }\n }\n await this.sendBinary('SUCC', digest)\n if (progressCallback != null) {\n progressCallback.onDone()\n }\n }\n\n /**\n * Receive files.\n * @param saveParam - The save parameter.\n * @param openSaveFile - The open save file function.\n * @param progressCallback - The progress callback.\n */\n public async recvFiles (\n saveParam: unknown,\n openSaveFile: OpenSaveFile,\n progressCallback: ProgressCallback | null\n ): Promise<string[]> {\n const binary = this.transferConfig.binary === true\n const directory = this.transferConfig.directory === true\n const overwrite = this.transferConfig.overwrite === true\n const timeoutVal = this.transferConfig.timeout as number | undefined\n const timeoutInMilliseconds = typeof timeoutVal === 'number' ? timeoutVal * 1000 : 100000\n const escapeCodes = Array.isArray(this.transferConfig.escape_chars)\n ? escapeCharsToCodes(this.transferConfig.escape_chars as string[][])\n : []\n\n const num = await this.recvFileNum(progressCallback)\n\n const localNames: string[] = []\n for (let i = 0; i < num; i++) {\n const file = await this.recvFileName(\n saveParam,\n openSaveFile,\n directory,\n overwrite,\n progressCallback\n )\n\n if (!localNames.includes(file.getLocalName())) {\n localNames.push(file.getLocalName())\n }\n\n if (file.isDir()) {\n continue\n }\n\n this.openedFiles.push(file)\n\n const size = await this.recvFileSize(progressCallback)\n\n const digest = await this.recvFileData(\n file,\n size,\n binary,\n escapeCodes,\n timeoutInMilliseconds,\n progressCallback\n )\n file.closeFile()\n\n await this.recvFileMD5(digest, progressCallback)\n }\n\n return localNames\n }\n}\n"],"names":["TrzszBuffer","TrzszError","line","idx","stripTmuxStatusLine","encodeBuffer","uint8ToStr","decodeBuffer","escapeData","unescapeData","trzszVersion","TmuxMode","buffer","md5","Md5","escapeCharsToCodes"],"mappings":"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"}
1
+ {"version":3,"file":"transfer.cjs","sources":["../../src/transfer.ts"],"sourcesContent":["/**\n * trzsz2: https://github.com/zxdong262/trzsz2\n * Copyright(c) 2024 Lonny Wong\n * @license MIT\n *\n * Pure protocol implementation without fs/browser dependencies.\n */\n\nimport { Md5 } from 'ts-md5'\nimport { TrzszBuffer } from './buffer'\nimport { escapeCharsToCodes, escapeData, unescapeData } from './escape'\nimport {\n trzszVersion,\n uint8ToStr,\n encodeBuffer,\n decodeBuffer,\n TmuxMode,\n TrzszError,\n type TrzszFile,\n type OpenSaveFile,\n type TrzszFileReader,\n type TrzszFileWriter,\n type ProgressCallback,\n stripTmuxStatusLine\n} from './comm'\n\n/**\n * TrzszTransfer class for handling file transfer protocol.\n */\nexport class TrzszTransfer {\n private readonly buffer: TrzszBuffer = new TrzszBuffer()\n private readonly writer: (data: string | Uint8Array) => void\n private readonly isWindowsShell: boolean\n private remoteIsWindows: boolean = false\n private lastInputTime: number = 0\n private readonly openedFiles: TrzszFile[] = []\n private readonly createdFiles: TrzszFileWriter[] = []\n private tmuxOutputJunk: boolean = false\n private cleanTimeoutInMilliseconds: number = 100\n private transferConfig: Record<string, unknown> = {}\n private stopped: boolean = false\n private maxChunkTimeInMilliseconds: number = 0\n private protocolNewline: string = '\\n'\n\n /**\n * Create a TrzszTransfer.\n * @param writer - The output writer function.\n * @param isWindowsShell - Whether the shell is Windows.\n */\n public constructor (writer: (data: string | Uint8Array) => void, isWindowsShell: boolean = false) {\n this.writer = writer\n this.isWindowsShell = isWindowsShell\n }\n\n /**\n * Cleanup resources.\n */\n public cleanup (): void {\n for (const file of this.openedFiles) {\n file.closeFile()\n }\n }\n\n /**\n * Add received data to the buffer.\n * @param data - The received data.\n */\n public addReceivedData (data: string | ArrayBuffer | Uint8Array | Blob): void {\n if (!this.stopped) {\n this.buffer.addBuffer(data)\n }\n this.lastInputTime = Date.now()\n }\n\n /**\n * Stop transferring.\n */\n public async stopTransferring (): Promise<void> {\n this.cleanTimeoutInMilliseconds = Math.max(this.maxChunkTimeInMilliseconds * 2, 500)\n this.stopped = true\n this.buffer.stopBuffer()\n }\n\n /**\n * Clean input buffer.\n * @param timeoutInMilliseconds - The timeout in milliseconds.\n */\n private async cleanInput (timeoutInMilliseconds: number): Promise<void> {\n this.stopped = true\n this.buffer.drainBuffer()\n this.lastInputTime = Date.now()\n while (true) {\n const sleepTime = timeoutInMilliseconds - (Date.now() - this.lastInputTime)\n if (sleepTime <= 0) {\n return\n }\n await new Promise((resolve) => setTimeout(resolve, sleepTime))\n }\n }\n\n /**\n * Send a line.\n * @param typ - The type.\n * @param buf - The buffer.\n */\n private async sendLine (typ: string, buf: string): Promise<void> {\n this.writer(`#${typ}:${buf}${this.protocolNewline}`)\n }\n\n /**\n * Receive a line.\n * @param expectType - The expected type.\n * @param mayHasJunk - Whether there may be junk.\n */\n private async recvLine (expectType: string, mayHasJunk: boolean = false): Promise<string> {\n if (this.stopped) {\n throw new TrzszError('Stopped')\n }\n\n if (this.isWindowsShell || this.remoteIsWindows) {\n let line = await this.buffer.readLineOnWindows()\n const idx = line.lastIndexOf('#' + expectType + ':')\n if (idx >= 0) {\n line = line.substring(idx)\n } else {\n const idx = line.lastIndexOf('#')\n if (idx > 0) {\n line = line.substring(idx)\n }\n }\n return line\n }\n\n let line = await this.buffer.readLine()\n\n if (this.tmuxOutputJunk || mayHasJunk) {\n if (line.length > 0) {\n while (line[line.length - 1] === '\\r') {\n line = line.substring(0, line.length - 1) + (await this.buffer.readLine())\n }\n }\n const idx = line.lastIndexOf('#' + expectType + ':')\n if (idx >= 0) {\n line = line.substring(idx)\n } else {\n const idx = line.lastIndexOf('#')\n if (idx > 0) {\n line = line.substring(idx)\n }\n }\n line = stripTmuxStatusLine(line)\n }\n\n return line\n }\n\n /**\n * Receive and check a line.\n * @param expectType - The expected type.\n * @param mayHasJunk - Whether there may be junk.\n */\n private async recvCheck (expectType: string, mayHasJunk: boolean = false): Promise<string> {\n const line = await this.recvLine(expectType, mayHasJunk)\n const idx = line.indexOf(':')\n if (idx < 1) {\n throw new TrzszError(encodeBuffer(line), 'colon', true)\n }\n const typ = line.substring(1, idx)\n const buf = line.substring(idx + 1)\n if (typ !== expectType) {\n throw new TrzszError(buf, typ, true)\n }\n return buf\n }\n\n /**\n * Send an integer.\n * @param typ - The type.\n * @param val - The value.\n */\n private async sendInteger (typ: string, val: number): Promise<void> {\n await this.sendLine(typ, val.toString())\n }\n\n /**\n * Receive an integer.\n * @param typ - The type.\n * @param mayHasJunk - Whether there may be junk.\n */\n private async recvInteger (typ: string, mayHasJunk: boolean = false): Promise<number> {\n const buf = await this.recvCheck(typ, mayHasJunk)\n return Number(buf)\n }\n\n /**\n * Check an integer.\n * @param expect - The expected value.\n */\n private async checkInteger (expect: number): Promise<void> {\n const result = await this.recvInteger('SUCC')\n if (result !== expect) {\n throw new TrzszError(`Integer check [${result}] <> [${expect}]`, null, true)\n }\n }\n\n /**\n * Send a string.\n * @param typ - The type.\n * @param str - The string.\n */\n private async sendString (typ: string, str: string): Promise<void> {\n await this.sendLine(typ, encodeBuffer(str))\n }\n\n /**\n * Receive a string.\n * @param typ - The type.\n * @param mayHasJunk - Whether there may be junk.\n */\n private async recvString (typ: string, mayHasJunk: boolean = false): Promise<string> {\n const buf = await this.recvCheck(typ, mayHasJunk)\n return await uint8ToStr(decodeBuffer(buf), 'utf8')\n }\n\n /**\n * Check a string.\n * @param expect - The expected string.\n */\n protected async checkString (expect: string): Promise<void> {\n const result = await this.recvString('SUCC')\n if (result !== expect) {\n throw new TrzszError(`String check [${result}] <> [${expect}]`, null, true)\n }\n }\n\n /**\n * Send binary data.\n * @param typ - The type.\n * @param buf - The buffer.\n */\n private async sendBinary (typ: string, buf: Uint8Array): Promise<void> {\n await this.sendLine(typ, encodeBuffer(buf))\n }\n\n /**\n * Receive binary data.\n * @param typ - The type.\n * @param mayHasJunk - Whether there may be junk.\n */\n private async recvBinary (typ: string, mayHasJunk: boolean = false): Promise<Uint8Array> {\n const buf = await this.recvCheck(typ, mayHasJunk)\n return decodeBuffer(buf)\n }\n\n /**\n * Check binary data.\n * @param expect - The expected buffer.\n */\n private async checkBinary (expect: Uint8Array): Promise<void> {\n const result = await this.recvBinary('SUCC')\n if (result.length !== expect.length) {\n throw new TrzszError(\n `Binary length check [${result.length}] <> [${expect.length}]`,\n null,\n true\n )\n }\n for (let i = 0; i < result.length; i++) {\n if (result[i] !== expect[i]) {\n throw new TrzszError(`Binary check [${result[i]}] <> [${expect[i]}]`, null, true)\n }\n }\n }\n\n /**\n * Send data.\n * @param data - The data.\n * @param binary - Whether to use binary mode.\n * @param escapeCodes - The escape codes.\n */\n private async sendData (\n data: Uint8Array,\n binary: boolean,\n escapeCodes: number[][]\n ): Promise<void> {\n if (!binary) {\n await this.sendBinary('DATA', data)\n return\n }\n\n const buf = escapeData(data, escapeCodes)\n this.writer(`#DATA:${buf.length}\\n`)\n this.writer(buf)\n }\n\n /**\n * Receive data.\n * @param binary - Whether to use binary mode.\n * @param escapeCodes - The escape codes.\n * @param timeoutInMilliseconds - The timeout in milliseconds.\n */\n private async recvData (\n binary: boolean,\n escapeCodes: number[][],\n timeoutInMilliseconds: number\n ): Promise<Uint8Array> {\n return await Promise.race<Uint8Array>([\n new Promise<Uint8Array>((_resolve, reject) =>\n setTimeout(() => {\n this.cleanTimeoutInMilliseconds = 3000\n reject(new TrzszError('Receive data timeout'))\n }, timeoutInMilliseconds)\n ),\n (async () => {\n if (!binary) {\n return await this.recvBinary('DATA')\n }\n const size = await this.recvInteger('DATA')\n const data = await this.buffer.readBinary(size)\n return unescapeData(data, escapeCodes)\n })()\n ])\n }\n\n /**\n * Send action.\n * @param confirm - Whether to confirm.\n * @param remoteIsWindows - Whether the remote is Windows.\n */\n public async sendAction (confirm: boolean, remoteIsWindows: boolean): Promise<void> {\n const action: Record<string, unknown> = {\n lang: 'js',\n confirm,\n version: trzszVersion,\n support_dir: true\n }\n if (this.isWindowsShell || remoteIsWindows) {\n action.binary = false\n action.newline = '!\\n'\n }\n if (remoteIsWindows) {\n this.remoteIsWindows = true\n this.protocolNewline = '!\\n'\n }\n await this.sendString('ACT', JSON.stringify(action))\n }\n\n /**\n * Receive action.\n */\n public async recvAction (): Promise<Record<string, unknown>> {\n const buf = await this.recvString('ACT', true)\n const action = JSON.parse(buf)\n const newline = (action as Record<string, unknown>).newline as string | undefined\n if (typeof newline === 'string' && newline.length > 0) {\n this.protocolNewline = newline\n }\n return action\n }\n\n /**\n * Send config.\n * @param args - The config arguments.\n * @param escapeChars - The escape characters.\n * @param tmuxMode - The tmux mode.\n * @param tmuxPaneWidth - The tmux pane width.\n */\n public async sendConfig (\n args: Record<string, unknown>,\n escapeChars: string[][],\n tmuxMode: number,\n tmuxPaneWidth: number\n ): Promise<void> {\n const config: Record<string, unknown> = { lang: 'js' }\n if ((args).quiet === true) {\n config.quiet = true\n }\n if ((args).binary === true) {\n config.binary = true\n config.escape_chars = escapeChars\n }\n if ((args).directory === true) {\n config.directory = true\n }\n if (typeof (args).bufsize === 'number') {\n config.bufsize = (args).bufsize\n }\n if (typeof (args).timeout === 'number') {\n config.timeout = (args).timeout\n }\n if ((args).overwrite === true) {\n config.overwrite = true\n }\n if (tmuxMode === TmuxMode.TmuxNormalMode) {\n config.tmux_output_junk = true\n }\n if (tmuxPaneWidth > 0) {\n config.tmux_pane_width = tmuxPaneWidth\n }\n let jsonStr = JSON.stringify(config)\n jsonStr = jsonStr.replace(/[\\u007F-\\uFFFF]/g, function (chr) {\n return '\\\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4)\n })\n this.transferConfig = config\n await this.sendString('CFG', jsonStr)\n }\n\n /**\n * Receive config.\n */\n public async recvConfig (): Promise<Record<string, unknown>> {\n const buf = await this.recvString('CFG', true)\n this.transferConfig = JSON.parse(buf)\n this.tmuxOutputJunk = this.transferConfig.tmux_output_junk === true\n return this.transferConfig\n }\n\n /**\n * Send client exit.\n * @param msg - The message.\n */\n public async clientExit (msg: string): Promise<void> {\n await this.sendString('EXIT', msg)\n }\n\n /**\n * Receive exit.\n */\n public async recvExit (): Promise<string> {\n return await this.recvString('EXIT')\n }\n\n /**\n * Delete created files.\n */\n private async deleteCreatedFiles (): Promise<string[]> {\n const deletedFiles: string[] = []\n for (const file of this.createdFiles) {\n const path = await file.deleteFile()\n if (typeof path === 'string' && path.length > 0) {\n deletedFiles.push(path)\n }\n }\n return deletedFiles\n }\n\n /**\n * Handle client error.\n * @param err - The error.\n */\n public async clientError (err: Error): Promise<void> {\n await this.cleanInput(this.cleanTimeoutInMilliseconds)\n\n const errMsg = TrzszError.getErrorMessage(err)\n let trace = true\n if (err instanceof TrzszError) {\n trace = err.isTraceBack()\n if (err.isRemoteExit()) {\n return\n }\n if (err.isRemoteFail()) {\n if (trace) {\n console.log(errMsg)\n }\n return\n }\n }\n\n await this.sendString(trace ? 'FAIL' : 'fail', errMsg)\n if (trace) {\n console.log(errMsg)\n }\n }\n\n /**\n * Handle server error.\n * @param err - The error.\n */\n public async serverError (err: Error): Promise<void> {\n await this.cleanInput(this.cleanTimeoutInMilliseconds)\n\n const errMsg = TrzszError.getErrorMessage(err)\n let trace = true\n if (err instanceof TrzszError) {\n if (err.isStopAndDelete()) {\n const deletedFiles = await this.deleteCreatedFiles()\n if (deletedFiles.length > 0) {\n await this.serverExit([err.message + ':'].concat(deletedFiles).join('\\r\\n- '))\n return\n }\n }\n trace = err.isTraceBack()\n if (err.isRemoteExit() || err.isRemoteFail()) {\n await this.serverExit(errMsg)\n return\n }\n }\n\n await this.sendString(trace ? 'FAIL' : 'fail', errMsg)\n await this.serverExit(errMsg)\n }\n\n /**\n * Server exit - to be implemented by subclass or user.\n * @param msg - The message.\n */\n public async serverExit (_msg: string): Promise<void> {\n // Base implementation does nothing\n // Subclasses or users should override this\n }\n\n /**\n * Send file number.\n * @param num - The number of files.\n * @param progressCallback - The progress callback.\n */\n private async sendFileNum (num: number, progressCallback: ProgressCallback | null): Promise<void> {\n await this.sendInteger('NUM', num)\n await this.checkInteger(num)\n if (progressCallback != null) {\n progressCallback.onNum(num)\n }\n }\n\n /**\n * Send file name.\n * @param file - The file reader.\n * @param directory - Whether it's a directory.\n * @param progressCallback - The progress callback.\n */\n private async sendFileName (\n file: TrzszFileReader,\n directory: boolean,\n progressCallback: ProgressCallback | null\n ): Promise<string> {\n const relPath = file.getRelPath()\n const fileName = relPath[relPath.length - 1]\n if (directory) {\n const jsonName = {\n path_id: file.getPathId(),\n path_name: relPath,\n is_dir: file.isDir()\n }\n await this.sendString('NAME', JSON.stringify(jsonName))\n } else {\n await this.sendString('NAME', fileName)\n }\n const remoteName = await this.recvString('SUCC')\n if (progressCallback != null) {\n progressCallback.onName(fileName)\n }\n return remoteName\n }\n\n /**\n * Send file size.\n * @param size - The file size.\n * @param progressCallback - The progress callback.\n */\n private async sendFileSize (\n size: number,\n progressCallback: ProgressCallback | null\n ): Promise<void> {\n await this.sendInteger('SIZE', size)\n await this.checkInteger(size)\n if (progressCallback != null) {\n progressCallback.onSize(size)\n }\n }\n\n /**\n * Send file data.\n * @param file - The file reader.\n * @param size - The file size.\n * @param binary - Whether to use binary mode.\n * @param escapeCodes - The escape codes.\n * @param maxBufSize - The maximum buffer size.\n * @param progressCallback - The progress callback.\n */\n private async sendFileData (\n file: TrzszFileReader,\n size: number,\n binary: boolean,\n escapeCodes: number[][],\n maxBufSize: number,\n progressCallback: ProgressCallback | null\n ): Promise<Uint8Array> {\n let step = 0\n if (progressCallback != null) {\n progressCallback.onStep(step)\n }\n let bufSize = 1024\n let buffer = new ArrayBuffer(bufSize)\n const md5 = new Md5()\n while (step < size) {\n const beginTime = Date.now()\n const data = await file.readFile(buffer)\n await this.sendData(data, binary, escapeCodes)\n md5.appendByteArray(data)\n await this.checkInteger(data.length)\n step += data.length\n if (progressCallback != null) {\n progressCallback.onStep(step)\n }\n const chunkTime = Date.now() - beginTime\n if (data.length === bufSize && chunkTime < 500 && bufSize < maxBufSize) {\n bufSize = Math.min(bufSize * 2, maxBufSize)\n buffer = new ArrayBuffer(bufSize)\n } else if (chunkTime >= 2000 && bufSize > 1024) {\n bufSize = 1024\n buffer = new ArrayBuffer(bufSize)\n }\n if (chunkTime > this.maxChunkTimeInMilliseconds) {\n this.maxChunkTimeInMilliseconds = chunkTime\n }\n }\n return new Uint8Array((md5.end(true) as Int32Array).buffer)\n }\n\n /**\n * Send file MD5.\n * @param digest - The MD5 digest.\n * @param progressCallback - The progress callback.\n */\n private async sendFileMD5 (\n digest: Uint8Array,\n progressCallback: ProgressCallback | null\n ): Promise<void> {\n await this.sendBinary('MD5', digest)\n await this.checkBinary(digest)\n if (progressCallback != null) {\n progressCallback.onDone()\n }\n }\n\n /**\n * Send files.\n * @param files - The file readers.\n * @param progressCallback - The progress callback.\n */\n public async sendFiles (\n files: TrzszFileReader[],\n progressCallback: ProgressCallback | null\n ): Promise<string[]> {\n this.openedFiles.push(...files)\n\n const binary = this.transferConfig.binary === true\n const directory = this.transferConfig.directory === true\n const bufsizeVal = this.transferConfig.bufsize as number | undefined\n const maxBufSize = typeof bufsizeVal === 'number' ? bufsizeVal : 10 * 1024 * 1024\n const escapeCodes = Array.isArray(this.transferConfig.escape_chars)\n ? escapeCharsToCodes(this.transferConfig.escape_chars as string[][])\n : []\n\n await this.sendFileNum(files.length, progressCallback)\n\n const remoteNames: string[] = []\n for (const file of files) {\n const remoteName = await this.sendFileName(file, directory, progressCallback)\n\n if (!remoteNames.includes(remoteName)) {\n remoteNames.push(remoteName)\n }\n\n if (file.isDir()) {\n continue\n }\n\n const size = file.getSize()\n await this.sendFileSize(size, progressCallback)\n\n const digest = await this.sendFileData(file, size, binary, escapeCodes, maxBufSize, progressCallback)\n file.closeFile()\n\n await this.sendFileMD5(digest, progressCallback)\n }\n\n return remoteNames\n }\n\n /**\n * Receive file number.\n * @param progressCallback - The progress callback.\n */\n private async recvFileNum (progressCallback: ProgressCallback | null): Promise<number> {\n const num = await this.recvInteger('NUM')\n await this.sendInteger('SUCC', num)\n if (progressCallback != null) {\n progressCallback.onNum(num)\n }\n return num\n }\n\n /**\n * Receive file name.\n * @param saveParam - The save parameter.\n * @param openSaveFile - The open save file function.\n * @param directory - Whether it's a directory.\n * @param overwrite - Whether to overwrite.\n * @param progressCallback - The progress callback.\n */\n private async recvFileName (\n saveParam: unknown,\n openSaveFile: OpenSaveFile,\n directory: boolean,\n overwrite: boolean,\n progressCallback: ProgressCallback | null\n ): Promise<TrzszFileWriter> {\n const fileName = await this.recvString('NAME')\n const file = await openSaveFile(saveParam, fileName, directory, overwrite)\n this.createdFiles.push(file)\n await this.sendString('SUCC', file.getLocalName())\n if (progressCallback != null) {\n progressCallback.onName(file.getFileName())\n }\n return file\n }\n\n /**\n * Receive file size.\n * @param progressCallback - The progress callback.\n */\n private async recvFileSize (progressCallback: ProgressCallback | null): Promise<number> {\n const fileSize = await this.recvInteger('SIZE')\n await this.sendInteger('SUCC', fileSize)\n if (progressCallback != null) {\n progressCallback.onSize(fileSize)\n }\n return fileSize\n }\n\n /**\n * Receive file data.\n * @param file - The file writer.\n * @param size - The file size.\n * @param binary - Whether to use binary mode.\n * @param escapeCodes - The escape codes.\n * @param timeoutInMilliseconds - The timeout in milliseconds.\n * @param progressCallback - The progress callback.\n */\n private async recvFileData (\n file: TrzszFileWriter,\n size: number,\n binary: boolean,\n escapeCodes: number[][],\n timeoutInMilliseconds: number,\n progressCallback: ProgressCallback | null\n ): Promise<Uint8Array> {\n let step = 0\n if (progressCallback != null) {\n progressCallback.onStep(step)\n }\n const md5 = new Md5()\n while (step < size) {\n const beginTime = Date.now()\n const data = await this.recvData(binary, escapeCodes, timeoutInMilliseconds)\n await file.writeFile(data)\n step += data.length\n if (progressCallback != null) {\n progressCallback.onStep(step)\n }\n await this.sendInteger('SUCC', data.length)\n md5.appendByteArray(data)\n const chunkTime = Date.now() - beginTime\n if (chunkTime > this.maxChunkTimeInMilliseconds) {\n this.maxChunkTimeInMilliseconds = chunkTime\n }\n }\n return new Uint8Array((md5.end(true) as Int32Array).buffer)\n }\n\n /**\n * Receive file MD5.\n * @param digest - The MD5 digest.\n * @param progressCallback - The progress callback.\n */\n private async recvFileMD5 (\n digest: Uint8Array,\n progressCallback: ProgressCallback | null\n ): Promise<void> {\n const expectDigest = await this.recvBinary('MD5')\n if (digest.length !== expectDigest.length) {\n throw new TrzszError('Check MD5 failed')\n }\n for (let j = 0; j < digest.length; j++) {\n if (digest[j] !== expectDigest[j]) {\n throw new TrzszError('Check MD5 failed')\n }\n }\n await this.sendBinary('SUCC', digest)\n if (progressCallback != null) {\n progressCallback.onDone()\n }\n }\n\n /**\n * Receive files.\n * @param saveParam - The save parameter.\n * @param openSaveFile - The open save file function.\n * @param progressCallback - The progress callback.\n */\n public async recvFiles (\n saveParam: unknown,\n openSaveFile: OpenSaveFile,\n progressCallback: ProgressCallback | null\n ): Promise<string[]> {\n const binary = this.transferConfig.binary === true\n const directory = this.transferConfig.directory === true\n const overwrite = this.transferConfig.overwrite === true\n const timeoutVal = this.transferConfig.timeout as number | undefined\n const timeoutInMilliseconds = typeof timeoutVal === 'number' ? timeoutVal * 1000 : 100000\n const escapeCodes = Array.isArray(this.transferConfig.escape_chars)\n ? escapeCharsToCodes(this.transferConfig.escape_chars as string[][])\n : []\n\n const num = await this.recvFileNum(progressCallback)\n\n const localNames: string[] = []\n for (let i = 0; i < num; i++) {\n const file = await this.recvFileName(\n saveParam,\n openSaveFile,\n directory,\n overwrite,\n progressCallback\n )\n\n if (!localNames.includes(file.getLocalName())) {\n localNames.push(file.getLocalName())\n }\n\n if (file.isDir()) {\n continue\n }\n\n this.openedFiles.push(file)\n\n const size = await this.recvFileSize(progressCallback)\n\n const digest = await this.recvFileData(\n file,\n size,\n binary,\n escapeCodes,\n timeoutInMilliseconds,\n progressCallback\n )\n file.closeFile()\n\n await this.recvFileMD5(digest, progressCallback)\n }\n\n return localNames\n }\n}\n"],"names":["TrzszBuffer","TrzszError","line","idx","stripTmuxStatusLine","encodeBuffer","uint8ToStr","decodeBuffer","escapeData","unescapeData","trzszVersion","TmuxMode","buffer","Md5","escapeCharsToCodes"],"mappings":"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"}