@zero-transfer/webdav 0.4.7 → 0.4.8
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/index.cjs +396 -123
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +245 -35
- package/dist/index.d.ts +245 -35
- package/dist/index.mjs +393 -123
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -60,6 +60,7 @@ __export(webdav_exports, {
|
|
|
60
60
|
copyBetween: () => copyBetween,
|
|
61
61
|
createAtomicDeployPlan: () => createAtomicDeployPlan,
|
|
62
62
|
createBandwidthThrottle: () => createBandwidthThrottle,
|
|
63
|
+
createDefaultRetryPolicy: () => createDefaultRetryPolicy,
|
|
63
64
|
createLocalProviderFactory: () => createLocalProviderFactory,
|
|
64
65
|
createMemoryProviderFactory: () => createMemoryProviderFactory,
|
|
65
66
|
createOAuthTokenSecretSource: () => createOAuthTokenSecretSource,
|
|
@@ -96,8 +97,10 @@ __export(webdav_exports, {
|
|
|
96
97
|
parseRemoteManifest: () => parseRemoteManifest,
|
|
97
98
|
redactCommand: () => redactCommand,
|
|
98
99
|
redactConnectionProfile: () => redactConnectionProfile,
|
|
100
|
+
redactErrorForLogging: () => redactErrorForLogging,
|
|
99
101
|
redactObject: () => redactObject,
|
|
100
102
|
redactSecretSource: () => redactSecretSource,
|
|
103
|
+
redactUrlForLogging: () => redactUrlForLogging,
|
|
101
104
|
redactValue: () => redactValue,
|
|
102
105
|
resolveConnectionProfileSecrets: () => resolveConnectionProfileSecrets,
|
|
103
106
|
resolveOpenSshHost: () => resolveOpenSshHost,
|
|
@@ -118,6 +121,68 @@ module.exports = __toCommonJS(webdav_exports);
|
|
|
118
121
|
// src/client/ZeroTransfer.ts
|
|
119
122
|
var import_node_events = require("events");
|
|
120
123
|
|
|
124
|
+
// src/logging/redaction.ts
|
|
125
|
+
var REDACTED = "[REDACTED]";
|
|
126
|
+
var SENSITIVE_KEY_PATTERN = /(?:password|passphrase|privatekey|token|secret|username|user)$/i;
|
|
127
|
+
var SECRET_COMMAND_PATTERN = /^(PASS|USER|ACCT)\s+(.+)$/i;
|
|
128
|
+
var URL_KEY_PATTERN = /(?:url|uri|href)$/i;
|
|
129
|
+
function isSensitiveKey(key) {
|
|
130
|
+
return SENSITIVE_KEY_PATTERN.test(key.replace(/[_-]/g, ""));
|
|
131
|
+
}
|
|
132
|
+
function redactCommand(command) {
|
|
133
|
+
return command.replace(SECRET_COMMAND_PATTERN, (_fullMatch, commandName) => {
|
|
134
|
+
return `${commandName.toUpperCase()} ${REDACTED}`;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function redactValue(value) {
|
|
138
|
+
if (typeof value === "string") {
|
|
139
|
+
return redactCommand(value);
|
|
140
|
+
}
|
|
141
|
+
if (Array.isArray(value)) {
|
|
142
|
+
return value.map((item) => redactValue(item));
|
|
143
|
+
}
|
|
144
|
+
if (value !== null && typeof value === "object") {
|
|
145
|
+
return redactObject(value);
|
|
146
|
+
}
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
149
|
+
function redactObject(input) {
|
|
150
|
+
return Object.fromEntries(
|
|
151
|
+
Object.entries(input).map(([key, value]) => {
|
|
152
|
+
if (isSensitiveKey(key)) {
|
|
153
|
+
return [key, REDACTED];
|
|
154
|
+
}
|
|
155
|
+
if (URL_KEY_PATTERN.test(key) && typeof value === "string") {
|
|
156
|
+
return [key, redactUrlForLogging(value)];
|
|
157
|
+
}
|
|
158
|
+
return [key, redactValue(value)];
|
|
159
|
+
})
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
function redactUrlForLogging(url) {
|
|
163
|
+
let parsed;
|
|
164
|
+
try {
|
|
165
|
+
parsed = typeof url === "string" ? new URL(url) : url;
|
|
166
|
+
} catch {
|
|
167
|
+
return REDACTED;
|
|
168
|
+
}
|
|
169
|
+
const origin = parsed.host.length > 0 ? `${parsed.protocol}//${parsed.host}` : parsed.protocol;
|
|
170
|
+
const query = parsed.search.length > 0 ? `?${REDACTED}` : "";
|
|
171
|
+
return `${origin}${parsed.pathname}${query}`;
|
|
172
|
+
}
|
|
173
|
+
function redactErrorForLogging(error) {
|
|
174
|
+
if (error !== null && typeof error === "object") {
|
|
175
|
+
const candidate = error;
|
|
176
|
+
if (typeof candidate.toJSON === "function") {
|
|
177
|
+
return redactObject(candidate.toJSON());
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (error instanceof Error) {
|
|
181
|
+
return redactObject({ message: error.message, name: error.name });
|
|
182
|
+
}
|
|
183
|
+
return { message: redactValue(typeof error === "string" ? error : String(error)) };
|
|
184
|
+
}
|
|
185
|
+
|
|
121
186
|
// src/errors/ZeroTransferError.ts
|
|
122
187
|
var ZeroTransferError = class extends Error {
|
|
123
188
|
/** Stable machine-readable error code. */
|
|
@@ -159,6 +224,11 @@ var ZeroTransferError = class extends Error {
|
|
|
159
224
|
/**
|
|
160
225
|
* Serializes the error into a plain object suitable for logs or API responses.
|
|
161
226
|
*
|
|
227
|
+
* `details` and `command` are passed through secret redaction so serialized
|
|
228
|
+
* errors never leak credentials, signed URLs, or raw protocol commands. The
|
|
229
|
+
* live {@link ZeroTransferError.details | details} property stays unredacted
|
|
230
|
+
* for programmatic consumers.
|
|
231
|
+
*
|
|
162
232
|
* @returns A JSON-safe object containing public structured error fields.
|
|
163
233
|
*/
|
|
164
234
|
toJSON() {
|
|
@@ -168,12 +238,12 @@ var ZeroTransferError = class extends Error {
|
|
|
168
238
|
message: this.message,
|
|
169
239
|
protocol: this.protocol,
|
|
170
240
|
host: this.host,
|
|
171
|
-
command: this.command,
|
|
241
|
+
command: this.command === void 0 ? void 0 : redactCommand(this.command),
|
|
172
242
|
ftpCode: this.ftpCode,
|
|
173
243
|
sftpCode: this.sftpCode,
|
|
174
244
|
path: this.path,
|
|
175
245
|
retryable: this.retryable,
|
|
176
|
-
details: this.details
|
|
246
|
+
details: this.details === void 0 ? void 0 : redactObject(this.details)
|
|
177
247
|
};
|
|
178
248
|
}
|
|
179
249
|
};
|
|
@@ -696,15 +766,20 @@ var ProviderRegistry = class {
|
|
|
696
766
|
var TransferClient = class {
|
|
697
767
|
/** Provider registry used by this client. */
|
|
698
768
|
registry;
|
|
769
|
+
/** Execution defaults applied when call sites omit their own values. */
|
|
770
|
+
defaults;
|
|
699
771
|
logger;
|
|
700
772
|
/**
|
|
701
773
|
* Creates a transfer client without opening any provider connections.
|
|
702
774
|
*
|
|
703
|
-
* @param options - Optional registry, provider factories, and
|
|
775
|
+
* @param options - Optional registry, provider factories, logger, and execution defaults.
|
|
704
776
|
*/
|
|
705
777
|
constructor(options = {}) {
|
|
706
778
|
this.registry = options.registry ?? new ProviderRegistry();
|
|
707
779
|
this.logger = options.logger ?? noopLogger;
|
|
780
|
+
if (options.defaults !== void 0) {
|
|
781
|
+
this.defaults = { ...options.defaults };
|
|
782
|
+
}
|
|
708
783
|
for (const provider of options.providers ?? []) {
|
|
709
784
|
this.registry.register(provider);
|
|
710
785
|
}
|
|
@@ -1277,18 +1352,25 @@ var TransferEngine = class {
|
|
|
1277
1352
|
for (let attemptNumber = 1; attemptNumber <= maxAttempts; attemptNumber += 1) {
|
|
1278
1353
|
this.throwIfAborted(abortScope.signal, job);
|
|
1279
1354
|
const attemptStartedAt = this.now();
|
|
1355
|
+
const attemptScope = createAttemptScope(
|
|
1356
|
+
abortScope.signal,
|
|
1357
|
+
options.timeout,
|
|
1358
|
+
job,
|
|
1359
|
+
attemptNumber
|
|
1360
|
+
);
|
|
1280
1361
|
const context = this.createExecutionContext(
|
|
1281
1362
|
job,
|
|
1282
1363
|
attemptNumber,
|
|
1283
1364
|
attemptStartedAt,
|
|
1284
1365
|
options,
|
|
1285
|
-
|
|
1366
|
+
attemptScope.signal,
|
|
1286
1367
|
(bytesTransferred) => {
|
|
1287
1368
|
latestBytesTransferred = bytesTransferred;
|
|
1288
|
-
}
|
|
1369
|
+
},
|
|
1370
|
+
attemptScope.notifyProgress
|
|
1289
1371
|
);
|
|
1290
1372
|
try {
|
|
1291
|
-
const result = await runExecutor(executor, context,
|
|
1373
|
+
const result = await runExecutor(executor, context, attemptScope.signal, job);
|
|
1292
1374
|
context.throwIfAborted();
|
|
1293
1375
|
latestBytesTransferred = result.bytesTransferred;
|
|
1294
1376
|
const completedAt = this.now();
|
|
@@ -1306,16 +1388,27 @@ var TransferEngine = class {
|
|
|
1306
1388
|
summarizeError(error)
|
|
1307
1389
|
);
|
|
1308
1390
|
attempts.push(attempt);
|
|
1309
|
-
if (error instanceof AbortError ||
|
|
1391
|
+
if (error instanceof AbortError || abortScope.signal?.aborted === true) {
|
|
1310
1392
|
throw error;
|
|
1311
1393
|
}
|
|
1312
|
-
const retryInput = {
|
|
1394
|
+
const retryInput = {
|
|
1395
|
+
attempt: attemptNumber,
|
|
1396
|
+
elapsedMs: Math.max(0, completedAt.getTime() - startedAt.getTime()),
|
|
1397
|
+
error,
|
|
1398
|
+
job
|
|
1399
|
+
};
|
|
1313
1400
|
const shouldRetry = attemptNumber < maxAttempts && (options.retry?.shouldRetry?.(retryInput) ?? isRetryable(error));
|
|
1314
1401
|
if (shouldRetry) {
|
|
1315
1402
|
options.retry?.onRetry?.(retryInput);
|
|
1403
|
+
const delayMs = normalizeDelayMs(options.retry?.getDelayMs?.(retryInput));
|
|
1404
|
+
if (delayMs > 0) {
|
|
1405
|
+
await sleepWithAbort(delayMs, abortScope.signal, job);
|
|
1406
|
+
}
|
|
1316
1407
|
continue;
|
|
1317
1408
|
}
|
|
1318
1409
|
throw createTransferFailure(job, error, attempts);
|
|
1410
|
+
} finally {
|
|
1411
|
+
attemptScope.dispose();
|
|
1319
1412
|
}
|
|
1320
1413
|
}
|
|
1321
1414
|
throw createTransferFailure(job, void 0, attempts);
|
|
@@ -1323,12 +1416,13 @@ var TransferEngine = class {
|
|
|
1323
1416
|
abortScope.dispose();
|
|
1324
1417
|
}
|
|
1325
1418
|
}
|
|
1326
|
-
createExecutionContext(job, attempt, startedAt, options, signal, updateBytesTransferred) {
|
|
1419
|
+
createExecutionContext(job, attempt, startedAt, options, signal, updateBytesTransferred, notifyProgress) {
|
|
1327
1420
|
const context = {
|
|
1328
1421
|
attempt,
|
|
1329
1422
|
job,
|
|
1330
1423
|
reportProgress: (bytesTransferred, totalBytes) => {
|
|
1331
1424
|
this.throwIfAborted(signal, job);
|
|
1425
|
+
notifyProgress();
|
|
1332
1426
|
updateBytesTransferred(bytesTransferred);
|
|
1333
1427
|
const progressInput = {
|
|
1334
1428
|
bytesTransferred,
|
|
@@ -1397,6 +1491,96 @@ function createAbortScope(parentSignal, timeout, job) {
|
|
|
1397
1491
|
signal: controller.signal
|
|
1398
1492
|
};
|
|
1399
1493
|
}
|
|
1494
|
+
function createAttemptScope(parentSignal, timeout, job, attempt) {
|
|
1495
|
+
const attemptTimeoutMs = normalizeTimeoutMs(timeout?.attemptTimeoutMs);
|
|
1496
|
+
const stallTimeoutMs = normalizeTimeoutMs(timeout?.stallTimeoutMs);
|
|
1497
|
+
if (attemptTimeoutMs === void 0 && stallTimeoutMs === void 0) {
|
|
1498
|
+
const scope = {
|
|
1499
|
+
dispose: () => void 0,
|
|
1500
|
+
notifyProgress: () => void 0
|
|
1501
|
+
};
|
|
1502
|
+
if (parentSignal !== void 0) scope.signal = parentSignal;
|
|
1503
|
+
return scope;
|
|
1504
|
+
}
|
|
1505
|
+
const controller = new AbortController();
|
|
1506
|
+
const retryable = timeout?.retryable ?? true;
|
|
1507
|
+
const abortFromParent = () => controller.abort(parentSignal?.reason);
|
|
1508
|
+
if (parentSignal?.aborted === true) {
|
|
1509
|
+
abortFromParent();
|
|
1510
|
+
} else {
|
|
1511
|
+
parentSignal?.addEventListener("abort", abortFromParent, { once: true });
|
|
1512
|
+
}
|
|
1513
|
+
const attemptTimer = attemptTimeoutMs === void 0 ? void 0 : setTimeout(() => {
|
|
1514
|
+
controller.abort(
|
|
1515
|
+
new TimeoutError({
|
|
1516
|
+
details: { attempt, attemptTimeoutMs, jobId: job.id, operation: job.operation },
|
|
1517
|
+
message: `Transfer attempt ${String(attempt)} timed out after ${String(attemptTimeoutMs)}ms: ${job.id}`,
|
|
1518
|
+
retryable
|
|
1519
|
+
})
|
|
1520
|
+
);
|
|
1521
|
+
}, attemptTimeoutMs);
|
|
1522
|
+
let stallTimer;
|
|
1523
|
+
const armStallWatchdog = () => {
|
|
1524
|
+
if (stallTimeoutMs === void 0 || controller.signal.aborted) return;
|
|
1525
|
+
if (stallTimer !== void 0) clearTimeout(stallTimer);
|
|
1526
|
+
stallTimer = setTimeout(() => {
|
|
1527
|
+
controller.abort(
|
|
1528
|
+
new TimeoutError({
|
|
1529
|
+
details: { attempt, jobId: job.id, operation: job.operation, stallTimeoutMs },
|
|
1530
|
+
message: `Transfer attempt ${String(attempt)} stalled (no progress for ${String(stallTimeoutMs)}ms): ${job.id}`,
|
|
1531
|
+
retryable
|
|
1532
|
+
})
|
|
1533
|
+
);
|
|
1534
|
+
}, stallTimeoutMs);
|
|
1535
|
+
};
|
|
1536
|
+
armStallWatchdog();
|
|
1537
|
+
return {
|
|
1538
|
+
dispose: () => {
|
|
1539
|
+
if (attemptTimer !== void 0) clearTimeout(attemptTimer);
|
|
1540
|
+
if (stallTimer !== void 0) clearTimeout(stallTimer);
|
|
1541
|
+
parentSignal?.removeEventListener("abort", abortFromParent);
|
|
1542
|
+
},
|
|
1543
|
+
notifyProgress: armStallWatchdog,
|
|
1544
|
+
signal: controller.signal
|
|
1545
|
+
};
|
|
1546
|
+
}
|
|
1547
|
+
function sleepWithAbort(delayMs, signal, job) {
|
|
1548
|
+
return new Promise((resolve, reject) => {
|
|
1549
|
+
if (signal === void 0) {
|
|
1550
|
+
setTimeout(resolve, delayMs);
|
|
1551
|
+
return;
|
|
1552
|
+
}
|
|
1553
|
+
if (signal.aborted) {
|
|
1554
|
+
reject(toAbortFailure(signal, job));
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1557
|
+
const rejectAbort = () => {
|
|
1558
|
+
clearTimeout(timer);
|
|
1559
|
+
reject(toAbortFailure(signal, job));
|
|
1560
|
+
};
|
|
1561
|
+
const timer = setTimeout(() => {
|
|
1562
|
+
signal.removeEventListener("abort", rejectAbort);
|
|
1563
|
+
resolve();
|
|
1564
|
+
}, delayMs);
|
|
1565
|
+
signal.addEventListener("abort", rejectAbort, { once: true });
|
|
1566
|
+
});
|
|
1567
|
+
}
|
|
1568
|
+
function toAbortFailure(signal, job) {
|
|
1569
|
+
if (signal.reason instanceof ZeroTransferError) {
|
|
1570
|
+
return signal.reason;
|
|
1571
|
+
}
|
|
1572
|
+
return new AbortError({
|
|
1573
|
+
details: { jobId: job.id, operation: job.operation },
|
|
1574
|
+
message: `Transfer job aborted: ${job.id}`,
|
|
1575
|
+
retryable: false
|
|
1576
|
+
});
|
|
1577
|
+
}
|
|
1578
|
+
function normalizeDelayMs(value) {
|
|
1579
|
+
if (value === void 0 || !Number.isFinite(value) || value <= 0) {
|
|
1580
|
+
return 0;
|
|
1581
|
+
}
|
|
1582
|
+
return Math.floor(value);
|
|
1583
|
+
}
|
|
1400
1584
|
function normalizeTimeoutMs(value) {
|
|
1401
1585
|
if (value === void 0 || !Number.isFinite(value) || value <= 0) {
|
|
1402
1586
|
return void 0;
|
|
@@ -1565,7 +1749,7 @@ async function runRoute(options) {
|
|
|
1565
1749
|
const executor = createProviderTransferExecutor({
|
|
1566
1750
|
resolveSession: ({ role }) => sessions.get(role)
|
|
1567
1751
|
});
|
|
1568
|
-
return await engine.execute(job, executor, buildExecuteOptions(options));
|
|
1752
|
+
return await engine.execute(job, executor, buildExecuteOptions(options, client));
|
|
1569
1753
|
} finally {
|
|
1570
1754
|
if (destinationSession !== void 0) {
|
|
1571
1755
|
await destinationSession.disconnect();
|
|
@@ -1602,12 +1786,14 @@ function defaultJobId(route, now) {
|
|
|
1602
1786
|
const timestamp = (now?.() ?? /* @__PURE__ */ new Date()).getTime();
|
|
1603
1787
|
return `route:${route.id}:${timestamp.toString(36)}`;
|
|
1604
1788
|
}
|
|
1605
|
-
function buildExecuteOptions(options) {
|
|
1789
|
+
function buildExecuteOptions(options, client) {
|
|
1606
1790
|
const execute = {};
|
|
1791
|
+
const retry = options.retry ?? client.defaults?.retry;
|
|
1792
|
+
const timeout = options.timeout ?? client.defaults?.timeout;
|
|
1607
1793
|
if (options.signal !== void 0) execute.signal = options.signal;
|
|
1608
|
-
if (
|
|
1794
|
+
if (retry !== void 0) execute.retry = retry;
|
|
1609
1795
|
if (options.onProgress !== void 0) execute.onProgress = options.onProgress;
|
|
1610
|
-
if (
|
|
1796
|
+
if (timeout !== void 0) execute.timeout = timeout;
|
|
1611
1797
|
if (options.bandwidthLimit !== void 0) execute.bandwidthLimit = options.bandwidthLimit;
|
|
1612
1798
|
return execute;
|
|
1613
1799
|
}
|
|
@@ -1664,41 +1850,6 @@ function defaultRouteSuffix(source, destination) {
|
|
|
1664
1850
|
return `${source}->${destination}`;
|
|
1665
1851
|
}
|
|
1666
1852
|
|
|
1667
|
-
// src/logging/redaction.ts
|
|
1668
|
-
var REDACTED = "[REDACTED]";
|
|
1669
|
-
var SENSITIVE_KEY_PATTERN = /(?:password|passphrase|privatekey|token|secret|username|user)$/i;
|
|
1670
|
-
var SECRET_COMMAND_PATTERN = /^(PASS|USER|ACCT)\s+(.+)$/i;
|
|
1671
|
-
function isSensitiveKey(key) {
|
|
1672
|
-
return SENSITIVE_KEY_PATTERN.test(key.replace(/[_-]/g, ""));
|
|
1673
|
-
}
|
|
1674
|
-
function redactCommand(command) {
|
|
1675
|
-
return command.replace(SECRET_COMMAND_PATTERN, (_fullMatch, commandName) => {
|
|
1676
|
-
return `${commandName.toUpperCase()} ${REDACTED}`;
|
|
1677
|
-
});
|
|
1678
|
-
}
|
|
1679
|
-
function redactValue(value) {
|
|
1680
|
-
if (typeof value === "string") {
|
|
1681
|
-
return redactCommand(value);
|
|
1682
|
-
}
|
|
1683
|
-
if (Array.isArray(value)) {
|
|
1684
|
-
return value.map((item) => redactValue(item));
|
|
1685
|
-
}
|
|
1686
|
-
if (value !== null && typeof value === "object") {
|
|
1687
|
-
return redactObject(value);
|
|
1688
|
-
}
|
|
1689
|
-
return value;
|
|
1690
|
-
}
|
|
1691
|
-
function redactObject(input) {
|
|
1692
|
-
return Object.fromEntries(
|
|
1693
|
-
Object.entries(input).map(([key, value]) => {
|
|
1694
|
-
if (isSensitiveKey(key)) {
|
|
1695
|
-
return [key, REDACTED];
|
|
1696
|
-
}
|
|
1697
|
-
return [key, redactValue(value)];
|
|
1698
|
-
})
|
|
1699
|
-
);
|
|
1700
|
-
}
|
|
1701
|
-
|
|
1702
1853
|
// src/profiles/SecretSource.ts
|
|
1703
1854
|
var import_node_buffer2 = require("buffer");
|
|
1704
1855
|
var import_promises = require("fs/promises");
|
|
@@ -2070,11 +2221,11 @@ var import_promises2 = require("fs/promises");
|
|
|
2070
2221
|
var import_node_path2 = __toESM(require("path"));
|
|
2071
2222
|
|
|
2072
2223
|
// src/utils/path.ts
|
|
2073
|
-
var UNSAFE_FTP_ARGUMENT_PATTERN = /[\r\n]/;
|
|
2224
|
+
var UNSAFE_FTP_ARGUMENT_PATTERN = /[\r\n\0]/;
|
|
2074
2225
|
function assertSafeFtpArgument(value, label = "path") {
|
|
2075
2226
|
if (UNSAFE_FTP_ARGUMENT_PATTERN.test(value)) {
|
|
2076
2227
|
throw new ConfigurationError({
|
|
2077
|
-
message: `Unsafe FTP ${label}: CR and
|
|
2228
|
+
message: `Unsafe FTP ${label}: CR, LF, and NUL characters are not allowed`,
|
|
2078
2229
|
retryable: false,
|
|
2079
2230
|
details: {
|
|
2080
2231
|
label
|
|
@@ -3376,7 +3527,6 @@ function expandAlgorithms(values) {
|
|
|
3376
3527
|
}
|
|
3377
3528
|
|
|
3378
3529
|
// src/profiles/importers/FileZillaImporter.ts
|
|
3379
|
-
var import_node_buffer5 = require("buffer");
|
|
3380
3530
|
function importFileZillaSites(xml) {
|
|
3381
3531
|
const events = tokenizeXml(xml);
|
|
3382
3532
|
if (events.length === 0) {
|
|
@@ -3392,7 +3542,6 @@ function importFileZillaSites(xml) {
|
|
|
3392
3542
|
const folderNamePending = [];
|
|
3393
3543
|
let inServer = false;
|
|
3394
3544
|
let serverFields = {};
|
|
3395
|
-
let serverPasswordEncoding;
|
|
3396
3545
|
let activeTag;
|
|
3397
3546
|
let captureFolderName = false;
|
|
3398
3547
|
for (const event of events) {
|
|
@@ -3405,13 +3554,9 @@ function importFileZillaSites(xml) {
|
|
|
3405
3554
|
if (event.name === "Server") {
|
|
3406
3555
|
inServer = true;
|
|
3407
3556
|
serverFields = {};
|
|
3408
|
-
serverPasswordEncoding = void 0;
|
|
3409
3557
|
continue;
|
|
3410
3558
|
}
|
|
3411
3559
|
activeTag = event.name;
|
|
3412
|
-
if (event.name === "Pass" && inServer) {
|
|
3413
|
-
serverPasswordEncoding = event.attributes["encoding"];
|
|
3414
|
-
}
|
|
3415
3560
|
if (event.name === "Name" && !inServer && folderNamePending.length > 0) {
|
|
3416
3561
|
captureFolderName = true;
|
|
3417
3562
|
}
|
|
@@ -3437,7 +3582,7 @@ function importFileZillaSites(xml) {
|
|
|
3437
3582
|
}
|
|
3438
3583
|
if (event.name === "Server") {
|
|
3439
3584
|
const folder = folderStack.filter((segment) => segment !== "");
|
|
3440
|
-
const result = buildSiteFromFields(serverFields
|
|
3585
|
+
const result = buildSiteFromFields(serverFields);
|
|
3441
3586
|
if (result.kind === "site") {
|
|
3442
3587
|
sites.push({ ...result.site, folder });
|
|
3443
3588
|
} else {
|
|
@@ -3449,7 +3594,6 @@ function importFileZillaSites(xml) {
|
|
|
3449
3594
|
}
|
|
3450
3595
|
inServer = false;
|
|
3451
3596
|
serverFields = {};
|
|
3452
|
-
serverPasswordEncoding = void 0;
|
|
3453
3597
|
activeTag = void 0;
|
|
3454
3598
|
continue;
|
|
3455
3599
|
}
|
|
@@ -3458,7 +3602,7 @@ function importFileZillaSites(xml) {
|
|
|
3458
3602
|
}
|
|
3459
3603
|
return { sites, skipped };
|
|
3460
3604
|
}
|
|
3461
|
-
function buildSiteFromFields(fields
|
|
3605
|
+
function buildSiteFromFields(fields) {
|
|
3462
3606
|
const name = (fields["Name"] ?? fields["Host"] ?? "Untitled").trim();
|
|
3463
3607
|
const host = (fields["Host"] ?? "").trim();
|
|
3464
3608
|
if (host === "") return { kind: "skipped", name };
|
|
@@ -3477,18 +3621,9 @@ function buildSiteFromFields(fields, passwordEncoding) {
|
|
|
3477
3621
|
}
|
|
3478
3622
|
const user = fields["User"]?.trim();
|
|
3479
3623
|
if (user !== void 0 && user !== "") profile.username = { value: user };
|
|
3480
|
-
let password;
|
|
3481
3624
|
const rawPass = fields["Pass"];
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
password = import_node_buffer5.Buffer.from(rawPass, "base64").toString("utf8");
|
|
3485
|
-
} else {
|
|
3486
|
-
password = rawPass;
|
|
3487
|
-
}
|
|
3488
|
-
if (password !== void 0 && password !== "") profile.password = { value: password };
|
|
3489
|
-
}
|
|
3490
|
-
const site = { name, profile };
|
|
3491
|
-
if (password !== void 0) site.password = password;
|
|
3625
|
+
const hasStoredPassword = rawPass !== void 0 && rawPass !== "";
|
|
3626
|
+
const site = { hasStoredPassword, name, profile };
|
|
3492
3627
|
const logonText = fields["Logontype"];
|
|
3493
3628
|
if (logonText !== void 0) {
|
|
3494
3629
|
const logonType = Number.parseInt(logonText.trim(), 10);
|
|
@@ -3731,6 +3866,62 @@ function mapFtp550(details) {
|
|
|
3731
3866
|
return new PermissionDeniedError(details);
|
|
3732
3867
|
}
|
|
3733
3868
|
|
|
3869
|
+
// src/transfers/createDefaultRetryPolicy.ts
|
|
3870
|
+
var DEFAULT_MAX_ATTEMPTS = 4;
|
|
3871
|
+
var DEFAULT_BASE_DELAY_MS = 250;
|
|
3872
|
+
var DEFAULT_MAX_DELAY_MS = 3e4;
|
|
3873
|
+
var DEFAULT_MAX_ELAPSED_MS = 3e5;
|
|
3874
|
+
function createDefaultRetryPolicy(options = {}) {
|
|
3875
|
+
const maxAttempts = normalizePositiveInteger(options.maxAttempts, DEFAULT_MAX_ATTEMPTS);
|
|
3876
|
+
const baseDelayMs = normalizeNonNegative(options.baseDelayMs, DEFAULT_BASE_DELAY_MS);
|
|
3877
|
+
const maxDelayMs = normalizeNonNegative(options.maxDelayMs, DEFAULT_MAX_DELAY_MS);
|
|
3878
|
+
const maxElapsedMs = normalizeNonNegative(options.maxElapsedMs, DEFAULT_MAX_ELAPSED_MS);
|
|
3879
|
+
const random = options.random ?? Math.random;
|
|
3880
|
+
return {
|
|
3881
|
+
getDelayMs(input) {
|
|
3882
|
+
const retryAfterMs = readRetryAfterMs(input.error);
|
|
3883
|
+
if (retryAfterMs !== void 0) {
|
|
3884
|
+
return retryAfterMs;
|
|
3885
|
+
}
|
|
3886
|
+
const exponentialMs = baseDelayMs * 2 ** (input.attempt - 1);
|
|
3887
|
+
const cappedMs = Math.min(maxDelayMs, exponentialMs);
|
|
3888
|
+
return Math.floor(random() * cappedMs);
|
|
3889
|
+
},
|
|
3890
|
+
maxAttempts,
|
|
3891
|
+
shouldRetry(input) {
|
|
3892
|
+
if (!(input.error instanceof ZeroTransferError) || !input.error.retryable) {
|
|
3893
|
+
return false;
|
|
3894
|
+
}
|
|
3895
|
+
if (input.elapsedMs >= maxElapsedMs) {
|
|
3896
|
+
return false;
|
|
3897
|
+
}
|
|
3898
|
+
const retryAfterMs = readRetryAfterMs(input.error);
|
|
3899
|
+
if (retryAfterMs !== void 0 && input.elapsedMs + retryAfterMs > maxElapsedMs) {
|
|
3900
|
+
return false;
|
|
3901
|
+
}
|
|
3902
|
+
return true;
|
|
3903
|
+
}
|
|
3904
|
+
};
|
|
3905
|
+
}
|
|
3906
|
+
function readRetryAfterMs(error) {
|
|
3907
|
+
if (!(error instanceof ZeroTransferError)) return void 0;
|
|
3908
|
+
const value = error.details?.["retryAfterMs"];
|
|
3909
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return void 0;
|
|
3910
|
+
return Math.floor(value);
|
|
3911
|
+
}
|
|
3912
|
+
function normalizePositiveInteger(value, fallback) {
|
|
3913
|
+
if (value === void 0 || !Number.isFinite(value) || value < 1) {
|
|
3914
|
+
return fallback;
|
|
3915
|
+
}
|
|
3916
|
+
return Math.floor(value);
|
|
3917
|
+
}
|
|
3918
|
+
function normalizeNonNegative(value, fallback) {
|
|
3919
|
+
if (value === void 0 || !Number.isFinite(value) || value < 0) {
|
|
3920
|
+
return fallback;
|
|
3921
|
+
}
|
|
3922
|
+
return Math.floor(value);
|
|
3923
|
+
}
|
|
3924
|
+
|
|
3734
3925
|
// src/transfers/TransferPlan.ts
|
|
3735
3926
|
function createTransferPlan(input) {
|
|
3736
3927
|
const plan = {
|
|
@@ -3828,8 +4019,8 @@ var TransferQueue = class {
|
|
|
3828
4019
|
this.concurrency = normalizeConcurrency(options.concurrency);
|
|
3829
4020
|
this.defaultExecutor = options.executor;
|
|
3830
4021
|
this.resolveExecutor = options.resolveExecutor;
|
|
3831
|
-
this.retry = options.retry;
|
|
3832
|
-
this.timeout = options.timeout;
|
|
4022
|
+
this.retry = options.retry ?? options.client?.defaults?.retry;
|
|
4023
|
+
this.timeout = options.timeout ?? options.client?.defaults?.timeout;
|
|
3833
4024
|
this.bandwidthLimit = options.bandwidthLimit;
|
|
3834
4025
|
this.onProgress = options.onProgress;
|
|
3835
4026
|
this.onReceipt = options.onReceipt;
|
|
@@ -4906,10 +5097,30 @@ function isMainModule(importMetaUrl) {
|
|
|
4906
5097
|
}
|
|
4907
5098
|
|
|
4908
5099
|
// src/providers/web/WebDavProvider.ts
|
|
4909
|
-
var
|
|
5100
|
+
var import_node_buffer6 = require("buffer");
|
|
4910
5101
|
|
|
4911
5102
|
// src/providers/web/httpInternals.ts
|
|
4912
|
-
var
|
|
5103
|
+
var import_node_buffer5 = require("buffer");
|
|
5104
|
+
function assertHttpsEnforced(input) {
|
|
5105
|
+
if (input.enforceHttps && !input.secure) {
|
|
5106
|
+
throw new ConfigurationError({
|
|
5107
|
+
details: { provider: input.providerId },
|
|
5108
|
+
message: `Provider "${input.providerId}" is configured with enforceHttps but its transport is cleartext http; set secure: true (or drop enforceHttps to explicitly accept cleartext)`,
|
|
5109
|
+
retryable: false
|
|
5110
|
+
});
|
|
5111
|
+
}
|
|
5112
|
+
}
|
|
5113
|
+
var cleartextWarnedKeys = /* @__PURE__ */ new Set();
|
|
5114
|
+
function warnCleartextCredentials(input) {
|
|
5115
|
+
if (!input.hasCredentials) return;
|
|
5116
|
+
const key = `${input.providerId}:${input.host}`;
|
|
5117
|
+
if (cleartextWarnedKeys.has(key)) return;
|
|
5118
|
+
cleartextWarnedKeys.add(key);
|
|
5119
|
+
process.emitWarning(
|
|
5120
|
+
`Provider "${input.providerId}" is sending credentials to ${input.host} over cleartext http; use https or set enforceHttps to block this`,
|
|
5121
|
+
{ code: "ZERO_TRANSFER_CLEARTEXT_CREDENTIALS", type: "SecurityWarning" }
|
|
5122
|
+
);
|
|
5123
|
+
}
|
|
4913
5124
|
function buildBaseUrl(profile, options) {
|
|
4914
5125
|
const protocol = options.secure ? "https:" : "http:";
|
|
4915
5126
|
const portSegment = profile.port !== void 0 ? `:${profile.port}` : "";
|
|
@@ -4957,18 +5168,19 @@ async function dispatchRequest(options, url, init) {
|
|
|
4957
5168
|
signal: controller.signal
|
|
4958
5169
|
});
|
|
4959
5170
|
} catch (error) {
|
|
5171
|
+
const safeUrl = redactUrlForLogging(url);
|
|
4960
5172
|
if (controller.signal.aborted && upstreamSignal?.aborted !== true) {
|
|
4961
5173
|
throw new TimeoutError({
|
|
4962
5174
|
cause: error,
|
|
4963
|
-
details: { timeoutMs: options.timeoutMs, url:
|
|
4964
|
-
message: `HTTP request to ${
|
|
5175
|
+
details: { timeoutMs: options.timeoutMs, url: safeUrl },
|
|
5176
|
+
message: `HTTP request to ${safeUrl} timed out after ${String(options.timeoutMs)}ms`,
|
|
4965
5177
|
retryable: true
|
|
4966
5178
|
});
|
|
4967
5179
|
}
|
|
4968
5180
|
throw new ConnectionError({
|
|
4969
5181
|
cause: error,
|
|
4970
|
-
details: { url:
|
|
4971
|
-
message: `HTTP request to ${
|
|
5182
|
+
details: { url: safeUrl },
|
|
5183
|
+
message: `HTTP request to ${safeUrl} failed`,
|
|
4972
5184
|
retryable: true
|
|
4973
5185
|
});
|
|
4974
5186
|
} finally {
|
|
@@ -5000,8 +5212,48 @@ function formatRangeHeader(offset, length) {
|
|
|
5000
5212
|
const end = offset + length - 1;
|
|
5001
5213
|
return `bytes=${String(offset)}-${String(end)}`;
|
|
5002
5214
|
}
|
|
5003
|
-
|
|
5004
|
-
|
|
5215
|
+
var ERROR_BODY_EXCERPT_LIMIT = 2048;
|
|
5216
|
+
async function readErrorBodyExcerpt(response) {
|
|
5217
|
+
try {
|
|
5218
|
+
const text = await response.text();
|
|
5219
|
+
if (text.length === 0) return void 0;
|
|
5220
|
+
return text.length > ERROR_BODY_EXCERPT_LIMIT ? `${text.slice(0, ERROR_BODY_EXCERPT_LIMIT)}... [truncated]` : text;
|
|
5221
|
+
} catch {
|
|
5222
|
+
return void 0;
|
|
5223
|
+
}
|
|
5224
|
+
}
|
|
5225
|
+
function parseRetryAfterMs(value, now = Date.now) {
|
|
5226
|
+
if (value === null) return void 0;
|
|
5227
|
+
const trimmed = value.trim();
|
|
5228
|
+
if (trimmed.length === 0) return void 0;
|
|
5229
|
+
if (/^\d+$/.test(trimmed)) {
|
|
5230
|
+
const seconds = Number.parseInt(trimmed, 10);
|
|
5231
|
+
return Number.isFinite(seconds) ? seconds * 1e3 : void 0;
|
|
5232
|
+
}
|
|
5233
|
+
if (!/[A-Za-z]/.test(trimmed)) return void 0;
|
|
5234
|
+
const retryAt = Date.parse(trimmed);
|
|
5235
|
+
if (Number.isNaN(retryAt)) return void 0;
|
|
5236
|
+
return Math.max(0, retryAt - now());
|
|
5237
|
+
}
|
|
5238
|
+
async function mapResponseErrorWithBody(response, path2) {
|
|
5239
|
+
return mapResponseError(response, path2, await readErrorBodyExcerpt(response));
|
|
5240
|
+
}
|
|
5241
|
+
function mapResponseError(response, path2, bodyExcerpt) {
|
|
5242
|
+
const details = {
|
|
5243
|
+
path: path2,
|
|
5244
|
+
status: response.status,
|
|
5245
|
+
statusText: response.statusText
|
|
5246
|
+
};
|
|
5247
|
+
if (bodyExcerpt !== void 0) details["body"] = bodyExcerpt;
|
|
5248
|
+
if (response.status === 429 || response.status === 503) {
|
|
5249
|
+
const retryAfterMs = parseRetryAfterMs(response.headers.get("retry-after"));
|
|
5250
|
+
if (retryAfterMs !== void 0) details["retryAfterMs"] = retryAfterMs;
|
|
5251
|
+
return new ConnectionError({
|
|
5252
|
+
details,
|
|
5253
|
+
message: response.status === 429 ? `HTTP request for ${path2} was rate limited (429)` : `HTTP service unavailable for ${path2} (503)`,
|
|
5254
|
+
retryable: true
|
|
5255
|
+
});
|
|
5256
|
+
}
|
|
5005
5257
|
if (response.status === 401) {
|
|
5006
5258
|
return new AuthenticationError({
|
|
5007
5259
|
details,
|
|
@@ -5033,18 +5285,58 @@ async function* webStreamToAsyncIterable(body) {
|
|
|
5033
5285
|
const reader = body.getReader();
|
|
5034
5286
|
try {
|
|
5035
5287
|
while (true) {
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5288
|
+
let result;
|
|
5289
|
+
try {
|
|
5290
|
+
result = await reader.read();
|
|
5291
|
+
} catch (error) {
|
|
5292
|
+
if (error instanceof ZeroTransferError) throw error;
|
|
5293
|
+
throw new ConnectionError({
|
|
5294
|
+
cause: error,
|
|
5295
|
+
message: "HTTP response stream was interrupted before completion",
|
|
5296
|
+
retryable: true
|
|
5297
|
+
});
|
|
5298
|
+
}
|
|
5299
|
+
if (result.done) break;
|
|
5300
|
+
if (result.value !== void 0) yield result.value;
|
|
5039
5301
|
}
|
|
5040
5302
|
} finally {
|
|
5041
5303
|
reader.releaseLock();
|
|
5042
5304
|
}
|
|
5043
5305
|
}
|
|
5306
|
+
function asyncIterableToReadableStream(source, onChunk) {
|
|
5307
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
5308
|
+
return new ReadableStream({
|
|
5309
|
+
async pull(controller) {
|
|
5310
|
+
try {
|
|
5311
|
+
const next = await iterator.next();
|
|
5312
|
+
if (next.done === true) {
|
|
5313
|
+
controller.close();
|
|
5314
|
+
return;
|
|
5315
|
+
}
|
|
5316
|
+
const chunk = next.value;
|
|
5317
|
+
if (chunk.byteLength === 0) {
|
|
5318
|
+
return;
|
|
5319
|
+
}
|
|
5320
|
+
controller.enqueue(chunk);
|
|
5321
|
+
onChunk(chunk);
|
|
5322
|
+
} catch (error) {
|
|
5323
|
+
controller.error(error);
|
|
5324
|
+
}
|
|
5325
|
+
},
|
|
5326
|
+
async cancel(reason) {
|
|
5327
|
+
if (typeof iterator.return === "function") {
|
|
5328
|
+
try {
|
|
5329
|
+
await iterator.return(reason);
|
|
5330
|
+
} catch {
|
|
5331
|
+
}
|
|
5332
|
+
}
|
|
5333
|
+
}
|
|
5334
|
+
});
|
|
5335
|
+
}
|
|
5044
5336
|
function secretToString(value) {
|
|
5045
5337
|
if (typeof value === "string") return value;
|
|
5046
|
-
if (value instanceof Uint8Array ||
|
|
5047
|
-
return
|
|
5338
|
+
if (value instanceof Uint8Array || import_node_buffer5.Buffer.isBuffer(value)) {
|
|
5339
|
+
return import_node_buffer5.Buffer.from(value).toString("utf8");
|
|
5048
5340
|
}
|
|
5049
5341
|
return String(value);
|
|
5050
5342
|
}
|
|
@@ -5056,7 +5348,8 @@ function createWebDavProviderFactory(options = {}) {
|
|
|
5056
5348
|
const secure = options.secure ?? false;
|
|
5057
5349
|
const basePath = options.basePath ?? "";
|
|
5058
5350
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
5059
|
-
const uploadStreaming = options.uploadStreaming ?? "
|
|
5351
|
+
const uploadStreaming = options.uploadStreaming ?? "always";
|
|
5352
|
+
assertHttpsEnforced({ enforceHttps: options.enforceHttps ?? false, providerId: id, secure });
|
|
5060
5353
|
if (typeof fetchImpl !== "function") {
|
|
5061
5354
|
throw new ConfigurationError({
|
|
5062
5355
|
message: "Global fetch is unavailable; supply WebDavProviderOptions.fetch explicitly",
|
|
@@ -5108,13 +5401,20 @@ var WebDavProvider = class {
|
|
|
5108
5401
|
id;
|
|
5109
5402
|
capabilities;
|
|
5110
5403
|
async connect(profile) {
|
|
5404
|
+
if (!this.internals.secure) {
|
|
5405
|
+
warnCleartextCredentials({
|
|
5406
|
+
hasCredentials: profile.username !== void 0 || profile.password !== void 0,
|
|
5407
|
+
host: profile.host,
|
|
5408
|
+
providerId: this.internals.id
|
|
5409
|
+
});
|
|
5410
|
+
}
|
|
5111
5411
|
const headers = { ...this.internals.defaultHeaders };
|
|
5112
5412
|
if (profile.username !== void 0) {
|
|
5113
5413
|
const username = await resolveSecret(profile.username);
|
|
5114
5414
|
const password = profile.password !== void 0 ? await resolveSecret(profile.password) : "";
|
|
5115
5415
|
const usernameText = secretToString(username);
|
|
5116
5416
|
const passwordText = secretToString(password);
|
|
5117
|
-
headers["Authorization"] = `Basic ${
|
|
5417
|
+
headers["Authorization"] = `Basic ${import_node_buffer6.Buffer.from(`${usernameText}:${passwordText}`).toString(
|
|
5118
5418
|
"base64"
|
|
5119
5419
|
)}`;
|
|
5120
5420
|
}
|
|
@@ -5162,7 +5462,7 @@ var WebDavFileSystem = class {
|
|
|
5162
5462
|
method: "PROPFIND"
|
|
5163
5463
|
});
|
|
5164
5464
|
if (!response.ok && response.status !== 207) {
|
|
5165
|
-
throw
|
|
5465
|
+
throw await mapResponseErrorWithBody(response, normalized);
|
|
5166
5466
|
}
|
|
5167
5467
|
const body = await response.text();
|
|
5168
5468
|
const entries = parsePropfindResponses(body, this.options.baseUrl);
|
|
@@ -5176,7 +5476,7 @@ var WebDavFileSystem = class {
|
|
|
5176
5476
|
method: "PROPFIND"
|
|
5177
5477
|
});
|
|
5178
5478
|
if (!response.ok && response.status !== 207) {
|
|
5179
|
-
throw
|
|
5479
|
+
throw await mapResponseErrorWithBody(response, normalized);
|
|
5180
5480
|
}
|
|
5181
5481
|
const body = await response.text();
|
|
5182
5482
|
const entries = parsePropfindResponses(body, this.options.baseUrl);
|
|
@@ -5221,12 +5521,12 @@ var WebDavTransferOperations = class {
|
|
|
5221
5521
|
if (request.signal !== void 0) init.signal = request.signal;
|
|
5222
5522
|
const response = await dispatchRequest(this.options, url, init);
|
|
5223
5523
|
if (!response.ok && response.status !== 206) {
|
|
5224
|
-
throw
|
|
5524
|
+
throw await mapResponseErrorWithBody(response, normalized);
|
|
5225
5525
|
}
|
|
5226
5526
|
const body = response.body;
|
|
5227
5527
|
if (body === null) {
|
|
5228
5528
|
throw new ConnectionError({
|
|
5229
|
-
message: `WebDAV response had no body for ${url
|
|
5529
|
+
message: `WebDAV response had no body for ${redactUrlForLogging(url)}`,
|
|
5230
5530
|
retryable: true
|
|
5231
5531
|
});
|
|
5232
5532
|
}
|
|
@@ -5270,7 +5570,7 @@ var WebDavTransferOperations = class {
|
|
|
5270
5570
|
if (request.signal !== void 0) init2.signal = request.signal;
|
|
5271
5571
|
const response2 = await dispatchRequest(this.options, url, init2);
|
|
5272
5572
|
if (!response2.ok) {
|
|
5273
|
-
throw
|
|
5573
|
+
throw await mapResponseErrorWithBody(response2, normalized);
|
|
5274
5574
|
}
|
|
5275
5575
|
request.reportProgress(buffered.byteLength, buffered.byteLength);
|
|
5276
5576
|
const result2 = {
|
|
@@ -5306,7 +5606,7 @@ var WebDavTransferOperations = class {
|
|
|
5306
5606
|
if (request.signal !== void 0) init.signal = request.signal;
|
|
5307
5607
|
const response = await dispatchRequest(this.options, url, init);
|
|
5308
5608
|
if (!response.ok) {
|
|
5309
|
-
throw
|
|
5609
|
+
throw await mapResponseErrorWithBody(response, normalized);
|
|
5310
5610
|
}
|
|
5311
5611
|
const result = {
|
|
5312
5612
|
bytesTransferred,
|
|
@@ -5332,36 +5632,6 @@ async function collectChunks(source) {
|
|
|
5332
5632
|
}
|
|
5333
5633
|
return out;
|
|
5334
5634
|
}
|
|
5335
|
-
function asyncIterableToReadableStream(source, onChunk) {
|
|
5336
|
-
const iterator = source[Symbol.asyncIterator]();
|
|
5337
|
-
return new ReadableStream({
|
|
5338
|
-
async pull(controller) {
|
|
5339
|
-
try {
|
|
5340
|
-
const next = await iterator.next();
|
|
5341
|
-
if (next.done === true) {
|
|
5342
|
-
controller.close();
|
|
5343
|
-
return;
|
|
5344
|
-
}
|
|
5345
|
-
const chunk = next.value;
|
|
5346
|
-
if (chunk.byteLength === 0) {
|
|
5347
|
-
return;
|
|
5348
|
-
}
|
|
5349
|
-
controller.enqueue(chunk);
|
|
5350
|
-
onChunk(chunk);
|
|
5351
|
-
} catch (error) {
|
|
5352
|
-
controller.error(error);
|
|
5353
|
-
}
|
|
5354
|
-
},
|
|
5355
|
-
async cancel(reason) {
|
|
5356
|
-
if (typeof iterator.return === "function") {
|
|
5357
|
-
try {
|
|
5358
|
-
await iterator.return(reason);
|
|
5359
|
-
} catch {
|
|
5360
|
-
}
|
|
5361
|
-
}
|
|
5362
|
-
}
|
|
5363
|
-
});
|
|
5364
|
-
}
|
|
5365
5635
|
function parsePropfindResponses(xml, baseUrl) {
|
|
5366
5636
|
const entries = [];
|
|
5367
5637
|
const responseRegex = /<(?:[a-zA-Z0-9-]+:)?response\b[^>]*>([\s\S]*?)<\/(?:[a-zA-Z0-9-]+:)?response>/gi;
|
|
@@ -5472,6 +5742,7 @@ function parentOf(path2) {
|
|
|
5472
5742
|
copyBetween,
|
|
5473
5743
|
createAtomicDeployPlan,
|
|
5474
5744
|
createBandwidthThrottle,
|
|
5745
|
+
createDefaultRetryPolicy,
|
|
5475
5746
|
createLocalProviderFactory,
|
|
5476
5747
|
createMemoryProviderFactory,
|
|
5477
5748
|
createOAuthTokenSecretSource,
|
|
@@ -5508,8 +5779,10 @@ function parentOf(path2) {
|
|
|
5508
5779
|
parseRemoteManifest,
|
|
5509
5780
|
redactCommand,
|
|
5510
5781
|
redactConnectionProfile,
|
|
5782
|
+
redactErrorForLogging,
|
|
5511
5783
|
redactObject,
|
|
5512
5784
|
redactSecretSource,
|
|
5785
|
+
redactUrlForLogging,
|
|
5513
5786
|
redactValue,
|
|
5514
5787
|
resolveConnectionProfileSecrets,
|
|
5515
5788
|
resolveOpenSshHost,
|