piclaw 0.0.19 → 0.0.21

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.
Files changed (270) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/defult-D5RLDUrI.js +1 -0
  3. package/.output/public/assets/{dist-CMBqBOCp.js → dist-BH_oa-kv.js} +1 -1
  4. package/.output/public/assets/index-7JvURuHy.js +204 -0
  5. package/.output/public/assets/index-K43slwjJ.css +1 -0
  6. package/.output/public/index.html +11 -2
  7. package/.output/server/_...path_.get.mjs +16 -0
  8. package/.output/server/_chunks/app.mjs +261 -181
  9. package/.output/server/_chunks/browser.mjs +4 -1
  10. package/.output/server/_chunks/config.mjs +4 -0
  11. package/.output/server/_chunks/db.mjs +32 -28
  12. package/.output/server/_chunks/device-bus.mjs +123 -0
  13. package/.output/server/_chunks/dummy.mjs +1 -1
  14. package/.output/server/_chunks/logger.mjs +23 -0
  15. package/.output/server/_chunks/login.mjs +1 -1
  16. package/.output/server/_chunks/notes.mjs +1 -3
  17. package/.output/server/_chunks/renderer-template.mjs +1 -1
  18. package/.output/server/_chunks/sandbox.mjs +217 -0
  19. package/.output/server/_chunks/server.mjs +2302 -122
  20. package/.output/server/_chunks/terminal.mjs +63 -8
  21. package/.output/server/_chunks/uploads.mjs +60 -0
  22. package/.output/server/_chunks/virtual.mjs +192 -54
  23. package/.output/server/_id_.delete.mjs +5 -2
  24. package/.output/server/_id_.patch.mjs +2 -0
  25. package/.output/server/_id_2.delete.mjs +8 -0
  26. package/.output/server/_jid_.delete.mjs +5 -2
  27. package/.output/server/_jid_.patch.mjs +37 -4
  28. package/.output/server/_jid_2.delete.mjs +5 -2
  29. package/.output/server/_libs/@acemir/cssom+[...].mjs +2269 -1137
  30. package/.output/server/_libs/@google/genai.mjs +337 -273
  31. package/.output/server/_libs/@mariozechner/pi-agent-core+[...].mjs +381 -2073
  32. package/.output/server/_libs/@mariozechner/pi-coding-agent+[...].mjs +231 -131
  33. package/.output/server/_libs/_.mjs +3 -2
  34. package/.output/server/_libs/_10.mjs +2 -4
  35. package/.output/server/_libs/_11.mjs +2 -4
  36. package/.output/server/_libs/_12.mjs +2 -3
  37. package/.output/server/_libs/_13.mjs +2 -3
  38. package/.output/server/_libs/_14.mjs +2 -4
  39. package/.output/server/_libs/_15.mjs +2 -4
  40. package/.output/server/_libs/_16.mjs +2 -3
  41. package/.output/server/_libs/_17.mjs +2 -4
  42. package/.output/server/_libs/_18.mjs +2 -2
  43. package/.output/server/_libs/_19.mjs +2 -2
  44. package/.output/server/_libs/_2.mjs +3 -3
  45. package/.output/server/_libs/_20.mjs +2 -2
  46. package/.output/server/_libs/_21.mjs +2 -2
  47. package/.output/server/_libs/_22.mjs +2 -2
  48. package/.output/server/_libs/_23.mjs +2 -2
  49. package/.output/server/_libs/_24.mjs +2 -2
  50. package/.output/server/_libs/_25.mjs +2 -2
  51. package/.output/server/_libs/_26.mjs +2 -2
  52. package/.output/server/_libs/_27.mjs +2 -2
  53. package/.output/server/_libs/_28.mjs +2 -2
  54. package/.output/server/_libs/_29.mjs +2 -2
  55. package/.output/server/_libs/_3.mjs +3 -3
  56. package/.output/server/_libs/_30.mjs +2 -2
  57. package/.output/server/_libs/_31.mjs +2 -2
  58. package/.output/server/_libs/_32.mjs +2 -2
  59. package/.output/server/_libs/_33.mjs +2 -2
  60. package/.output/server/_libs/_34.mjs +2 -2
  61. package/.output/server/_libs/_35.mjs +2 -2
  62. package/.output/server/_libs/_36.mjs +2 -2
  63. package/.output/server/_libs/_37.mjs +2 -2
  64. package/.output/server/_libs/_38.mjs +2 -2
  65. package/.output/server/_libs/_39.mjs +2 -2
  66. package/.output/server/_libs/_4.mjs +4 -3
  67. package/.output/server/_libs/_40.mjs +2 -2
  68. package/.output/server/_libs/_41.mjs +2 -2
  69. package/.output/server/_libs/_42.mjs +2 -2
  70. package/.output/server/_libs/_43.mjs +2 -2
  71. package/.output/server/_libs/_44.mjs +2 -2
  72. package/.output/server/_libs/_45.mjs +2 -2
  73. package/.output/server/_libs/_46.mjs +2 -2
  74. package/.output/server/_libs/_47.mjs +2 -2
  75. package/.output/server/_libs/_48.mjs +2 -2
  76. package/.output/server/_libs/_49.mjs +2 -2
  77. package/.output/server/_libs/_5.mjs +2 -3
  78. package/.output/server/_libs/_50.mjs +2 -2
  79. package/.output/server/_libs/_51.mjs +2 -2
  80. package/.output/server/_libs/_52.mjs +2 -2
  81. package/.output/server/_libs/_53.mjs +2 -2
  82. package/.output/server/_libs/_54.mjs +2 -2
  83. package/.output/server/_libs/_55.mjs +2 -2
  84. package/.output/server/_libs/_56.mjs +2 -2
  85. package/.output/server/_libs/_57.mjs +2 -2
  86. package/.output/server/_libs/_58.mjs +2 -2
  87. package/.output/server/_libs/_59.mjs +2 -2
  88. package/.output/server/_libs/_6.mjs +2 -3
  89. package/.output/server/_libs/_60.mjs +2 -2
  90. package/.output/server/_libs/_61.mjs +2 -2
  91. package/.output/server/_libs/_62.mjs +2 -2
  92. package/.output/server/_libs/_63.mjs +2 -2
  93. package/.output/server/_libs/_64.mjs +2 -2
  94. package/.output/server/_libs/_65.mjs +2 -2
  95. package/.output/server/_libs/_66.mjs +2 -2
  96. package/.output/server/_libs/_67.mjs +2 -2
  97. package/.output/server/_libs/_68.mjs +2 -2
  98. package/.output/server/_libs/_69.mjs +2 -2
  99. package/.output/server/_libs/_7.mjs +2 -5
  100. package/.output/server/_libs/_70.mjs +2 -2
  101. package/.output/server/_libs/_71.mjs +2 -2
  102. package/.output/server/_libs/_72.mjs +2 -2
  103. package/.output/server/_libs/_73.mjs +2 -2
  104. package/.output/server/_libs/_74.mjs +2 -2
  105. package/.output/server/_libs/_75.mjs +2 -2
  106. package/.output/server/_libs/_76.mjs +2 -2
  107. package/.output/server/_libs/_77.mjs +2 -2
  108. package/.output/server/_libs/_78.mjs +2 -2
  109. package/.output/server/_libs/_79.mjs +2 -2
  110. package/.output/server/_libs/_8.mjs +2 -3
  111. package/.output/server/_libs/_80.mjs +2 -2
  112. package/.output/server/_libs/_81.mjs +2 -2
  113. package/.output/server/_libs/_82.mjs +2 -2
  114. package/.output/server/_libs/_83.mjs +2 -2
  115. package/.output/server/_libs/_84.mjs +2 -2
  116. package/.output/server/_libs/_85.mjs +2 -2
  117. package/.output/server/_libs/_86.mjs +2 -2
  118. package/.output/server/_libs/_87.mjs +2 -2
  119. package/.output/server/_libs/_88.mjs +2 -2
  120. package/.output/server/_libs/_89.mjs +2 -2
  121. package/.output/server/_libs/_9.mjs +2 -4
  122. package/.output/server/_libs/_90.mjs +5 -2
  123. package/.output/server/_libs/_91.mjs +3 -2
  124. package/.output/server/_libs/_92.mjs +2 -2
  125. package/.output/server/_libs/_93.mjs +2 -2
  126. package/.output/server/_libs/_94.mjs +2 -2
  127. package/.output/server/_libs/agent-base.mjs +1 -1
  128. package/.output/server/_libs/cheerio+[...].mjs +1 -1
  129. package/.output/server/_libs/data-uri-to-buffer.mjs +2 -67
  130. package/.output/server/_libs/data-urls+[...].mjs +1 -1
  131. package/.output/server/_libs/diff.mjs +1 -1
  132. package/.output/server/_libs/exodus__bytes.mjs +99 -81
  133. package/.output/server/_libs/fetch-blob+node-domexception.mjs +1 -1
  134. package/.output/server/_libs/h3+rou3+srvx.mjs +34 -4
  135. package/.output/server/_libs/html-encoding-sniffer.mjs +1 -1
  136. package/.output/server/_libs/https-proxy-agent.mjs +2 -2
  137. package/.output/server/_libs/jsdom.mjs +1 -1
  138. package/.output/server/_libs/just-bash+[...].mjs +4676 -3916
  139. package/.output/server/_libs/mariozechner__jiti.mjs +1 -1
  140. package/.output/server/_libs/mariozechner__pi-ai.mjs +1472 -0
  141. package/.output/server/_libs/md4x.mjs +1 -1
  142. package/.output/server/_libs/mime.mjs +838 -1
  143. package/.output/server/_libs/node-fetch.mjs +4 -4
  144. package/.output/server/_libs/node-liblzma.mjs +1 -1
  145. package/.output/server/_libs/silvia-odwyer__photon-node.mjs +1 -1
  146. package/.output/server/_routes/api/auth/approve.mjs +2 -0
  147. package/.output/server/_routes/api/auth/revoke.mjs +2 -0
  148. package/.output/server/_routes/api/auth/status.mjs +25 -6
  149. package/.output/server/_routes/api/browser2.mjs +1 -1
  150. package/.output/server/_routes/api/config2.mjs +2 -0
  151. package/.output/server/_routes/api/device_events.mjs +36 -0
  152. package/.output/server/_routes/api/files/groups.mjs +1 -2
  153. package/.output/server/_routes/api/files/raw.mjs +1 -1
  154. package/.output/server/_routes/api/groups.mjs +5 -3
  155. package/.output/server/_routes/api/groups2.mjs +18 -6
  156. package/.output/server/_routes/api/health.mjs +1 -2
  157. package/.output/server/_routes/api/messages.mjs +7 -1
  158. package/.output/server/_routes/api/notes/delete.mjs +4 -1
  159. package/.output/server/_routes/api/notes/write.mjs +2 -0
  160. package/.output/server/_routes/api/ntfy/setup.mjs +8 -0
  161. package/.output/server/_routes/api/pi/apikey.mjs +3 -2
  162. package/.output/server/_routes/api/pi/apikey_providers.mjs +1 -2
  163. package/.output/server/_routes/api/pi/commands.mjs +13 -3
  164. package/.output/server/_routes/api/pi/login/events.mjs +0 -1
  165. package/.output/server/_routes/api/pi/login/respond.mjs +2 -1
  166. package/.output/server/_routes/api/pi/login.mjs +1 -2
  167. package/.output/server/_routes/api/pi/logout.mjs +2 -1
  168. package/.output/server/_routes/api/pi/models.mjs +1 -2
  169. package/.output/server/_routes/api/pi/models_config2.mjs +2 -0
  170. package/.output/server/_routes/api/pi/settings2.mjs +2 -0
  171. package/.output/server/_routes/api/pi/status.mjs +1 -2
  172. package/.output/server/_routes/api/proxy.mjs +19 -1
  173. package/.output/server/_routes/api/sandbox.mjs +26 -0
  174. package/.output/server/_routes/api/sandbox2.mjs +17 -0
  175. package/.output/server/_routes/api/send.mjs +26 -18
  176. package/.output/server/_routes/api/status.mjs +1 -3
  177. package/.output/server/_routes/api/stop.mjs +11 -0
  178. package/.output/server/_routes/api/store/plugins.mjs +75 -0
  179. package/.output/server/_routes/api/store/skills.mjs +11 -0
  180. package/.output/server/_routes/api/tasks2.mjs +3 -2
  181. package/.output/server/_routes/api/telegram/setup.mjs +5 -2
  182. package/.output/server/_routes/api/telegram/status.mjs +1 -2
  183. package/.output/server/_routes/api/terminal2.mjs +2 -1
  184. package/.output/server/_routes/api/tunnel/setup.mjs +4 -2
  185. package/.output/server/_runtime.mjs +1 -2
  186. package/.output/server/_utils.mjs +10 -2
  187. package/.output/server/index.mjs +1 -1
  188. package/.output/server/node_modules/amdefine/amdefine.js +301 -0
  189. package/.output/server/node_modules/amdefine/package.json +16 -0
  190. package/.output/server/node_modules/compressjs/lib/BWT.js +420 -0
  191. package/.output/server/node_modules/compressjs/lib/BWTC.js +234 -0
  192. package/.output/server/node_modules/compressjs/lib/BitStream.js +108 -0
  193. package/.output/server/node_modules/compressjs/lib/Bzip2.js +936 -0
  194. package/.output/server/node_modules/compressjs/lib/CRC32.js +105 -0
  195. package/.output/server/node_modules/compressjs/lib/Context1Model.js +56 -0
  196. package/.output/server/node_modules/compressjs/lib/DefSumModel.js +152 -0
  197. package/.output/server/node_modules/compressjs/lib/DeflateDistanceModel.js +55 -0
  198. package/.output/server/node_modules/compressjs/lib/Dmc.js +197 -0
  199. package/.output/server/node_modules/compressjs/lib/DummyRangeCoder.js +81 -0
  200. package/.output/server/node_modules/compressjs/lib/FenwickModel.js +194 -0
  201. package/.output/server/node_modules/compressjs/lib/Huffman.js +514 -0
  202. package/.output/server/node_modules/compressjs/lib/HuffmanAllocator.js +227 -0
  203. package/.output/server/node_modules/compressjs/lib/LogDistanceModel.js +46 -0
  204. package/.output/server/node_modules/compressjs/lib/Lzjb.js +300 -0
  205. package/.output/server/node_modules/compressjs/lib/LzjbR.js +241 -0
  206. package/.output/server/node_modules/compressjs/lib/Lzp3.js +273 -0
  207. package/.output/server/node_modules/compressjs/lib/MTFModel.js +208 -0
  208. package/.output/server/node_modules/compressjs/lib/NoModel.js +46 -0
  209. package/.output/server/node_modules/compressjs/lib/PPM.js +343 -0
  210. package/.output/server/node_modules/compressjs/lib/RangeCoder.js +238 -0
  211. package/.output/server/node_modules/compressjs/lib/Simple.js +111 -0
  212. package/.output/server/node_modules/compressjs/lib/Stream.js +53 -0
  213. package/.output/server/node_modules/compressjs/lib/Util.js +324 -0
  214. package/.output/server/node_modules/compressjs/lib/freeze.js +14 -0
  215. package/.output/server/node_modules/compressjs/main.js +29 -0
  216. package/.output/server/node_modules/compressjs/package.json +35 -0
  217. package/.output/server/package.json +2 -1
  218. package/README.md +10 -1
  219. package/lib/index.d.mts +1 -0
  220. package/lib/index.mjs +1 -0
  221. package/lib/piclaw.mjs +100 -0
  222. package/lib/utils.mjs +96 -0
  223. package/package.json +16 -11
  224. package/.output/public/assets/defult-CMO6TZ5a.js +0 -1
  225. package/.output/public/assets/index-jdnbJw-M.js +0 -204
  226. package/.output/public/assets/index-ooXrRwgl.css +0 -1
  227. package/.output/server/_chunks/commands.mjs +0 -282
  228. package/.output/server/_chunks/pi.mjs +0 -202
  229. package/.output/server/_chunks/session.mjs +0 -1114
  230. package/.output/server/_libs/@aws-crypto/crc32+[...].mjs +0 -299
  231. package/.output/server/_libs/@aws-sdk/client-bedrock-runtime+[...].mjs +0 -17828
  232. package/.output/server/_libs/@aws-sdk/credential-provider-http+[...].mjs +0 -122
  233. package/.output/server/_libs/@aws-sdk/credential-provider-ini+[...].mjs +0 -417
  234. package/.output/server/_libs/@aws-sdk/credential-provider-process+[...].mjs +0 -54
  235. package/.output/server/_libs/@aws-sdk/credential-provider-sso+[...].mjs +0 -1151
  236. package/.output/server/_libs/@aws-sdk/credential-provider-web-identity+[...].mjs +0 -50
  237. package/.output/server/_libs/@smithy/credential-provider-imds+[...].mjs +0 -369
  238. package/.output/server/_libs/@tootallnate/quickjs-emscripten+[...].mjs +0 -3011
  239. package/.output/server/_libs/_100.mjs +0 -2
  240. package/.output/server/_libs/_101.mjs +0 -2
  241. package/.output/server/_libs/_102.mjs +0 -5
  242. package/.output/server/_libs/_103.mjs +0 -3
  243. package/.output/server/_libs/_104.mjs +0 -2
  244. package/.output/server/_libs/_105.mjs +0 -3
  245. package/.output/server/_libs/_106.mjs +0 -2
  246. package/.output/server/_libs/_107.mjs +0 -2
  247. package/.output/server/_libs/_95.mjs +0 -2
  248. package/.output/server/_libs/_96.mjs +0 -2
  249. package/.output/server/_libs/_97.mjs +0 -2
  250. package/.output/server/_libs/_98.mjs +0 -2
  251. package/.output/server/_libs/_99.mjs +0 -2
  252. package/.output/server/_libs/amdefine.mjs +0 -188
  253. package/.output/server/_libs/ast-types.mjs +0 -2270
  254. package/.output/server/_libs/aws-sdk__nested-clients.mjs +0 -3141
  255. package/.output/server/_libs/basic-ftp.mjs +0 -1906
  256. package/.output/server/_libs/compressjs.mjs +0 -50
  257. package/.output/server/_libs/degenerator+[...].mjs +0 -9964
  258. package/.output/server/_libs/get-uri.mjs +0 -413
  259. package/.output/server/_libs/http-proxy-agent.mjs +0 -123
  260. package/.output/server/_libs/ip-address.mjs +0 -1423
  261. package/.output/server/_libs/lru-cache.mjs +0 -732
  262. package/.output/server/_libs/netmask.mjs +0 -139
  263. package/.output/server/_libs/pac-proxy-agent+[...].mjs +0 -3104
  264. package/.output/server/_libs/proxy-agent+proxy-from-env.mjs +0 -204
  265. package/.output/server/_libs/smithy__core.mjs +0 -192
  266. package/.output/server/node_modules/tslib/modules/index.js +0 -70
  267. package/.output/server/node_modules/tslib/modules/package.json +0 -3
  268. package/.output/server/node_modules/tslib/package.json +0 -47
  269. package/.output/server/node_modules/tslib/tslib.js +0 -484
  270. package/bin/piclaw.mjs +0 -195
@@ -1,1906 +0,0 @@
1
- import { a as __require, t as __commonJSMin } from "../_runtime.mjs";
2
- var require_parseControlResponse = /* @__PURE__ */ __commonJSMin(((exports) => {
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.parseControlResponse = parseControlResponse;
5
- exports.isSingleLine = isSingleLine;
6
- exports.isMultiline = isMultiline;
7
- exports.positiveCompletion = positiveCompletion;
8
- exports.positiveIntermediate = positiveIntermediate;
9
- var LF = "\n";
10
- /**
11
- * Parse an FTP control response as a collection of messages. A message is a complete
12
- * single- or multiline response. A response can also contain multiple multiline responses
13
- * that will each be represented by a message. A response can also be incomplete
14
- * and be completed on the next incoming data chunk for which case this function also
15
- * describes a `rest`. This function converts all CRLF to LF.
16
- */
17
- function parseControlResponse(text) {
18
- const lines = text.split(/\r?\n/).filter(isNotBlank);
19
- const messages = [];
20
- let startAt = 0;
21
- let tokenRegex;
22
- for (let i = 0; i < lines.length; i++) {
23
- const line = lines[i];
24
- if (!tokenRegex) {
25
- if (isMultiline(line)) {
26
- const token = line.substr(0, 3);
27
- tokenRegex = new RegExp(`^${token}(?:$| )`);
28
- startAt = i;
29
- } else if (isSingleLine(line)) messages.push(line);
30
- } else if (tokenRegex.test(line)) {
31
- tokenRegex = void 0;
32
- messages.push(lines.slice(startAt, i + 1).join(LF));
33
- }
34
- }
35
- return {
36
- messages,
37
- rest: tokenRegex ? lines.slice(startAt).join(LF) + LF : ""
38
- };
39
- }
40
- function isSingleLine(line) {
41
- return /^\d\d\d(?:$| )/.test(line);
42
- }
43
- function isMultiline(line) {
44
- return /^\d\d\d-/.test(line);
45
- }
46
- /**
47
- * Return true if an FTP return code describes a positive completion.
48
- */
49
- function positiveCompletion(code) {
50
- return code >= 200 && code < 300;
51
- }
52
- /**
53
- * Return true if an FTP return code describes a positive intermediate response.
54
- */
55
- function positiveIntermediate(code) {
56
- return code >= 300 && code < 400;
57
- }
58
- function isNotBlank(str) {
59
- return str.trim() !== "";
60
- }
61
- }));
62
- var require_FtpContext = /* @__PURE__ */ __commonJSMin(((exports) => {
63
- Object.defineProperty(exports, "__esModule", { value: true });
64
- exports.FTPContext = exports.FTPError = void 0;
65
- var net_1 = __require("net");
66
- var parseControlResponse_1 = require_parseControlResponse();
67
- /**
68
- * Describes an FTP server error response including the FTP response code.
69
- */
70
- var FTPError = class extends Error {
71
- constructor(res) {
72
- super(res.message);
73
- this.name = this.constructor.name;
74
- this.code = res.code;
75
- }
76
- };
77
- exports.FTPError = FTPError;
78
- function doNothing() {
79
- /** Do nothing */
80
- }
81
- /**
82
- * FTPContext holds the control and data sockets of an FTP connection and provides a
83
- * simplified way to interact with an FTP server, handle responses, errors and timeouts.
84
- *
85
- * It doesn't implement or use any FTP commands. It's only a foundation to make writing an FTP
86
- * client as easy as possible. You won't usually instantiate this, but use `Client`.
87
- */
88
- var FTPContext = class {
89
- /**
90
- * Instantiate an FTP context.
91
- *
92
- * @param timeout - Timeout in milliseconds to apply to control and data connections. Use 0 for no timeout.
93
- * @param encoding - Encoding to use for control connection. UTF-8 by default. Use "latin1" for older servers.
94
- */
95
- constructor(timeout = 0, encoding = "utf8") {
96
- this.timeout = timeout;
97
- /** Debug-level logging of all socket communication. */
98
- this.verbose = false;
99
- /** IP version to prefer (4: IPv4, 6: IPv6, undefined: automatic). */
100
- this.ipFamily = void 0;
101
- /** Options for TLS connections. */
102
- this.tlsOptions = {};
103
- /** A multiline response might be received as multiple chunks. */
104
- this._partialResponse = "";
105
- this._encoding = encoding;
106
- this._socket = this.socket = this._newSocket();
107
- this._dataSocket = void 0;
108
- }
109
- /**
110
- * Close the context.
111
- */
112
- close() {
113
- const message = this._task ? "User closed client during task" : "User closed client";
114
- const err = new Error(message);
115
- this.closeWithError(err);
116
- }
117
- /**
118
- * Close the context with an error.
119
- */
120
- closeWithError(err) {
121
- if (this._closingError) return;
122
- this._closingError = err;
123
- this._closeControlSocket();
124
- this._closeSocket(this._dataSocket);
125
- this._passToHandler(err);
126
- this._stopTrackingTask();
127
- }
128
- /**
129
- * Returns true if this context has been closed or hasn't been connected yet. You can reopen it with `access`.
130
- */
131
- get closed() {
132
- return this.socket.remoteAddress === void 0 || this._closingError !== void 0;
133
- }
134
- /**
135
- * Reset this contex and all of its state.
136
- */
137
- reset() {
138
- this.socket = this._newSocket();
139
- }
140
- /**
141
- * Get the FTP control socket.
142
- */
143
- get socket() {
144
- return this._socket;
145
- }
146
- /**
147
- * Set the socket for the control connection. This will only close the current control socket
148
- * if the new one is not an upgrade to the current one.
149
- */
150
- set socket(socket) {
151
- this.dataSocket = void 0;
152
- this.tlsOptions = {};
153
- this._partialResponse = "";
154
- if (this._socket) if (socket.localPort === this._socket.localPort) this._removeSocketListeners(this.socket);
155
- else this._closeControlSocket();
156
- if (socket) {
157
- this._closingError = void 0;
158
- socket.setTimeout(0);
159
- socket.setEncoding(this._encoding);
160
- socket.setKeepAlive(true);
161
- socket.on("data", (data) => this._onControlSocketData(data));
162
- socket.on("end", () => this.closeWithError(/* @__PURE__ */ new Error("Server sent FIN packet unexpectedly, closing connection.")));
163
- socket.on("close", (hadError) => {
164
- if (!hadError) this.closeWithError(/* @__PURE__ */ new Error("Server closed connection unexpectedly."));
165
- });
166
- this._setupDefaultErrorHandlers(socket, "control socket");
167
- }
168
- this._socket = socket;
169
- }
170
- /**
171
- * Get the current FTP data connection if present.
172
- */
173
- get dataSocket() {
174
- return this._dataSocket;
175
- }
176
- /**
177
- * Set the socket for the data connection. This will automatically close the former data socket.
178
- */
179
- set dataSocket(socket) {
180
- this._closeSocket(this._dataSocket);
181
- if (socket) {
182
- socket.setTimeout(0);
183
- this._setupDefaultErrorHandlers(socket, "data socket");
184
- }
185
- this._dataSocket = socket;
186
- }
187
- /**
188
- * Get the currently used encoding.
189
- */
190
- get encoding() {
191
- return this._encoding;
192
- }
193
- /**
194
- * Set the encoding used for the control socket.
195
- *
196
- * See https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings for what encodings
197
- * are supported by Node.
198
- */
199
- set encoding(encoding) {
200
- this._encoding = encoding;
201
- if (this.socket) this.socket.setEncoding(encoding);
202
- }
203
- /**
204
- * Send an FTP command without waiting for or handling the result.
205
- */
206
- send(command) {
207
- const message = command.startsWith("PASS") ? "> PASS ###" : `> ${command}`;
208
- this.log(message);
209
- this._socket.write(command + "\r\n", this.encoding);
210
- }
211
- /**
212
- * Send an FTP command and handle the first response. Use this if you have a simple
213
- * request-response situation.
214
- */
215
- request(command) {
216
- return this.handle(command, (res, task) => {
217
- if (res instanceof Error) task.reject(res);
218
- else task.resolve(res);
219
- });
220
- }
221
- /**
222
- * Send an FTP command and handle any response until you resolve/reject. Use this if you expect multiple responses
223
- * to a request. This returns a Promise that will hold whatever the response handler passed on when resolving/rejecting its task.
224
- */
225
- handle(command, responseHandler) {
226
- if (this._task) {
227
- const err = /* @__PURE__ */ new Error("User launched a task while another one is still running. Forgot to use 'await' or '.then()'?");
228
- err.stack += `\nRunning task launched at: ${this._task.stack}`;
229
- this.closeWithError(err);
230
- }
231
- return new Promise((resolveTask, rejectTask) => {
232
- this._task = {
233
- stack: (/* @__PURE__ */ new Error()).stack || "Unknown call stack",
234
- responseHandler,
235
- resolver: {
236
- resolve: (arg) => {
237
- this._stopTrackingTask();
238
- resolveTask(arg);
239
- },
240
- reject: (err) => {
241
- this._stopTrackingTask();
242
- rejectTask(err);
243
- }
244
- }
245
- };
246
- if (this._closingError) {
247
- const err = /* @__PURE__ */ new Error(`Client is closed because ${this._closingError.message}`);
248
- err.stack += `\nClosing reason: ${this._closingError.stack}`;
249
- err.code = this._closingError.code !== void 0 ? this._closingError.code : "0";
250
- this._passToHandler(err);
251
- return;
252
- }
253
- this.socket.setTimeout(this.timeout);
254
- if (command) this.send(command);
255
- });
256
- }
257
- /**
258
- * Log message if set to be verbose.
259
- */
260
- log(message) {
261
- if (this.verbose) console.log(message);
262
- }
263
- /**
264
- * Return true if the control socket is using TLS. This does not mean that a session
265
- * has already been negotiated.
266
- */
267
- get hasTLS() {
268
- return "encrypted" in this._socket;
269
- }
270
- /**
271
- * Removes reference to current task and handler. This won't resolve or reject the task.
272
- * @protected
273
- */
274
- _stopTrackingTask() {
275
- this.socket.setTimeout(0);
276
- this._task = void 0;
277
- }
278
- /**
279
- * Handle incoming data on the control socket. The chunk is going to be of type `string`
280
- * because we let `socket` handle encoding with `setEncoding`.
281
- * @protected
282
- */
283
- _onControlSocketData(chunk) {
284
- this.log(`< ${chunk}`);
285
- const completeResponse = this._partialResponse + chunk;
286
- const parsed = (0, parseControlResponse_1.parseControlResponse)(completeResponse);
287
- this._partialResponse = parsed.rest;
288
- for (const message of parsed.messages) {
289
- const code = parseInt(message.substr(0, 3), 10);
290
- const response = {
291
- code,
292
- message
293
- };
294
- const err = code >= 400 ? new FTPError(response) : void 0;
295
- this._passToHandler(err ? err : response);
296
- }
297
- }
298
- /**
299
- * Send the current handler a response. This is usually a control socket response
300
- * or a socket event, like an error or timeout.
301
- * @protected
302
- */
303
- _passToHandler(response) {
304
- if (this._task) this._task.responseHandler(response, this._task.resolver);
305
- }
306
- /**
307
- * Setup all error handlers for a socket.
308
- * @protected
309
- */
310
- _setupDefaultErrorHandlers(socket, identifier) {
311
- socket.once("error", (error) => {
312
- error.message += ` (${identifier})`;
313
- this.closeWithError(error);
314
- });
315
- socket.once("close", (hadError) => {
316
- if (hadError) this.closeWithError(/* @__PURE__ */ new Error(`Socket closed due to transmission error (${identifier})`));
317
- });
318
- socket.once("timeout", () => {
319
- socket.destroy();
320
- this.closeWithError(/* @__PURE__ */ new Error(`Timeout (${identifier})`));
321
- });
322
- }
323
- /**
324
- * Close the control socket. Sends QUIT, then FIN, and ignores any response or error.
325
- */
326
- _closeControlSocket() {
327
- this._removeSocketListeners(this._socket);
328
- this._socket.on("error", doNothing);
329
- this.send("QUIT");
330
- this._closeSocket(this._socket);
331
- }
332
- /**
333
- * Close a socket, ignores any error.
334
- * @protected
335
- */
336
- _closeSocket(socket) {
337
- if (socket) {
338
- this._removeSocketListeners(socket);
339
- socket.on("error", doNothing);
340
- socket.destroy();
341
- }
342
- }
343
- /**
344
- * Remove all default listeners for socket.
345
- * @protected
346
- */
347
- _removeSocketListeners(socket) {
348
- socket.removeAllListeners();
349
- socket.removeAllListeners("timeout");
350
- socket.removeAllListeners("data");
351
- socket.removeAllListeners("end");
352
- socket.removeAllListeners("error");
353
- socket.removeAllListeners("close");
354
- socket.removeAllListeners("connect");
355
- }
356
- /**
357
- * Provide a new socket instance.
358
- *
359
- * Internal use only, replaced for unit tests.
360
- */
361
- _newSocket() {
362
- return new net_1.Socket();
363
- }
364
- };
365
- exports.FTPContext = FTPContext;
366
- }));
367
- var require_FileInfo = /* @__PURE__ */ __commonJSMin(((exports) => {
368
- Object.defineProperty(exports, "__esModule", { value: true });
369
- exports.FileInfo = exports.FileType = void 0;
370
- var FileType;
371
- (function(FileType) {
372
- FileType[FileType["Unknown"] = 0] = "Unknown";
373
- FileType[FileType["File"] = 1] = "File";
374
- FileType[FileType["Directory"] = 2] = "Directory";
375
- FileType[FileType["SymbolicLink"] = 3] = "SymbolicLink";
376
- })(FileType || (exports.FileType = FileType = {}));
377
- /**
378
- * Describes a file, directory or symbolic link.
379
- */
380
- var FileInfo = class {
381
- constructor(name) {
382
- this.name = name;
383
- this.type = FileType.Unknown;
384
- this.size = 0;
385
- /**
386
- * Unparsed, raw modification date as a string.
387
- *
388
- * If `modifiedAt` is undefined, the FTP server you're connected to doesn't support the more modern
389
- * MLSD command for machine-readable directory listings. The older command LIST is then used returning
390
- * results that vary a lot between servers as the format hasn't been standardized. Here, directory listings
391
- * and especially modification dates were meant to be human-readable first.
392
- *
393
- * Be careful when still trying to parse this by yourself. Parsing dates from listings using LIST is
394
- * unreliable. This library decides to offer parsed dates only when they're absolutely reliable and safe to
395
- * use e.g. for comparisons.
396
- */
397
- this.rawModifiedAt = "";
398
- /**
399
- * Parsed modification date.
400
- *
401
- * Available if the FTP server supports the MLSD command. Only MLSD guarantees dates than can be reliably
402
- * parsed with the correct timezone and a resolution down to seconds. See `rawModifiedAt` property for the unparsed
403
- * date that is always available.
404
- */
405
- this.modifiedAt = void 0;
406
- /**
407
- * Unix permissions if present. If the underlying FTP server is not running on Unix this will be undefined.
408
- * If set, you might be able to edit permissions with the FTP command `SITE CHMOD`.
409
- */
410
- this.permissions = void 0;
411
- /**
412
- * Hard link count if available.
413
- */
414
- this.hardLinkCount = void 0;
415
- /**
416
- * Link name for symbolic links if available.
417
- */
418
- this.link = void 0;
419
- /**
420
- * Unix group if available.
421
- */
422
- this.group = void 0;
423
- /**
424
- * Unix user if available.
425
- */
426
- this.user = void 0;
427
- /**
428
- * Unique ID if available.
429
- */
430
- this.uniqueID = void 0;
431
- this.name = name;
432
- }
433
- get isDirectory() {
434
- return this.type === FileType.Directory;
435
- }
436
- get isSymbolicLink() {
437
- return this.type === FileType.SymbolicLink;
438
- }
439
- get isFile() {
440
- return this.type === FileType.File;
441
- }
442
- /**
443
- * Deprecated, legacy API. Use `rawModifiedAt` instead.
444
- * @deprecated
445
- */
446
- get date() {
447
- return this.rawModifiedAt;
448
- }
449
- set date(rawModifiedAt) {
450
- this.rawModifiedAt = rawModifiedAt;
451
- }
452
- };
453
- exports.FileInfo = FileInfo;
454
- FileInfo.UnixPermission = {
455
- Read: 4,
456
- Write: 2,
457
- Execute: 1
458
- };
459
- }));
460
- var require_parseListDOS = /* @__PURE__ */ __commonJSMin(((exports) => {
461
- Object.defineProperty(exports, "__esModule", { value: true });
462
- exports.testLine = testLine;
463
- exports.parseLine = parseLine;
464
- exports.transformList = transformList;
465
- var FileInfo_1 = require_FileInfo();
466
- /**
467
- * This parser is based on the FTP client library source code in Apache Commons Net provided
468
- * under the Apache 2.0 license. It has been simplified and rewritten to better fit the Javascript language.
469
- *
470
- * https://github.com/apache/commons-net/blob/master/src/main/java/org/apache/commons/net/ftp/parser/NTFTPEntryParser.java
471
- */
472
- var RE_LINE = /* @__PURE__ */ new RegExp("(\\S+)\\s+(\\S+)\\s+(?:(<DIR>)|([0-9]+))\\s+(\\S.*)");
473
- /**
474
- * Returns true if a given line might be a DOS-style listing.
475
- *
476
- * - Example: `12-05-96 05:03PM <DIR> myDir`
477
- */
478
- function testLine(line) {
479
- return /^\d{2}/.test(line) && RE_LINE.test(line);
480
- }
481
- /**
482
- * Parse a single line of a DOS-style directory listing.
483
- */
484
- function parseLine(line) {
485
- const groups = line.match(RE_LINE);
486
- if (groups === null) return;
487
- const name = groups[5];
488
- if (name === "." || name === "..") return;
489
- const file = new FileInfo_1.FileInfo(name);
490
- if (groups[3] === "<DIR>") {
491
- file.type = FileInfo_1.FileType.Directory;
492
- file.size = 0;
493
- } else {
494
- file.type = FileInfo_1.FileType.File;
495
- file.size = parseInt(groups[4], 10);
496
- }
497
- file.rawModifiedAt = groups[1] + " " + groups[2];
498
- return file;
499
- }
500
- function transformList(files) {
501
- return files;
502
- }
503
- }));
504
- var require_parseListUnix = /* @__PURE__ */ __commonJSMin(((exports) => {
505
- Object.defineProperty(exports, "__esModule", { value: true });
506
- exports.testLine = testLine;
507
- exports.parseLine = parseLine;
508
- exports.transformList = transformList;
509
- var FileInfo_1 = require_FileInfo();
510
- /**
511
- * This parser is based on the FTP client library source code in Apache Commons Net provided
512
- * under the Apache 2.0 license. It has been simplified and rewritten to better fit the Javascript language.
513
- *
514
- * https://github.com/apache/commons-net/blob/master/src/main/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java
515
- *
516
- * Below is the regular expression used by this parser.
517
- *
518
- * Permissions:
519
- * r the file is readable
520
- * w the file is writable
521
- * x the file is executable
522
- * - the indicated permission is not granted
523
- * L mandatory locking occurs during access (the set-group-ID bit is
524
- * on and the group execution bit is off)
525
- * s the set-user-ID or set-group-ID bit is on, and the corresponding
526
- * user or group execution bit is also on
527
- * S undefined bit-state (the set-user-ID bit is on and the user
528
- * execution bit is off)
529
- * t the 1000 (octal) bit, or sticky bit, is on [see chmod(1)], and
530
- * execution is on
531
- * T the 1000 bit is turned on, and execution is off (undefined bit-
532
- * state)
533
- * e z/OS external link bit
534
- * Final letter may be appended:
535
- * + file has extended security attributes (e.g. ACL)
536
- * Note: local listings on MacOSX also use '@'
537
- * this is not allowed for here as does not appear to be shown by FTP servers
538
- * {@code @} file has extended attributes
539
- */
540
- var RE_LINE = /* @__PURE__ */ new RegExp("([bcdelfmpSs-])(((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]?)))\\+?\\s*(\\d+)\\s+(?:(\\S+(?:\\s\\S+)*?)\\s+)?(?:(\\S+(?:\\s\\S+)*)\\s+)?(\\d+(?:,\\s*\\d+)?)\\s+((?:\\d+[-/]\\d+[-/]\\d+)|(?:\\S{3}\\s+\\d{1,2})|(?:\\d{1,2}\\s+\\S{3})|(?:\\d{1,2}月\\s+\\d{1,2}日))\\s+((?:\\d+(?::\\d+)?)|(?:\\d{4}年))\\s(.*)");
541
- /**
542
- * Returns true if a given line might be a Unix-style listing.
543
- *
544
- * - Example: `-rw-r--r--+ 1 patrick staff 1057 Dec 11 14:35 test.txt`
545
- */
546
- function testLine(line) {
547
- return RE_LINE.test(line);
548
- }
549
- /**
550
- * Parse a single line of a Unix-style directory listing.
551
- */
552
- function parseLine(line) {
553
- const groups = line.match(RE_LINE);
554
- if (groups === null) return;
555
- const name = groups[21];
556
- if (name === "." || name === "..") return;
557
- const file = new FileInfo_1.FileInfo(name);
558
- file.size = parseInt(groups[18], 10);
559
- file.user = groups[16];
560
- file.group = groups[17];
561
- file.hardLinkCount = parseInt(groups[15], 10);
562
- file.rawModifiedAt = groups[19] + " " + groups[20];
563
- file.permissions = {
564
- user: parseMode(groups[4], groups[5], groups[6]),
565
- group: parseMode(groups[8], groups[9], groups[10]),
566
- world: parseMode(groups[12], groups[13], groups[14])
567
- };
568
- switch (groups[1].charAt(0)) {
569
- case "d":
570
- file.type = FileInfo_1.FileType.Directory;
571
- break;
572
- case "e":
573
- file.type = FileInfo_1.FileType.SymbolicLink;
574
- break;
575
- case "l":
576
- file.type = FileInfo_1.FileType.SymbolicLink;
577
- break;
578
- case "b":
579
- case "c":
580
- file.type = FileInfo_1.FileType.File;
581
- break;
582
- case "f":
583
- case "-":
584
- file.type = FileInfo_1.FileType.File;
585
- break;
586
- default: file.type = FileInfo_1.FileType.Unknown;
587
- }
588
- if (file.isSymbolicLink) {
589
- const end = name.indexOf(" -> ");
590
- if (end !== -1) {
591
- file.name = name.substring(0, end);
592
- file.link = name.substring(end + 4);
593
- }
594
- }
595
- return file;
596
- }
597
- function transformList(files) {
598
- return files;
599
- }
600
- function parseMode(r, w, x) {
601
- let value = 0;
602
- if (r !== "-") value += FileInfo_1.FileInfo.UnixPermission.Read;
603
- if (w !== "-") value += FileInfo_1.FileInfo.UnixPermission.Write;
604
- const execToken = x.charAt(0);
605
- if (execToken !== "-" && execToken.toUpperCase() !== execToken) value += FileInfo_1.FileInfo.UnixPermission.Execute;
606
- return value;
607
- }
608
- }));
609
- var require_parseListMLSD = /* @__PURE__ */ __commonJSMin(((exports) => {
610
- Object.defineProperty(exports, "__esModule", { value: true });
611
- exports.testLine = testLine;
612
- exports.parseLine = parseLine;
613
- exports.transformList = transformList;
614
- exports.parseMLSxDate = parseMLSxDate;
615
- var FileInfo_1 = require_FileInfo();
616
- function parseSize(value, info) {
617
- info.size = parseInt(value, 10);
618
- }
619
- /**
620
- * Parsers for MLSD facts.
621
- */
622
- var factHandlersByName = {
623
- "size": parseSize,
624
- "sizd": parseSize,
625
- "unique": (value, info) => {
626
- info.uniqueID = value;
627
- },
628
- "modify": (value, info) => {
629
- info.modifiedAt = parseMLSxDate(value);
630
- info.rawModifiedAt = info.modifiedAt.toISOString();
631
- },
632
- "type": (value, info) => {
633
- if (value.startsWith("OS.unix=slink")) {
634
- info.type = FileInfo_1.FileType.SymbolicLink;
635
- info.link = value.substr(value.indexOf(":") + 1);
636
- return 1;
637
- }
638
- switch (value) {
639
- case "file":
640
- info.type = FileInfo_1.FileType.File;
641
- break;
642
- case "dir":
643
- info.type = FileInfo_1.FileType.Directory;
644
- break;
645
- case "OS.unix=symlink":
646
- info.type = FileInfo_1.FileType.SymbolicLink;
647
- break;
648
- case "cdir":
649
- case "pdir": return 2;
650
- default: info.type = FileInfo_1.FileType.Unknown;
651
- }
652
- return 1;
653
- },
654
- "unix.mode": (value, info) => {
655
- const digits = value.substr(-3);
656
- info.permissions = {
657
- user: parseInt(digits[0], 10),
658
- group: parseInt(digits[1], 10),
659
- world: parseInt(digits[2], 10)
660
- };
661
- },
662
- "unix.ownername": (value, info) => {
663
- info.user = value;
664
- },
665
- "unix.owner": (value, info) => {
666
- if (info.user === void 0) info.user = value;
667
- },
668
- get "unix.uid"() {
669
- return this["unix.owner"];
670
- },
671
- "unix.groupname": (value, info) => {
672
- info.group = value;
673
- },
674
- "unix.group": (value, info) => {
675
- if (info.group === void 0) info.group = value;
676
- },
677
- get "unix.gid"() {
678
- return this["unix.group"];
679
- }
680
- };
681
- /**
682
- * Split a string once at the first position of a delimiter. For example
683
- * `splitStringOnce("a b c d", " ")` returns `["a", "b c d"]`.
684
- */
685
- function splitStringOnce(str, delimiter) {
686
- const pos = str.indexOf(delimiter);
687
- return [str.substr(0, pos), str.substr(pos + delimiter.length)];
688
- }
689
- /**
690
- * Returns true if a given line might be part of an MLSD listing.
691
- *
692
- * - Example 1: `size=15227;type=dir;perm=el;modify=20190419065730; test one`
693
- * - Example 2: ` file name` (leading space)
694
- */
695
- function testLine(line) {
696
- return /^\S+=\S+;/.test(line) || line.startsWith(" ");
697
- }
698
- /**
699
- * Parse single line as MLSD listing, see specification at https://tools.ietf.org/html/rfc3659#section-7.
700
- */
701
- function parseLine(line) {
702
- const [packedFacts, name] = splitStringOnce(line, " ");
703
- if (name === "" || name === "." || name === "..") return;
704
- const info = new FileInfo_1.FileInfo(name);
705
- const facts = packedFacts.split(";");
706
- for (const fact of facts) {
707
- const [factName, factValue] = splitStringOnce(fact, "=");
708
- if (!factValue) continue;
709
- const factHandler = factHandlersByName[factName.toLowerCase()];
710
- if (!factHandler) continue;
711
- if (factHandler(factValue, info) === 2) return;
712
- }
713
- return info;
714
- }
715
- function transformList(files) {
716
- const nonLinksByID = /* @__PURE__ */ new Map();
717
- for (const file of files) if (!file.isSymbolicLink && file.uniqueID !== void 0) nonLinksByID.set(file.uniqueID, file);
718
- const resolvedFiles = [];
719
- for (const file of files) {
720
- if (file.isSymbolicLink && file.uniqueID !== void 0 && file.link === void 0) {
721
- const target = nonLinksByID.get(file.uniqueID);
722
- if (target !== void 0) file.link = target.name;
723
- }
724
- if (!file.name.includes("/")) resolvedFiles.push(file);
725
- }
726
- return resolvedFiles;
727
- }
728
- /**
729
- * Parse date as specified in https://tools.ietf.org/html/rfc3659#section-2.3.
730
- *
731
- * Message contains response code and modified time in the format: YYYYMMDDHHMMSS[.sss]
732
- * For example `19991005213102` or `19980615100045.014`.
733
- */
734
- function parseMLSxDate(fact) {
735
- return new Date(Date.UTC(+fact.slice(0, 4), +fact.slice(4, 6) - 1, +fact.slice(6, 8), +fact.slice(8, 10), +fact.slice(10, 12), +fact.slice(12, 14), +fact.slice(15, 18)));
736
- }
737
- }));
738
- var require_parseList = /* @__PURE__ */ __commonJSMin(((exports) => {
739
- var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
740
- if (k2 === void 0) k2 = k;
741
- var desc = Object.getOwnPropertyDescriptor(m, k);
742
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) desc = {
743
- enumerable: true,
744
- get: function() {
745
- return m[k];
746
- }
747
- };
748
- Object.defineProperty(o, k2, desc);
749
- }) : (function(o, m, k, k2) {
750
- if (k2 === void 0) k2 = k;
751
- o[k2] = m[k];
752
- }));
753
- var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
754
- Object.defineProperty(o, "default", {
755
- enumerable: true,
756
- value: v
757
- });
758
- }) : function(o, v) {
759
- o["default"] = v;
760
- });
761
- var __importStar = exports && exports.__importStar || (function() {
762
- var ownKeys = function(o) {
763
- ownKeys = Object.getOwnPropertyNames || function(o) {
764
- var ar = [];
765
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
766
- return ar;
767
- };
768
- return ownKeys(o);
769
- };
770
- return function(mod) {
771
- if (mod && mod.__esModule) return mod;
772
- var result = {};
773
- if (mod != null) {
774
- for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
775
- }
776
- __setModuleDefault(result, mod);
777
- return result;
778
- };
779
- })();
780
- Object.defineProperty(exports, "__esModule", { value: true });
781
- exports.parseList = parseList;
782
- /**
783
- * Available directory listing parsers. These are candidates that will be tested
784
- * in the order presented. The first candidate will be used to parse the whole list.
785
- */
786
- var availableParsers = [
787
- __importStar(require_parseListDOS()),
788
- __importStar(require_parseListUnix()),
789
- __importStar(require_parseListMLSD())
790
- ];
791
- function firstCompatibleParser(line, parsers) {
792
- return parsers.find((parser) => parser.testLine(line) === true);
793
- }
794
- function isNotBlank(str) {
795
- return str.trim() !== "";
796
- }
797
- function isNotMeta(str) {
798
- return !str.startsWith("total");
799
- }
800
- var REGEX_NEWLINE = /\r?\n/;
801
- /**
802
- * Parse raw directory listing.
803
- */
804
- function parseList(rawList) {
805
- const lines = rawList.split(REGEX_NEWLINE).filter(isNotBlank).filter(isNotMeta);
806
- if (lines.length === 0) return [];
807
- const testLine = lines[lines.length - 1];
808
- const parser = firstCompatibleParser(testLine, availableParsers);
809
- if (!parser) throw new Error("This library only supports MLSD, Unix- or DOS-style directory listing. Your FTP server seems to be using another format. You can see the transmitted listing when setting `client.ftp.verbose = true`. You can then provide a custom parser to `client.parseList`, see the documentation for details.");
810
- const files = lines.map(parser.parseLine).filter((info) => info !== void 0);
811
- return parser.transformList(files);
812
- }
813
- }));
814
- var require_ProgressTracker = /* @__PURE__ */ __commonJSMin(((exports) => {
815
- Object.defineProperty(exports, "__esModule", { value: true });
816
- exports.ProgressTracker = void 0;
817
- /**
818
- * Tracks progress of one socket data transfer at a time.
819
- */
820
- var ProgressTracker = class {
821
- constructor() {
822
- this.bytesOverall = 0;
823
- this.intervalMs = 500;
824
- this.onStop = noop;
825
- this.onHandle = noop;
826
- }
827
- /**
828
- * Register a new handler for progress info. Use `undefined` to disable reporting.
829
- */
830
- reportTo(onHandle = noop) {
831
- this.onHandle = onHandle;
832
- }
833
- /**
834
- * Start tracking transfer progress of a socket.
835
- *
836
- * @param socket The socket to observe.
837
- * @param name A name associated with this progress tracking, e.g. a filename.
838
- * @param type The type of the transfer, typically "upload" or "download".
839
- */
840
- start(socket, name, type) {
841
- let lastBytes = 0;
842
- this.onStop = poll(this.intervalMs, () => {
843
- const bytes = socket.bytesRead + socket.bytesWritten;
844
- this.bytesOverall += bytes - lastBytes;
845
- lastBytes = bytes;
846
- this.onHandle({
847
- name,
848
- type,
849
- bytes,
850
- bytesOverall: this.bytesOverall
851
- });
852
- });
853
- }
854
- /**
855
- * Stop tracking transfer progress.
856
- */
857
- stop() {
858
- this.onStop(false);
859
- }
860
- /**
861
- * Call the progress handler one more time, then stop tracking.
862
- */
863
- updateAndStop() {
864
- this.onStop(true);
865
- }
866
- };
867
- exports.ProgressTracker = ProgressTracker;
868
- /**
869
- * Starts calling a callback function at a regular interval. The first call will go out
870
- * immediately. The function returns a function to stop the polling.
871
- */
872
- function poll(intervalMs, updateFunc) {
873
- const id = setInterval(updateFunc, intervalMs);
874
- const stopFunc = (stopWithUpdate) => {
875
- clearInterval(id);
876
- if (stopWithUpdate) updateFunc();
877
- updateFunc = noop;
878
- };
879
- updateFunc();
880
- return stopFunc;
881
- }
882
- function noop() {}
883
- }));
884
- var require_StringWriter = /* @__PURE__ */ __commonJSMin(((exports) => {
885
- Object.defineProperty(exports, "__esModule", { value: true });
886
- exports.StringWriter = void 0;
887
- var stream_1$1 = __require("stream");
888
- var StringWriter = class extends stream_1$1.Writable {
889
- constructor() {
890
- super(...arguments);
891
- this.buf = Buffer.alloc(0);
892
- }
893
- _write(chunk, _, callback) {
894
- if (chunk instanceof Buffer) {
895
- this.buf = Buffer.concat([this.buf, chunk]);
896
- callback(null);
897
- } else callback(/* @__PURE__ */ new Error("StringWriter expects chunks of type 'Buffer'."));
898
- }
899
- getText(encoding) {
900
- return this.buf.toString(encoding);
901
- }
902
- };
903
- exports.StringWriter = StringWriter;
904
- }));
905
- var require_netUtils = /* @__PURE__ */ __commonJSMin(((exports) => {
906
- Object.defineProperty(exports, "__esModule", { value: true });
907
- exports.describeTLS = describeTLS;
908
- exports.describeAddress = describeAddress;
909
- exports.upgradeSocket = upgradeSocket;
910
- exports.ipIsPrivateV4Address = ipIsPrivateV4Address;
911
- var tls_1$2 = __require("tls");
912
- /**
913
- * Returns a string describing the encryption on a given socket instance.
914
- */
915
- function describeTLS(socket) {
916
- if (socket instanceof tls_1$2.TLSSocket) {
917
- const protocol = socket.getProtocol();
918
- return protocol ? protocol : "Server socket or disconnected client socket";
919
- }
920
- return "No encryption";
921
- }
922
- /**
923
- * Returns a string describing the remote address of a socket.
924
- */
925
- function describeAddress(socket) {
926
- if (socket.remoteFamily === "IPv6") return `[${socket.remoteAddress}]:${socket.remotePort}`;
927
- return `${socket.remoteAddress}:${socket.remotePort}`;
928
- }
929
- /**
930
- * Upgrade a socket connection with TLS.
931
- */
932
- function upgradeSocket(socket, options) {
933
- return new Promise((resolve, reject) => {
934
- const tlsOptions = Object.assign({}, options, { socket });
935
- const tlsSocket = (0, tls_1$2.connect)(tlsOptions, () => {
936
- if (tlsOptions.rejectUnauthorized !== false && !tlsSocket.authorized) reject(tlsSocket.authorizationError);
937
- else {
938
- tlsSocket.removeAllListeners("error");
939
- resolve(tlsSocket);
940
- }
941
- }).once("error", (error) => {
942
- reject(error);
943
- });
944
- });
945
- }
946
- /**
947
- * Returns true if an IP is a private address according to https://tools.ietf.org/html/rfc1918#section-3.
948
- * This will handle IPv4-mapped IPv6 addresses correctly but return false for all other IPv6 addresses.
949
- *
950
- * @param ip The IP as a string, e.g. "192.168.0.1"
951
- */
952
- function ipIsPrivateV4Address(ip = "") {
953
- if (ip.startsWith("::ffff:")) ip = ip.substr(7);
954
- const octets = ip.split(".").map((o) => parseInt(o, 10));
955
- return octets[0] === 10 || octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31 || octets[0] === 192 && octets[1] === 168 || ip === "127.0.0.1";
956
- }
957
- }));
958
- var require_transfer = /* @__PURE__ */ __commonJSMin(((exports) => {
959
- Object.defineProperty(exports, "__esModule", { value: true });
960
- exports.enterPassiveModeIPv6 = enterPassiveModeIPv6;
961
- exports.parseEpsvResponse = parseEpsvResponse;
962
- exports.enterPassiveModeIPv4 = enterPassiveModeIPv4;
963
- exports.enterPassiveModeIPv4_forceControlHostIP = enterPassiveModeIPv4_forceControlHostIP;
964
- exports.parsePasvResponse = parsePasvResponse;
965
- exports.connectForPassiveTransfer = connectForPassiveTransfer;
966
- exports.uploadFrom = uploadFrom;
967
- exports.downloadTo = downloadTo;
968
- var netUtils_1 = require_netUtils();
969
- var stream_1 = __require("stream");
970
- var tls_1$1 = __require("tls");
971
- var parseControlResponse_1 = require_parseControlResponse();
972
- /**
973
- * Prepare a data socket using passive mode over IPv6.
974
- */
975
- async function enterPassiveModeIPv6(ftp) {
976
- const res = await ftp.request("EPSV");
977
- const port = parseEpsvResponse(res.message);
978
- if (!port) throw new Error("Can't parse EPSV response: " + res.message);
979
- const controlHost = ftp.socket.remoteAddress;
980
- if (controlHost === void 0) throw new Error("Control socket is disconnected, can't get remote address.");
981
- await connectForPassiveTransfer(controlHost, port, ftp);
982
- return res;
983
- }
984
- /**
985
- * Parse an EPSV response. Returns only the port as in EPSV the host of the control connection is used.
986
- */
987
- function parseEpsvResponse(message) {
988
- const groups = message.match(/[|!]{3}(.+)[|!]/);
989
- if (groups === null || groups[1] === void 0) throw new Error(`Can't parse response to 'EPSV': ${message}`);
990
- const port = parseInt(groups[1], 10);
991
- if (Number.isNaN(port)) throw new Error(`Can't parse response to 'EPSV', port is not a number: ${message}`);
992
- return port;
993
- }
994
- /**
995
- * Prepare a data socket using passive mode over IPv4.
996
- */
997
- async function enterPassiveModeIPv4(ftp) {
998
- const res = await ftp.request("PASV");
999
- const target = parsePasvResponse(res.message);
1000
- if (!target) throw new Error("Can't parse PASV response: " + res.message);
1001
- const controlHost = ftp.socket.remoteAddress;
1002
- if ((0, netUtils_1.ipIsPrivateV4Address)(target.host) && controlHost && !(0, netUtils_1.ipIsPrivateV4Address)(controlHost)) target.host = controlHost;
1003
- await connectForPassiveTransfer(target.host, target.port, ftp);
1004
- return res;
1005
- }
1006
- /**
1007
- * Prepare a data socket using passive mode over IPv4. Ignore the IP provided by the PASV response,
1008
- * and use the control host IP. This is the same behaviour as with the more modern variant EPSV. Use
1009
- * this to fix issues around NAT or provide more security by preventing FTP bounce attacks.
1010
- */
1011
- async function enterPassiveModeIPv4_forceControlHostIP(ftp) {
1012
- const res = await ftp.request("PASV");
1013
- const target = parsePasvResponse(res.message);
1014
- if (!target) throw new Error("Can't parse PASV response: " + res.message);
1015
- const controlHost = ftp.socket.remoteAddress;
1016
- if (controlHost === void 0) throw new Error("Control socket is disconnected, can't get remote address.");
1017
- await connectForPassiveTransfer(controlHost, target.port, ftp);
1018
- return res;
1019
- }
1020
- /**
1021
- * Parse a PASV response.
1022
- */
1023
- function parsePasvResponse(message) {
1024
- const groups = message.match(/([-\d]+,[-\d]+,[-\d]+,[-\d]+),([-\d]+),([-\d]+)/);
1025
- if (groups === null || groups.length !== 4) throw new Error(`Can't parse response to 'PASV': ${message}`);
1026
- return {
1027
- host: groups[1].replace(/,/g, "."),
1028
- port: (parseInt(groups[2], 10) & 255) * 256 + (parseInt(groups[3], 10) & 255)
1029
- };
1030
- }
1031
- function connectForPassiveTransfer(host, port, ftp) {
1032
- return new Promise((resolve, reject) => {
1033
- let socket = ftp._newSocket();
1034
- const handleConnErr = function(err) {
1035
- err.message = "Can't open data connection in passive mode: " + err.message;
1036
- reject(err);
1037
- };
1038
- const handleTimeout = function() {
1039
- socket.destroy();
1040
- reject(/* @__PURE__ */ new Error(`Timeout when trying to open data connection to ${host}:${port}`));
1041
- };
1042
- socket.setTimeout(ftp.timeout);
1043
- socket.on("error", handleConnErr);
1044
- socket.on("timeout", handleTimeout);
1045
- socket.connect({
1046
- port,
1047
- host,
1048
- family: ftp.ipFamily
1049
- }, () => {
1050
- if (ftp.socket instanceof tls_1$1.TLSSocket) socket = (0, tls_1$1.connect)(Object.assign({}, ftp.tlsOptions, {
1051
- socket,
1052
- session: ftp.socket.getSession()
1053
- }));
1054
- socket.removeListener("error", handleConnErr);
1055
- socket.removeListener("timeout", handleTimeout);
1056
- ftp.dataSocket = socket;
1057
- resolve();
1058
- });
1059
- });
1060
- }
1061
- /**
1062
- * Helps resolving/rejecting transfers.
1063
- *
1064
- * This is used internally for all FTP transfers. For example when downloading, the server might confirm
1065
- * with "226 Transfer complete" when in fact the download on the data connection has not finished
1066
- * yet. With all transfers we make sure that a) the result arrived and b) has been confirmed by
1067
- * e.g. the control connection. We just don't know in which order this will happen.
1068
- */
1069
- var TransferResolver = class {
1070
- /**
1071
- * Instantiate a TransferResolver
1072
- */
1073
- constructor(ftp, progress) {
1074
- this.ftp = ftp;
1075
- this.progress = progress;
1076
- this.response = void 0;
1077
- this.dataTransferDone = false;
1078
- }
1079
- /**
1080
- * Mark the beginning of a transfer.
1081
- *
1082
- * @param name - Name of the transfer, usually the filename.
1083
- * @param type - Type of transfer, usually "upload" or "download".
1084
- */
1085
- onDataStart(name, type) {
1086
- if (this.ftp.dataSocket === void 0) throw new Error("Data transfer should start but there is no data connection.");
1087
- this.ftp.socket.setTimeout(0);
1088
- this.ftp.dataSocket.setTimeout(this.ftp.timeout);
1089
- this.progress.start(this.ftp.dataSocket, name, type);
1090
- }
1091
- /**
1092
- * The data connection has finished the transfer.
1093
- */
1094
- onDataDone(task) {
1095
- this.progress.updateAndStop();
1096
- this.ftp.socket.setTimeout(this.ftp.timeout);
1097
- if (this.ftp.dataSocket) this.ftp.dataSocket.setTimeout(0);
1098
- this.dataTransferDone = true;
1099
- this.tryResolve(task);
1100
- }
1101
- /**
1102
- * The control connection reports the transfer as finished.
1103
- */
1104
- onControlDone(task, response) {
1105
- this.response = response;
1106
- this.tryResolve(task);
1107
- }
1108
- /**
1109
- * An error has been reported and the task should be rejected.
1110
- */
1111
- onError(task, err) {
1112
- this.progress.updateAndStop();
1113
- this.ftp.socket.setTimeout(this.ftp.timeout);
1114
- this.ftp.dataSocket = void 0;
1115
- task.reject(err);
1116
- }
1117
- /**
1118
- * Control connection sent an unexpected request requiring a response from our part. We
1119
- * can't provide that (because unknown) and have to close the contrext with an error because
1120
- * the FTP server is now caught up in a state we can't resolve.
1121
- */
1122
- onUnexpectedRequest(response) {
1123
- const err = /* @__PURE__ */ new Error(`Unexpected FTP response is requesting an answer: ${response.message}`);
1124
- this.ftp.closeWithError(err);
1125
- }
1126
- tryResolve(task) {
1127
- if (this.dataTransferDone && this.response !== void 0) {
1128
- this.ftp.dataSocket = void 0;
1129
- task.resolve(this.response);
1130
- }
1131
- }
1132
- };
1133
- function uploadFrom(source, config) {
1134
- const resolver = new TransferResolver(config.ftp, config.tracker);
1135
- const fullCommand = `${config.command} ${config.remotePath}`;
1136
- return config.ftp.handle(fullCommand, (res, task) => {
1137
- if (res instanceof Error) resolver.onError(task, res);
1138
- else if (res.code === 150 || res.code === 125) {
1139
- const dataSocket = config.ftp.dataSocket;
1140
- if (!dataSocket) {
1141
- resolver.onError(task, /* @__PURE__ */ new Error("Upload should begin but no data connection is available."));
1142
- return;
1143
- }
1144
- onConditionOrEvent("getCipher" in dataSocket ? dataSocket.getCipher() !== void 0 : true, dataSocket, "secureConnect", () => {
1145
- config.ftp.log(`Uploading to ${(0, netUtils_1.describeAddress)(dataSocket)} (${(0, netUtils_1.describeTLS)(dataSocket)})`);
1146
- resolver.onDataStart(config.remotePath, config.type);
1147
- (0, stream_1.pipeline)(source, dataSocket, (err) => {
1148
- if (err) resolver.onError(task, err);
1149
- else resolver.onDataDone(task);
1150
- });
1151
- });
1152
- } else if ((0, parseControlResponse_1.positiveCompletion)(res.code)) resolver.onControlDone(task, res);
1153
- else if ((0, parseControlResponse_1.positiveIntermediate)(res.code)) resolver.onUnexpectedRequest(res);
1154
- });
1155
- }
1156
- function downloadTo(destination, config) {
1157
- if (!config.ftp.dataSocket) throw new Error("Download will be initiated but no data connection is available.");
1158
- const resolver = new TransferResolver(config.ftp, config.tracker);
1159
- return config.ftp.handle(config.command, (res, task) => {
1160
- if (res instanceof Error) resolver.onError(task, res);
1161
- else if (res.code === 150 || res.code === 125) {
1162
- const dataSocket = config.ftp.dataSocket;
1163
- if (!dataSocket) {
1164
- resolver.onError(task, /* @__PURE__ */ new Error("Download should begin but no data connection is available."));
1165
- return;
1166
- }
1167
- config.ftp.log(`Downloading from ${(0, netUtils_1.describeAddress)(dataSocket)} (${(0, netUtils_1.describeTLS)(dataSocket)})`);
1168
- resolver.onDataStart(config.remotePath, config.type);
1169
- (0, stream_1.pipeline)(dataSocket, destination, (err) => {
1170
- if (err) resolver.onError(task, err);
1171
- else resolver.onDataDone(task);
1172
- });
1173
- } else if (res.code === 350) config.ftp.send("RETR " + config.remotePath);
1174
- else if ((0, parseControlResponse_1.positiveCompletion)(res.code)) resolver.onControlDone(task, res);
1175
- else if ((0, parseControlResponse_1.positiveIntermediate)(res.code)) resolver.onUnexpectedRequest(res);
1176
- });
1177
- }
1178
- /**
1179
- * Calls a function immediately if a condition is met or subscribes to an event and calls
1180
- * it once the event is emitted.
1181
- *
1182
- * @param condition The condition to test.
1183
- * @param emitter The emitter to use if the condition is not met.
1184
- * @param eventName The event to subscribe to if the condition is not met.
1185
- * @param action The function to call.
1186
- */
1187
- function onConditionOrEvent(condition, emitter, eventName, action) {
1188
- if (condition === true) action();
1189
- else emitter.once(eventName, () => action());
1190
- }
1191
- }));
1192
- var require_Client = /* @__PURE__ */ __commonJSMin(((exports) => {
1193
- Object.defineProperty(exports, "__esModule", { value: true });
1194
- exports.Client = void 0;
1195
- var fs_1 = __require("fs");
1196
- var path_1 = __require("path");
1197
- var tls_1 = __require("tls");
1198
- var util_1 = __require("util");
1199
- var FtpContext_1 = require_FtpContext();
1200
- var parseList_1 = require_parseList();
1201
- var ProgressTracker_1 = require_ProgressTracker();
1202
- var StringWriter_1 = require_StringWriter();
1203
- var parseListMLSD_1 = require_parseListMLSD();
1204
- var netUtils_1 = require_netUtils();
1205
- var transfer_1 = require_transfer();
1206
- var parseControlResponse_1 = require_parseControlResponse();
1207
- var fsReadDir = (0, util_1.promisify)(fs_1.readdir);
1208
- var fsMkDir = (0, util_1.promisify)(fs_1.mkdir);
1209
- var fsStat = (0, util_1.promisify)(fs_1.stat);
1210
- var fsOpen = (0, util_1.promisify)(fs_1.open);
1211
- var fsClose = (0, util_1.promisify)(fs_1.close);
1212
- var fsUnlink = (0, util_1.promisify)(fs_1.unlink);
1213
- var defaultClientOptions = { allowSeparateTransferHost: true };
1214
- var LIST_COMMANDS_DEFAULT = () => ["LIST -a", "LIST"];
1215
- var LIST_COMMANDS_MLSD = () => [
1216
- "MLSD",
1217
- "LIST -a",
1218
- "LIST"
1219
- ];
1220
- /**
1221
- * High-level API to interact with an FTP server.
1222
- */
1223
- var Client = class {
1224
- /**
1225
- * Instantiate an FTP client.
1226
- *
1227
- * @param timeout Timeout in milliseconds, use 0 for no timeout. Optional, default is 30 seconds.
1228
- */
1229
- constructor(timeout = 3e4, options = defaultClientOptions) {
1230
- this.availableListCommands = LIST_COMMANDS_DEFAULT();
1231
- this.ftp = new FtpContext_1.FTPContext(timeout);
1232
- this.prepareTransfer = this._enterFirstCompatibleMode([transfer_1.enterPassiveModeIPv6, options.allowSeparateTransferHost ? transfer_1.enterPassiveModeIPv4 : transfer_1.enterPassiveModeIPv4_forceControlHostIP]);
1233
- this.parseList = parseList_1.parseList;
1234
- this._progressTracker = new ProgressTracker_1.ProgressTracker();
1235
- }
1236
- /**
1237
- * Close the client and all open socket connections.
1238
- *
1239
- * Close the client and all open socket connections. The client can’t be used anymore after calling this method,
1240
- * you have to either reconnect with `access` or `connect` or instantiate a new instance to continue any work.
1241
- * A client is also closed automatically if any timeout or connection error occurs.
1242
- */
1243
- close() {
1244
- this.ftp.close();
1245
- this._progressTracker.stop();
1246
- }
1247
- /**
1248
- * Returns true if the client is closed and can't be used anymore.
1249
- */
1250
- get closed() {
1251
- return this.ftp.closed;
1252
- }
1253
- /**
1254
- * Connect (or reconnect) to an FTP server.
1255
- *
1256
- * This is an instance method and thus can be called multiple times during the lifecycle of a `Client`
1257
- * instance. Whenever you do, the client is reset with a new control connection. This also implies that
1258
- * you can reopen a `Client` instance that has been closed due to an error when reconnecting with this
1259
- * method. In fact, reconnecting is the only way to continue using a closed `Client`.
1260
- *
1261
- * @param host Host the client should connect to. Optional, default is "localhost".
1262
- * @param port Port the client should connect to. Optional, default is 21.
1263
- */
1264
- connect(host = "localhost", port = 21) {
1265
- this.ftp.reset();
1266
- this.ftp.socket.connect({
1267
- host,
1268
- port,
1269
- family: this.ftp.ipFamily
1270
- }, () => this.ftp.log(`Connected to ${(0, netUtils_1.describeAddress)(this.ftp.socket)} (${(0, netUtils_1.describeTLS)(this.ftp.socket)})`));
1271
- return this._handleConnectResponse();
1272
- }
1273
- /**
1274
- * As `connect` but using implicit TLS. Implicit TLS is not an FTP standard and has been replaced by
1275
- * explicit TLS. There are still FTP servers that support only implicit TLS, though.
1276
- */
1277
- connectImplicitTLS(host = "localhost", port = 21, tlsOptions = {}) {
1278
- this.ftp.reset();
1279
- this.ftp.socket = (0, tls_1.connect)(port, host, tlsOptions, () => this.ftp.log(`Connected to ${(0, netUtils_1.describeAddress)(this.ftp.socket)} (${(0, netUtils_1.describeTLS)(this.ftp.socket)})`));
1280
- this.ftp.tlsOptions = tlsOptions;
1281
- return this._handleConnectResponse();
1282
- }
1283
- /**
1284
- * Handles the first reponse by an FTP server after the socket connection has been established.
1285
- */
1286
- _handleConnectResponse() {
1287
- return this.ftp.handle(void 0, (res, task) => {
1288
- if (res instanceof Error) task.reject(res);
1289
- else if ((0, parseControlResponse_1.positiveCompletion)(res.code)) task.resolve(res);
1290
- else task.reject(new FtpContext_1.FTPError(res));
1291
- });
1292
- }
1293
- /**
1294
- * Send an FTP command and handle the first response.
1295
- */
1296
- send(command, ignoreErrorCodesDEPRECATED = false) {
1297
- if (ignoreErrorCodesDEPRECATED) {
1298
- this.ftp.log("Deprecated call using send(command, flag) with boolean flag to ignore errors. Use sendIgnoringError(command).");
1299
- return this.sendIgnoringError(command);
1300
- }
1301
- return this.ftp.request(command);
1302
- }
1303
- /**
1304
- * Send an FTP command and ignore an FTP error response. Any other kind of error or timeout will still reject the Promise.
1305
- *
1306
- * @param command
1307
- */
1308
- sendIgnoringError(command) {
1309
- return this.ftp.handle(command, (res, task) => {
1310
- if (res instanceof FtpContext_1.FTPError) task.resolve({
1311
- code: res.code,
1312
- message: res.message
1313
- });
1314
- else if (res instanceof Error) task.reject(res);
1315
- else task.resolve(res);
1316
- });
1317
- }
1318
- /**
1319
- * Upgrade the current socket connection to TLS.
1320
- *
1321
- * @param options TLS options as in `tls.connect(options)`, optional.
1322
- * @param command Set the authentication command. Optional, default is "AUTH TLS".
1323
- */
1324
- async useTLS(options = {}, command = "AUTH TLS") {
1325
- const ret = await this.send(command);
1326
- this.ftp.socket = await (0, netUtils_1.upgradeSocket)(this.ftp.socket, options);
1327
- this.ftp.tlsOptions = options;
1328
- this.ftp.log(`Control socket is using: ${(0, netUtils_1.describeTLS)(this.ftp.socket)}`);
1329
- return ret;
1330
- }
1331
- /**
1332
- * Login a user with a password.
1333
- *
1334
- * @param user Username to use for login. Optional, default is "anonymous".
1335
- * @param password Password to use for login. Optional, default is "guest".
1336
- */
1337
- login(user = "anonymous", password = "guest") {
1338
- this.ftp.log(`Login security: ${(0, netUtils_1.describeTLS)(this.ftp.socket)}`);
1339
- return this.ftp.handle("USER " + user, (res, task) => {
1340
- if (res instanceof Error) task.reject(res);
1341
- else if ((0, parseControlResponse_1.positiveCompletion)(res.code)) task.resolve(res);
1342
- else if (res.code === 331) this.ftp.send("PASS " + password);
1343
- else task.reject(new FtpContext_1.FTPError(res));
1344
- });
1345
- }
1346
- /**
1347
- * Set the usual default settings.
1348
- *
1349
- * Settings used:
1350
- * * Binary mode (TYPE I)
1351
- * * File structure (STRU F)
1352
- * * Additional settings for FTPS (PBSZ 0, PROT P)
1353
- */
1354
- async useDefaultSettings() {
1355
- const supportsMLSD = (await this.features()).has("MLST");
1356
- this.availableListCommands = supportsMLSD ? LIST_COMMANDS_MLSD() : LIST_COMMANDS_DEFAULT();
1357
- await this.send("TYPE I");
1358
- await this.sendIgnoringError("STRU F");
1359
- await this.sendIgnoringError("OPTS UTF8 ON");
1360
- if (supportsMLSD) await this.sendIgnoringError("OPTS MLST type;size;modify;unique;unix.mode;unix.owner;unix.group;unix.ownername;unix.groupname;");
1361
- if (this.ftp.hasTLS) {
1362
- await this.sendIgnoringError("PBSZ 0");
1363
- await this.sendIgnoringError("PROT P");
1364
- }
1365
- }
1366
- /**
1367
- * Convenience method that calls `connect`, `useTLS`, `login` and `useDefaultSettings`.
1368
- *
1369
- * This is an instance method and thus can be called multiple times during the lifecycle of a `Client`
1370
- * instance. Whenever you do, the client is reset with a new control connection. This also implies that
1371
- * you can reopen a `Client` instance that has been closed due to an error when reconnecting with this
1372
- * method. In fact, reconnecting is the only way to continue using a closed `Client`.
1373
- */
1374
- async access(options = {}) {
1375
- var _a, _b;
1376
- const useExplicitTLS = options.secure === true;
1377
- const useImplicitTLS = options.secure === "implicit";
1378
- let welcome;
1379
- if (useImplicitTLS) welcome = await this.connectImplicitTLS(options.host, options.port, options.secureOptions);
1380
- else welcome = await this.connect(options.host, options.port);
1381
- if (useExplicitTLS) {
1382
- const secureOptions = (_a = options.secureOptions) !== null && _a !== void 0 ? _a : {};
1383
- secureOptions.host = (_b = secureOptions.host) !== null && _b !== void 0 ? _b : options.host;
1384
- await this.useTLS(secureOptions);
1385
- }
1386
- await this.sendIgnoringError("OPTS UTF8 ON");
1387
- await this.login(options.user, options.password);
1388
- await this.useDefaultSettings();
1389
- return welcome;
1390
- }
1391
- /**
1392
- * Get the current working directory.
1393
- */
1394
- async pwd() {
1395
- const res = await this.send("PWD");
1396
- const parsed = res.message.match(/"(.+)"/);
1397
- if (parsed === null || parsed[1] === void 0) throw new Error(`Can't parse response to command 'PWD': ${res.message}`);
1398
- return parsed[1];
1399
- }
1400
- /**
1401
- * Get a description of supported features.
1402
- *
1403
- * This sends the FEAT command and parses the result into a Map where keys correspond to available commands
1404
- * and values hold further information. Be aware that your FTP servers might not support this
1405
- * command in which case this method will not throw an exception but just return an empty Map.
1406
- */
1407
- async features() {
1408
- const res = await this.sendIgnoringError("FEAT");
1409
- const features = /* @__PURE__ */ new Map();
1410
- if (res.code < 400 && (0, parseControlResponse_1.isMultiline)(res.message)) res.message.split("\n").slice(1, -1).forEach((line) => {
1411
- const entry = line.trim().split(" ");
1412
- features.set(entry[0], entry[1] || "");
1413
- });
1414
- return features;
1415
- }
1416
- /**
1417
- * Set the working directory.
1418
- */
1419
- async cd(path) {
1420
- const validPath = await this.protectWhitespace(path);
1421
- return this.send("CWD " + validPath);
1422
- }
1423
- /**
1424
- * Switch to the parent directory of the working directory.
1425
- */
1426
- async cdup() {
1427
- return this.send("CDUP");
1428
- }
1429
- /**
1430
- * Get the last modified time of a file. This is not supported by every FTP server, in which case
1431
- * calling this method will throw an exception.
1432
- */
1433
- async lastMod(path) {
1434
- const validPath = await this.protectWhitespace(path);
1435
- const date = (await this.send(`MDTM ${validPath}`)).message.slice(4);
1436
- return (0, parseListMLSD_1.parseMLSxDate)(date);
1437
- }
1438
- /**
1439
- * Get the size of a file.
1440
- */
1441
- async size(path) {
1442
- const command = `SIZE ${await this.protectWhitespace(path)}`;
1443
- const res = await this.send(command);
1444
- const size = parseInt(res.message.slice(4), 10);
1445
- if (Number.isNaN(size)) throw new Error(`Can't parse response to command '${command}' as a numerical value: ${res.message}`);
1446
- return size;
1447
- }
1448
- /**
1449
- * Rename a file.
1450
- *
1451
- * Depending on the FTP server this might also be used to move a file from one
1452
- * directory to another by providing full paths.
1453
- */
1454
- async rename(srcPath, destPath) {
1455
- const validSrc = await this.protectWhitespace(srcPath);
1456
- const validDest = await this.protectWhitespace(destPath);
1457
- await this.send("RNFR " + validSrc);
1458
- return this.send("RNTO " + validDest);
1459
- }
1460
- /**
1461
- * Remove a file from the current working directory.
1462
- *
1463
- * You can ignore FTP error return codes which won't throw an exception if e.g.
1464
- * the file doesn't exist.
1465
- */
1466
- async remove(path, ignoreErrorCodes = false) {
1467
- const validPath = await this.protectWhitespace(path);
1468
- if (ignoreErrorCodes) return this.sendIgnoringError(`DELE ${validPath}`);
1469
- return this.send(`DELE ${validPath}`);
1470
- }
1471
- /**
1472
- * Report transfer progress for any upload or download to a given handler.
1473
- *
1474
- * This will also reset the overall transfer counter that can be used for multiple transfers. You can
1475
- * also call the function without a handler to stop reporting to an earlier one.
1476
- *
1477
- * @param handler Handler function to call on transfer progress.
1478
- */
1479
- trackProgress(handler) {
1480
- this._progressTracker.bytesOverall = 0;
1481
- this._progressTracker.reportTo(handler);
1482
- }
1483
- /**
1484
- * Upload data from a readable stream or a local file to a remote file.
1485
- *
1486
- * @param source Readable stream or path to a local file.
1487
- * @param toRemotePath Path to a remote file to write to.
1488
- */
1489
- async uploadFrom(source, toRemotePath, options = {}) {
1490
- return this._uploadWithCommand(source, toRemotePath, "STOR", options);
1491
- }
1492
- /**
1493
- * Upload data from a readable stream or a local file by appending it to an existing file. If the file doesn't
1494
- * exist the FTP server should create it.
1495
- *
1496
- * @param source Readable stream or path to a local file.
1497
- * @param toRemotePath Path to a remote file to write to.
1498
- */
1499
- async appendFrom(source, toRemotePath, options = {}) {
1500
- return this._uploadWithCommand(source, toRemotePath, "APPE", options);
1501
- }
1502
- /**
1503
- * @protected
1504
- */
1505
- async _uploadWithCommand(source, remotePath, command, options) {
1506
- if (typeof source === "string") return this._uploadLocalFile(source, remotePath, command, options);
1507
- return this._uploadFromStream(source, remotePath, command);
1508
- }
1509
- /**
1510
- * @protected
1511
- */
1512
- async _uploadLocalFile(localPath, remotePath, command, options) {
1513
- const fd = await fsOpen(localPath, "r");
1514
- const source = (0, fs_1.createReadStream)("", {
1515
- fd,
1516
- start: options.localStart,
1517
- end: options.localEndInclusive,
1518
- autoClose: false
1519
- });
1520
- try {
1521
- return await this._uploadFromStream(source, remotePath, command);
1522
- } finally {
1523
- await ignoreError(() => fsClose(fd));
1524
- }
1525
- }
1526
- /**
1527
- * @protected
1528
- */
1529
- async _uploadFromStream(source, remotePath, command) {
1530
- const onError = (err) => this.ftp.closeWithError(err);
1531
- source.once("error", onError);
1532
- try {
1533
- const validPath = await this.protectWhitespace(remotePath);
1534
- await this.prepareTransfer(this.ftp);
1535
- return await (0, transfer_1.uploadFrom)(source, {
1536
- ftp: this.ftp,
1537
- tracker: this._progressTracker,
1538
- command,
1539
- remotePath: validPath,
1540
- type: "upload"
1541
- });
1542
- } finally {
1543
- source.removeListener("error", onError);
1544
- }
1545
- }
1546
- /**
1547
- * Download a remote file and pipe its data to a writable stream or to a local file.
1548
- *
1549
- * You can optionally define at which position of the remote file you'd like to start
1550
- * downloading. If the destination you provide is a file, the offset will be applied
1551
- * to it as well. For example: To resume a failed download, you'd request the size of
1552
- * the local, partially downloaded file and use that as the offset. Assuming the size
1553
- * is 23, you'd download the rest using `downloadTo("local.txt", "remote.txt", 23)`.
1554
- *
1555
- * @param destination Stream or path for a local file to write to.
1556
- * @param fromRemotePath Path of the remote file to read from.
1557
- * @param startAt Position within the remote file to start downloading at. If the destination is a file, this offset is also applied to it.
1558
- */
1559
- async downloadTo(destination, fromRemotePath, startAt = 0) {
1560
- if (typeof destination === "string") return this._downloadToFile(destination, fromRemotePath, startAt);
1561
- return this._downloadToStream(destination, fromRemotePath, startAt);
1562
- }
1563
- /**
1564
- * @protected
1565
- */
1566
- async _downloadToFile(localPath, remotePath, startAt) {
1567
- const appendingToLocalFile = startAt > 0;
1568
- const fd = await fsOpen(localPath, appendingToLocalFile ? "r+" : "w");
1569
- const destination = (0, fs_1.createWriteStream)("", {
1570
- fd,
1571
- start: startAt,
1572
- autoClose: false
1573
- });
1574
- try {
1575
- return await this._downloadToStream(destination, remotePath, startAt);
1576
- } catch (err) {
1577
- const localFileStats = await ignoreError(() => fsStat(localPath));
1578
- const hasDownloadedData = localFileStats && localFileStats.size > 0;
1579
- if (!appendingToLocalFile && !hasDownloadedData) await ignoreError(() => fsUnlink(localPath));
1580
- throw err;
1581
- } finally {
1582
- await ignoreError(() => fsClose(fd));
1583
- }
1584
- }
1585
- /**
1586
- * @protected
1587
- */
1588
- async _downloadToStream(destination, remotePath, startAt) {
1589
- const onError = (err) => this.ftp.closeWithError(err);
1590
- destination.once("error", onError);
1591
- try {
1592
- const validPath = await this.protectWhitespace(remotePath);
1593
- await this.prepareTransfer(this.ftp);
1594
- return await (0, transfer_1.downloadTo)(destination, {
1595
- ftp: this.ftp,
1596
- tracker: this._progressTracker,
1597
- command: startAt > 0 ? `REST ${startAt}` : `RETR ${validPath}`,
1598
- remotePath: validPath,
1599
- type: "download"
1600
- });
1601
- } finally {
1602
- destination.removeListener("error", onError);
1603
- destination.end();
1604
- }
1605
- }
1606
- /**
1607
- * List files and directories in the current working directory, or from `path` if specified.
1608
- *
1609
- * @param [path] Path to remote file or directory.
1610
- */
1611
- async list(path = "") {
1612
- const validPath = await this.protectWhitespace(path);
1613
- let lastError;
1614
- for (const candidate of this.availableListCommands) {
1615
- const command = validPath === "" ? candidate : `${candidate} ${validPath}`;
1616
- await this.prepareTransfer(this.ftp);
1617
- try {
1618
- const parsedList = await this._requestListWithCommand(command);
1619
- this.availableListCommands = [candidate];
1620
- return parsedList;
1621
- } catch (err) {
1622
- if (!(err instanceof FtpContext_1.FTPError)) throw err;
1623
- lastError = err;
1624
- }
1625
- }
1626
- throw lastError;
1627
- }
1628
- /**
1629
- * @protected
1630
- */
1631
- async _requestListWithCommand(command) {
1632
- const buffer = new StringWriter_1.StringWriter();
1633
- await (0, transfer_1.downloadTo)(buffer, {
1634
- ftp: this.ftp,
1635
- tracker: this._progressTracker,
1636
- command,
1637
- remotePath: "",
1638
- type: "list"
1639
- });
1640
- const text = buffer.getText(this.ftp.encoding);
1641
- this.ftp.log(text);
1642
- return this.parseList(text);
1643
- }
1644
- /**
1645
- * Remove a directory and all of its content.
1646
- *
1647
- * @param remoteDirPath The path of the remote directory to delete.
1648
- * @example client.removeDir("foo") // Remove directory 'foo' using a relative path.
1649
- * @example client.removeDir("foo/bar") // Remove directory 'bar' using a relative path.
1650
- * @example client.removeDir("/foo/bar") // Remove directory 'bar' using an absolute path.
1651
- * @example client.removeDir("/") // Remove everything.
1652
- */
1653
- async removeDir(remoteDirPath) {
1654
- return this._exitAtCurrentDirectory(async () => {
1655
- await this.cd(remoteDirPath);
1656
- const absoluteDirPath = await this.pwd();
1657
- await this.clearWorkingDir();
1658
- if (!(absoluteDirPath === "/")) {
1659
- await this.cdup();
1660
- await this.removeEmptyDir(absoluteDirPath);
1661
- }
1662
- });
1663
- }
1664
- /**
1665
- * Remove all files and directories in the working directory without removing
1666
- * the working directory itself.
1667
- */
1668
- async clearWorkingDir() {
1669
- for (const file of await this.list()) if (file.isDirectory) {
1670
- await this.cd(file.name);
1671
- await this.clearWorkingDir();
1672
- await this.cdup();
1673
- await this.removeEmptyDir(file.name);
1674
- } else await this.remove(file.name);
1675
- }
1676
- /**
1677
- * Upload the contents of a local directory to the remote working directory.
1678
- *
1679
- * This will overwrite existing files with the same names and reuse existing directories.
1680
- * Unrelated files and directories will remain untouched. You can optionally provide a `remoteDirPath`
1681
- * to put the contents inside a directory which will be created if necessary including all
1682
- * intermediate directories. If you did provide a remoteDirPath the working directory will stay
1683
- * the same as before calling this method.
1684
- *
1685
- * @param localDirPath Local path, e.g. "foo/bar" or "../test"
1686
- * @param [remoteDirPath] Remote path of a directory to upload to. Working directory if undefined.
1687
- */
1688
- async uploadFromDir(localDirPath, remoteDirPath) {
1689
- return this._exitAtCurrentDirectory(async () => {
1690
- if (remoteDirPath) await this.ensureDir(remoteDirPath);
1691
- return await this._uploadToWorkingDir(localDirPath);
1692
- });
1693
- }
1694
- /**
1695
- * @protected
1696
- */
1697
- async _uploadToWorkingDir(localDirPath) {
1698
- const files = await fsReadDir(localDirPath);
1699
- for (const file of files) {
1700
- const fullPath = (0, path_1.join)(localDirPath, file);
1701
- const stats = await fsStat(fullPath);
1702
- if (stats.isFile()) await this.uploadFrom(fullPath, file);
1703
- else if (stats.isDirectory()) {
1704
- await this._openDir(file);
1705
- await this._uploadToWorkingDir(fullPath);
1706
- await this.cdup();
1707
- }
1708
- }
1709
- }
1710
- /**
1711
- * Download all files and directories of the working directory to a local directory.
1712
- *
1713
- * @param localDirPath The local directory to download to.
1714
- * @param remoteDirPath Remote directory to download. Current working directory if not specified.
1715
- */
1716
- async downloadToDir(localDirPath, remoteDirPath) {
1717
- return this._exitAtCurrentDirectory(async () => {
1718
- if (remoteDirPath) await this.cd(remoteDirPath);
1719
- return await this._downloadFromWorkingDir(localDirPath);
1720
- });
1721
- }
1722
- /**
1723
- * @protected
1724
- */
1725
- async _downloadFromWorkingDir(localDirPath) {
1726
- await ensureLocalDirectory(localDirPath);
1727
- for (const file of await this.list()) {
1728
- if (!file.name || (0, path_1.basename)(file.name) !== file.name) {
1729
- const safeName = JSON.stringify(file.name);
1730
- this.ftp.log(`Invalid filename from server listing, will skip file. (${safeName})`);
1731
- continue;
1732
- }
1733
- const localPath = (0, path_1.join)(localDirPath, file.name);
1734
- if (file.isDirectory) {
1735
- await this.cd(file.name);
1736
- await this._downloadFromWorkingDir(localPath);
1737
- await this.cdup();
1738
- } else if (file.isFile) await this.downloadTo(localPath, file.name);
1739
- }
1740
- }
1741
- /**
1742
- * Make sure a given remote path exists, creating all directories as necessary.
1743
- * This function also changes the current working directory to the given path.
1744
- */
1745
- async ensureDir(remoteDirPath) {
1746
- if (remoteDirPath.startsWith("/")) await this.cd("/");
1747
- const names = remoteDirPath.split("/").filter((name) => name !== "");
1748
- for (const name of names) await this._openDir(name);
1749
- }
1750
- /**
1751
- * Try to create a directory and enter it. This will not raise an exception if the directory
1752
- * couldn't be created if for example it already exists.
1753
- * @protected
1754
- */
1755
- async _openDir(dirName) {
1756
- await this.sendIgnoringError("MKD " + dirName);
1757
- await this.cd(dirName);
1758
- }
1759
- /**
1760
- * Remove an empty directory, will fail if not empty.
1761
- */
1762
- async removeEmptyDir(path) {
1763
- const validPath = await this.protectWhitespace(path);
1764
- return this.send(`RMD ${validPath}`);
1765
- }
1766
- /**
1767
- * FTP servers can't handle filenames that have leading whitespace. This method transforms
1768
- * a given path to fix that issue for most cases.
1769
- */
1770
- async protectWhitespace(path) {
1771
- if (!path.startsWith(" ")) return path;
1772
- const pwd = await this.pwd();
1773
- return (pwd.endsWith("/") ? pwd : pwd + "/") + path;
1774
- }
1775
- async _exitAtCurrentDirectory(func) {
1776
- const userDir = await this.pwd();
1777
- try {
1778
- return await func();
1779
- } finally {
1780
- if (!this.closed) await ignoreError(() => this.cd(userDir));
1781
- }
1782
- }
1783
- /**
1784
- * Try all available transfer strategies and pick the first one that works. Update `client` to
1785
- * use the working strategy for all successive transfer requests.
1786
- *
1787
- * @returns a function that will try the provided strategies.
1788
- */
1789
- _enterFirstCompatibleMode(strategies) {
1790
- return async (ftp) => {
1791
- ftp.log("Trying to find optimal transfer strategy...");
1792
- let lastError = void 0;
1793
- for (const strategy of strategies) try {
1794
- const res = await strategy(ftp);
1795
- ftp.log("Optimal transfer strategy found.");
1796
- this.prepareTransfer = strategy;
1797
- return res;
1798
- } catch (err) {
1799
- lastError = err;
1800
- }
1801
- throw new Error(`None of the available transfer strategies work. Last error response was '${lastError}'.`);
1802
- };
1803
- }
1804
- /**
1805
- * DEPRECATED, use `uploadFrom`.
1806
- * @deprecated
1807
- */
1808
- async upload(source, toRemotePath, options = {}) {
1809
- this.ftp.log("Warning: upload() has been deprecated, use uploadFrom().");
1810
- return this.uploadFrom(source, toRemotePath, options);
1811
- }
1812
- /**
1813
- * DEPRECATED, use `appendFrom`.
1814
- * @deprecated
1815
- */
1816
- async append(source, toRemotePath, options = {}) {
1817
- this.ftp.log("Warning: append() has been deprecated, use appendFrom().");
1818
- return this.appendFrom(source, toRemotePath, options);
1819
- }
1820
- /**
1821
- * DEPRECATED, use `downloadTo`.
1822
- * @deprecated
1823
- */
1824
- async download(destination, fromRemotePath, startAt = 0) {
1825
- this.ftp.log("Warning: download() has been deprecated, use downloadTo().");
1826
- return this.downloadTo(destination, fromRemotePath, startAt);
1827
- }
1828
- /**
1829
- * DEPRECATED, use `uploadFromDir`.
1830
- * @deprecated
1831
- */
1832
- async uploadDir(localDirPath, remoteDirPath) {
1833
- this.ftp.log("Warning: uploadDir() has been deprecated, use uploadFromDir().");
1834
- return this.uploadFromDir(localDirPath, remoteDirPath);
1835
- }
1836
- /**
1837
- * DEPRECATED, use `downloadToDir`.
1838
- * @deprecated
1839
- */
1840
- async downloadDir(localDirPath) {
1841
- this.ftp.log("Warning: downloadDir() has been deprecated, use downloadToDir().");
1842
- return this.downloadToDir(localDirPath);
1843
- }
1844
- };
1845
- exports.Client = Client;
1846
- async function ensureLocalDirectory(path) {
1847
- try {
1848
- await fsStat(path);
1849
- } catch (_a) {
1850
- await fsMkDir(path, { recursive: true });
1851
- }
1852
- }
1853
- async function ignoreError(func) {
1854
- try {
1855
- return await func();
1856
- } catch (_a) {
1857
- return;
1858
- }
1859
- }
1860
- }));
1861
- var require_StringEncoding = /* @__PURE__ */ __commonJSMin(((exports) => {
1862
- Object.defineProperty(exports, "__esModule", { value: true });
1863
- }));
1864
- var require_dist = /* @__PURE__ */ __commonJSMin(((exports) => {
1865
- var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
1866
- if (k2 === void 0) k2 = k;
1867
- var desc = Object.getOwnPropertyDescriptor(m, k);
1868
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) desc = {
1869
- enumerable: true,
1870
- get: function() {
1871
- return m[k];
1872
- }
1873
- };
1874
- Object.defineProperty(o, k2, desc);
1875
- }) : (function(o, m, k, k2) {
1876
- if (k2 === void 0) k2 = k;
1877
- o[k2] = m[k];
1878
- }));
1879
- var __exportStar = exports && exports.__exportStar || function(m, exports$1) {
1880
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports$1, p)) __createBinding(exports$1, m, p);
1881
- };
1882
- Object.defineProperty(exports, "__esModule", { value: true });
1883
- exports.enterPassiveModeIPv6 = exports.enterPassiveModeIPv4 = void 0;
1884
- /**
1885
- * Public API
1886
- */
1887
- __exportStar(require_Client(), exports);
1888
- __exportStar(require_FtpContext(), exports);
1889
- __exportStar(require_FileInfo(), exports);
1890
- __exportStar(require_parseList(), exports);
1891
- __exportStar(require_StringEncoding(), exports);
1892
- var transfer_1 = require_transfer();
1893
- Object.defineProperty(exports, "enterPassiveModeIPv4", {
1894
- enumerable: true,
1895
- get: function() {
1896
- return transfer_1.enterPassiveModeIPv4;
1897
- }
1898
- });
1899
- Object.defineProperty(exports, "enterPassiveModeIPv6", {
1900
- enumerable: true,
1901
- get: function() {
1902
- return transfer_1.enterPassiveModeIPv6;
1903
- }
1904
- });
1905
- }));
1906
- export { require_dist as t };