@zero-transfer/sdk 0.1.0-alpha.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +182 -213
- package/assets/zero-transfer-logo.svg +201 -201
- package/dist/index.cjs +12 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +309 -4
- package/dist/index.d.ts +309 -4
- package/dist/index.mjs +11 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +16 -4
- package/CHANGELOG.md +0 -177
package/dist/index.d.ts
CHANGED
|
@@ -375,7 +375,17 @@ interface TlsProfile {
|
|
|
375
375
|
minVersion?: SecureVersion;
|
|
376
376
|
/** Maximum TLS protocol version accepted by the client. */
|
|
377
377
|
maxVersion?: SecureVersion;
|
|
378
|
-
/**
|
|
378
|
+
/**
|
|
379
|
+
* Optional. Expected server certificate SHA-256 fingerprint(s) for **certificate pinning**, in
|
|
380
|
+
* hex form with or without colons. When present, the TLS handshake additionally requires the
|
|
381
|
+
* leaf certificate's SHA-256 fingerprint to match one of these values.
|
|
382
|
+
*
|
|
383
|
+
* Not required for normal CA-trusted endpoints — public CAs and `ca` bundles already gate
|
|
384
|
+
* trust via `rejectUnauthorized`. Pinning is **recommended for production** when you control
|
|
385
|
+
* the server and want defence-in-depth against rogue certificates issued by trusted CAs.
|
|
386
|
+
*
|
|
387
|
+
* @example "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99"
|
|
388
|
+
*/
|
|
379
389
|
pinnedFingerprint256?: string | readonly string[];
|
|
380
390
|
/** Optional custom server identity checker for private PKI or certificate pinning. */
|
|
381
391
|
checkServerIdentity?: (host: string, cert: PeerCertificate) => Error | undefined;
|
|
@@ -395,9 +405,25 @@ interface SshProfile {
|
|
|
395
405
|
privateKey?: SecretSource;
|
|
396
406
|
/** Passphrase used to decrypt an encrypted private key. */
|
|
397
407
|
passphrase?: SecretSource;
|
|
398
|
-
/**
|
|
408
|
+
/**
|
|
409
|
+
* Optional. OpenSSH `known_hosts` content used for **strict SFTP host-key verification**.
|
|
410
|
+
* Mutually exclusive with provider-level `hostHash`/`hostVerifier` options.
|
|
411
|
+
*
|
|
412
|
+
* Not required for the connection to succeed, but **strongly recommended for production**:
|
|
413
|
+
* without `knownHosts` (and without {@link SshProfile.pinnedHostKeySha256 | pinnedHostKeySha256}),
|
|
414
|
+
* the SSH session accepts any host key the server presents, leaving you exposed to MITM.
|
|
415
|
+
*/
|
|
399
416
|
knownHosts?: SshKnownHostsSource;
|
|
400
|
-
/**
|
|
417
|
+
/**
|
|
418
|
+
* Optional. SSH host-key SHA-256 fingerprint(s) the remote must present, in OpenSSH
|
|
419
|
+
* `SHA256:<base64>` form, raw base64, or hex.
|
|
420
|
+
*
|
|
421
|
+
* Use this as a lighter-weight alternative to a full `known_hosts` file when you only need
|
|
422
|
+
* to pin a single host. Like `knownHosts`, it is **optional but recommended for production**;
|
|
423
|
+
* leaving both unset disables host-key verification entirely.
|
|
424
|
+
*
|
|
425
|
+
* @example "SHA256:abc123basesixfourpinFromKnownHosts="
|
|
426
|
+
*/
|
|
401
427
|
pinnedHostKeySha256?: string | readonly string[];
|
|
402
428
|
/** Runtime callback that answers SSH keyboard-interactive authentication prompts. */
|
|
403
429
|
keyboardInteractive?: SshKeyboardInteractiveHandler;
|
|
@@ -406,6 +432,46 @@ interface SshProfile {
|
|
|
406
432
|
}
|
|
407
433
|
/**
|
|
408
434
|
* Connection settings accepted by facade and adapter implementations.
|
|
435
|
+
*
|
|
436
|
+
* Every `ConnectionProfile` has a `host` and a `provider` (or `protocol`).
|
|
437
|
+
* Authentication and transport-specific material is layered on via the
|
|
438
|
+
* optional `ssh`, `tls`, `oauth`, and provider-specific blocks (e.g. `s3`,
|
|
439
|
+
* `azure`, `dropbox`).
|
|
440
|
+
*
|
|
441
|
+
* @example SFTP with public-key auth
|
|
442
|
+
* ```ts
|
|
443
|
+
* const profile: ConnectionProfile = {
|
|
444
|
+
* host: "sftp.example.com",
|
|
445
|
+
* provider: "sftp",
|
|
446
|
+
* username: "deploy",
|
|
447
|
+
* ssh: {
|
|
448
|
+
* privateKey: { path: "./keys/id_ed25519" },
|
|
449
|
+
* pinnedHostKeySha256: "SHA256:abc123basesixfourpinFromKnownHosts=",
|
|
450
|
+
* },
|
|
451
|
+
* };
|
|
452
|
+
* ```
|
|
453
|
+
*
|
|
454
|
+
* @example FTPS with username/password and public-CA TLS
|
|
455
|
+
* ```ts
|
|
456
|
+
* const profile: ConnectionProfile = {
|
|
457
|
+
* host: "ftps.example.com",
|
|
458
|
+
* provider: "ftps",
|
|
459
|
+
* username: "deploy",
|
|
460
|
+
* password: { env: "FTPS_PASSWORD" },
|
|
461
|
+
* tls: { minVersion: "TLSv1.2" },
|
|
462
|
+
* };
|
|
463
|
+
* ```
|
|
464
|
+
*
|
|
465
|
+
* @example S3-compatible
|
|
466
|
+
* ```ts
|
|
467
|
+
* const profile: ConnectionProfile = {
|
|
468
|
+
* host: "my-bucket",
|
|
469
|
+
* provider: "s3",
|
|
470
|
+
* username: process.env.AWS_ACCESS_KEY_ID,
|
|
471
|
+
* password: { env: "AWS_SECRET_ACCESS_KEY" },
|
|
472
|
+
* s3: { region: "us-east-1" },
|
|
473
|
+
* };
|
|
474
|
+
* ```
|
|
409
475
|
*/
|
|
410
476
|
interface ConnectionProfile {
|
|
411
477
|
/** Provider to use for this connection. Prefer this over the compatibility protocol field. */
|
|
@@ -982,8 +1048,50 @@ declare class TransferClient {
|
|
|
982
1048
|
/**
|
|
983
1049
|
* Creates a provider-neutral transfer client.
|
|
984
1050
|
*
|
|
1051
|
+
* The returned client owns a registry of provider factories and produces
|
|
1052
|
+
* `TransferSession` instances on demand via {@link TransferClient.connect}.
|
|
1053
|
+
* Registering only the providers you actually use keeps bundle size small
|
|
1054
|
+
* (each factory pulls in its own SDK dependencies).
|
|
1055
|
+
*
|
|
985
1056
|
* @param options - Optional registry, provider factories, and logger.
|
|
986
1057
|
* @returns A disconnected {@link TransferClient} instance.
|
|
1058
|
+
*
|
|
1059
|
+
* @example Multi-provider client
|
|
1060
|
+
* ```ts
|
|
1061
|
+
* import {
|
|
1062
|
+
* createS3ProviderFactory,
|
|
1063
|
+
* createSftpProviderFactory,
|
|
1064
|
+
* createTransferClient,
|
|
1065
|
+
* } from "@zero-transfer/sdk";
|
|
1066
|
+
*
|
|
1067
|
+
* const client = createTransferClient({
|
|
1068
|
+
* providers: [createSftpProviderFactory(), createS3ProviderFactory()],
|
|
1069
|
+
* });
|
|
1070
|
+
*
|
|
1071
|
+
* const session = await client.connect({
|
|
1072
|
+
* host: "sftp.example.com",
|
|
1073
|
+
* provider: "sftp",
|
|
1074
|
+
* username: "deploy",
|
|
1075
|
+
* ssh: { privateKey: { path: "./keys/id_ed25519" } },
|
|
1076
|
+
* });
|
|
1077
|
+
* try {
|
|
1078
|
+
* const list = await session.fs.list("/uploads");
|
|
1079
|
+
* console.log(list);
|
|
1080
|
+
* } finally {
|
|
1081
|
+
* await session.disconnect();
|
|
1082
|
+
* }
|
|
1083
|
+
* ```
|
|
1084
|
+
*
|
|
1085
|
+
* @example Friendly one-shot helpers
|
|
1086
|
+
* ```ts
|
|
1087
|
+
* import { uploadFile } from "@zero-transfer/sdk";
|
|
1088
|
+
*
|
|
1089
|
+
* await uploadFile({
|
|
1090
|
+
* client,
|
|
1091
|
+
* destination: { path: "/uploads/report.csv", profile },
|
|
1092
|
+
* localPath: "./out/report.csv",
|
|
1093
|
+
* });
|
|
1094
|
+
* ```
|
|
987
1095
|
*/
|
|
988
1096
|
declare function createTransferClient(options?: TransferClientOptions): TransferClient;
|
|
989
1097
|
|
|
@@ -1280,8 +1388,37 @@ interface UploadFileOptions extends FriendlyTransferOptions {
|
|
|
1280
1388
|
/**
|
|
1281
1389
|
* Uploads a single local file to a remote endpoint.
|
|
1282
1390
|
*
|
|
1391
|
+
* The remote provider is resolved from `destination.profile.provider`, so any
|
|
1392
|
+
* provider factory you registered with {@link createTransferClient} can be used
|
|
1393
|
+
* as the destination.
|
|
1394
|
+
*
|
|
1283
1395
|
* @param options - Friendly upload options.
|
|
1284
1396
|
* @returns Receipt produced by the underlying transfer engine.
|
|
1397
|
+
*
|
|
1398
|
+
* @example Upload to SFTP with public-key auth
|
|
1399
|
+
* ```ts
|
|
1400
|
+
* import {
|
|
1401
|
+
* createSftpProviderFactory,
|
|
1402
|
+
* createTransferClient,
|
|
1403
|
+
* uploadFile,
|
|
1404
|
+
* } from "@zero-transfer/sdk";
|
|
1405
|
+
*
|
|
1406
|
+
* const client = createTransferClient({ providers: [createSftpProviderFactory()] });
|
|
1407
|
+
*
|
|
1408
|
+
* await uploadFile({
|
|
1409
|
+
* client,
|
|
1410
|
+
* destination: {
|
|
1411
|
+
* path: "/uploads/report.csv",
|
|
1412
|
+
* profile: {
|
|
1413
|
+
* host: "sftp.example.com",
|
|
1414
|
+
* provider: "sftp",
|
|
1415
|
+
* username: "deploy",
|
|
1416
|
+
* ssh: { privateKey: { path: "./keys/id_ed25519" } },
|
|
1417
|
+
* },
|
|
1418
|
+
* },
|
|
1419
|
+
* localPath: "./out/report.csv",
|
|
1420
|
+
* });
|
|
1421
|
+
* ```
|
|
1285
1422
|
*/
|
|
1286
1423
|
declare function uploadFile(options: UploadFileOptions): Promise<TransferReceipt>;
|
|
1287
1424
|
/** Options for {@link downloadFile}. */
|
|
@@ -1296,8 +1433,35 @@ interface DownloadFileOptions extends FriendlyTransferOptions {
|
|
|
1296
1433
|
/**
|
|
1297
1434
|
* Downloads a single remote file to a local path.
|
|
1298
1435
|
*
|
|
1436
|
+
* The remote provider is resolved from `source.profile.provider`. The local
|
|
1437
|
+
* destination path is created (including parent directories) on demand.
|
|
1438
|
+
*
|
|
1299
1439
|
* @param options - Friendly download options.
|
|
1300
1440
|
* @returns Receipt produced by the underlying transfer engine.
|
|
1441
|
+
*
|
|
1442
|
+
* @example Download from S3
|
|
1443
|
+
* ```ts
|
|
1444
|
+
* import {
|
|
1445
|
+
* createS3ProviderFactory,
|
|
1446
|
+
* createTransferClient,
|
|
1447
|
+
* downloadFile,
|
|
1448
|
+
* } from "@zero-transfer/sdk";
|
|
1449
|
+
*
|
|
1450
|
+
* const client = createTransferClient({ providers: [createS3ProviderFactory()] });
|
|
1451
|
+
*
|
|
1452
|
+
* await downloadFile({
|
|
1453
|
+
* client,
|
|
1454
|
+
* localPath: "./tmp/snapshot.tar.gz",
|
|
1455
|
+
* source: {
|
|
1456
|
+
* path: "snapshots/2026-04-28/snapshot.tar.gz",
|
|
1457
|
+
* profile: {
|
|
1458
|
+
* host: "snapshots", // S3 bucket
|
|
1459
|
+
* provider: "s3",
|
|
1460
|
+
* s3: { region: "us-east-1" },
|
|
1461
|
+
* },
|
|
1462
|
+
* },
|
|
1463
|
+
* });
|
|
1464
|
+
* ```
|
|
1301
1465
|
*/
|
|
1302
1466
|
declare function downloadFile(options: DownloadFileOptions): Promise<TransferReceipt>;
|
|
1303
1467
|
/** Options for {@link copyBetween}. */
|
|
@@ -1312,8 +1476,38 @@ interface CopyBetweenOptions extends FriendlyTransferOptions {
|
|
|
1312
1476
|
/**
|
|
1313
1477
|
* Copies a file between two remote endpoints in a single call.
|
|
1314
1478
|
*
|
|
1479
|
+
* Both source and destination providers must be registered with the
|
|
1480
|
+
* {@link TransferClient}. Streams are piped end-to-end without staging the file
|
|
1481
|
+
* on the local disk.
|
|
1482
|
+
*
|
|
1315
1483
|
* @param options - Friendly copy options.
|
|
1316
1484
|
* @returns Receipt produced by the underlying transfer engine.
|
|
1485
|
+
*
|
|
1486
|
+
* @example Copy from SFTP to S3
|
|
1487
|
+
* ```ts
|
|
1488
|
+
* import {
|
|
1489
|
+
* copyBetween,
|
|
1490
|
+
* createS3ProviderFactory,
|
|
1491
|
+
* createSftpProviderFactory,
|
|
1492
|
+
* createTransferClient,
|
|
1493
|
+
* } from "@zero-transfer/sdk";
|
|
1494
|
+
*
|
|
1495
|
+
* const client = createTransferClient({
|
|
1496
|
+
* providers: [createSftpProviderFactory(), createS3ProviderFactory()],
|
|
1497
|
+
* });
|
|
1498
|
+
*
|
|
1499
|
+
* await copyBetween({
|
|
1500
|
+
* client,
|
|
1501
|
+
* source: {
|
|
1502
|
+
* path: "/exports/daily.csv",
|
|
1503
|
+
* profile: { host: "sftp.example.com", provider: "sftp", username: "etl" },
|
|
1504
|
+
* },
|
|
1505
|
+
* destination: {
|
|
1506
|
+
* path: "warehouse/daily.csv",
|
|
1507
|
+
* profile: { host: "warehouse", provider: "s3", s3: { region: "us-east-1" } },
|
|
1508
|
+
* },
|
|
1509
|
+
* });
|
|
1510
|
+
* ```
|
|
1317
1511
|
*/
|
|
1318
1512
|
declare function copyBetween(options: CopyBetweenOptions): Promise<TransferReceipt>;
|
|
1319
1513
|
|
|
@@ -1444,8 +1638,24 @@ interface LocalProviderOptions {
|
|
|
1444
1638
|
/**
|
|
1445
1639
|
* Creates a provider factory backed by the local filesystem.
|
|
1446
1640
|
*
|
|
1641
|
+
* Useful for copying files between two remote endpoints via a local staging
|
|
1642
|
+
* area, or as the destination for `downloadFile`. The friendly `uploadFile`
|
|
1643
|
+
* helper registers a local provider implicitly.
|
|
1644
|
+
*
|
|
1447
1645
|
* @param options - Optional local root path exposed through provider sessions.
|
|
1448
1646
|
* @returns Provider factory suitable for `createTransferClient({ providers: [...] })`.
|
|
1647
|
+
*
|
|
1648
|
+
* @example Use a fixed root directory
|
|
1649
|
+
* ```ts
|
|
1650
|
+
* import { createLocalProviderFactory, createTransferClient } from "@zero-transfer/sdk";
|
|
1651
|
+
*
|
|
1652
|
+
* const client = createTransferClient({
|
|
1653
|
+
* providers: [createLocalProviderFactory({ rootPath: "/var/lib/zt-staging" })],
|
|
1654
|
+
* });
|
|
1655
|
+
*
|
|
1656
|
+
* const session = await client.connect({ host: "staging", provider: "local" });
|
|
1657
|
+
* const list = await session.fs.list("/");
|
|
1658
|
+
* ```
|
|
1449
1659
|
*/
|
|
1450
1660
|
declare function createLocalProviderFactory(options?: LocalProviderOptions): ProviderFactory;
|
|
1451
1661
|
|
|
@@ -1692,7 +1902,7 @@ interface S3MultipartPart {
|
|
|
1692
1902
|
* Persistence contract for resuming partial multipart uploads across
|
|
1693
1903
|
* processes or retries. Implementations may be synchronous or asynchronous;
|
|
1694
1904
|
* `clear` is invoked once the multipart upload completes successfully (or is
|
|
1695
|
-
* explicitly aborted
|
|
1905
|
+
* explicitly aborted).
|
|
1696
1906
|
*/
|
|
1697
1907
|
interface S3MultipartResumeStore {
|
|
1698
1908
|
load(key: S3MultipartResumeKey): Promise<S3MultipartCheckpoint | undefined> | S3MultipartCheckpoint | undefined;
|
|
@@ -1707,6 +1917,34 @@ declare function createMemoryS3MultipartResumeStore(): S3MultipartResumeStore;
|
|
|
1707
1917
|
* Credentials must be supplied via the connection profile: `username` is the
|
|
1708
1918
|
* access key id and `password` is the secret access key. `profile.host` may
|
|
1709
1919
|
* be set to the bucket name (taking precedence over `options.bucket`).
|
|
1920
|
+
*
|
|
1921
|
+
* Works with AWS S3 and any S3-compatible API (MinIO, Cloudflare R2,
|
|
1922
|
+
* Backblaze B2, DigitalOcean Spaces, Wasabi, etc.) via `options.endpoint`.
|
|
1923
|
+
*
|
|
1924
|
+
* @example AWS S3
|
|
1925
|
+
* ```ts
|
|
1926
|
+
* import { createS3ProviderFactory, createTransferClient } from "@zero-transfer/sdk";
|
|
1927
|
+
*
|
|
1928
|
+
* const client = createTransferClient({ providers: [createS3ProviderFactory()] });
|
|
1929
|
+
*
|
|
1930
|
+
* const session = await client.connect({
|
|
1931
|
+
* host: "my-bucket",
|
|
1932
|
+
* provider: "s3",
|
|
1933
|
+
* username: process.env.AWS_ACCESS_KEY_ID,
|
|
1934
|
+
* password: { env: "AWS_SECRET_ACCESS_KEY" },
|
|
1935
|
+
* s3: { region: "us-east-1" },
|
|
1936
|
+
* });
|
|
1937
|
+
* ```
|
|
1938
|
+
*
|
|
1939
|
+
* @example MinIO / R2 / S3-compatible endpoint
|
|
1940
|
+
* ```ts
|
|
1941
|
+
* const client = createTransferClient({
|
|
1942
|
+
* providers: [createS3ProviderFactory({
|
|
1943
|
+
* endpoint: "https://minio.internal:9000",
|
|
1944
|
+
* pathStyle: true,
|
|
1945
|
+
* })],
|
|
1946
|
+
* });
|
|
1947
|
+
* ```
|
|
1710
1948
|
*/
|
|
1711
1949
|
declare function createS3ProviderFactory(options?: S3ProviderOptions): ProviderFactory;
|
|
1712
1950
|
|
|
@@ -2325,6 +2563,20 @@ interface FtpsProviderOptions extends FtpProviderOptions {
|
|
|
2325
2563
|
*
|
|
2326
2564
|
* @param options - Optional provider defaults.
|
|
2327
2565
|
* @returns Provider factory suitable for `createTransferClient({ providers: [...] })`.
|
|
2566
|
+
*
|
|
2567
|
+
* @example Plain FTP (cleartext — prefer FTPS or SFTP whenever possible)
|
|
2568
|
+
* ```ts
|
|
2569
|
+
* import { createFtpProviderFactory, createTransferClient } from "@zero-transfer/sdk";
|
|
2570
|
+
*
|
|
2571
|
+
* const client = createTransferClient({ providers: [createFtpProviderFactory()] });
|
|
2572
|
+
*
|
|
2573
|
+
* const session = await client.connect({
|
|
2574
|
+
* host: "ftp.example.com",
|
|
2575
|
+
* provider: "ftp",
|
|
2576
|
+
* username: "deploy",
|
|
2577
|
+
* password: { env: "FTP_PASSWORD" },
|
|
2578
|
+
* });
|
|
2579
|
+
* ```
|
|
2328
2580
|
*/
|
|
2329
2581
|
declare function createFtpProviderFactory(options?: FtpProviderOptions): ProviderFactory;
|
|
2330
2582
|
/**
|
|
@@ -2335,6 +2587,37 @@ declare function createFtpProviderFactory(options?: FtpProviderOptions): Provide
|
|
|
2335
2587
|
*
|
|
2336
2588
|
* @param options - Optional provider defaults.
|
|
2337
2589
|
* @returns Provider factory suitable for `createTransferClient({ providers: [...] })`.
|
|
2590
|
+
*
|
|
2591
|
+
* @example FTPS with public-CA TLS (no extra TLS material needed)
|
|
2592
|
+
* ```ts
|
|
2593
|
+
* import { createFtpsProviderFactory, createTransferClient } from "@zero-transfer/sdk";
|
|
2594
|
+
*
|
|
2595
|
+
* const client = createTransferClient({ providers: [createFtpsProviderFactory()] });
|
|
2596
|
+
*
|
|
2597
|
+
* const session = await client.connect({
|
|
2598
|
+
* host: "ftps.example.com",
|
|
2599
|
+
* provider: "ftps",
|
|
2600
|
+
* username: "deploy",
|
|
2601
|
+
* password: { env: "FTPS_PASSWORD" },
|
|
2602
|
+
* tls: { minVersion: "TLSv1.2" },
|
|
2603
|
+
* });
|
|
2604
|
+
* ```
|
|
2605
|
+
*
|
|
2606
|
+
* @example FTPS with private CA + certificate pinning (defence-in-depth)
|
|
2607
|
+
* ```ts
|
|
2608
|
+
* await client.connect({
|
|
2609
|
+
* host: "ftps.internal.example",
|
|
2610
|
+
* provider: "ftps",
|
|
2611
|
+
* username: "audit",
|
|
2612
|
+
* tls: {
|
|
2613
|
+
* ca: { path: "./certs/ca-bundle.pem" },
|
|
2614
|
+
* cert: { path: "./certs/client.crt" },
|
|
2615
|
+
* key: { path: "./certs/client.key" },
|
|
2616
|
+
* // Optional but recommended:
|
|
2617
|
+
* pinnedFingerprint256: "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99",
|
|
2618
|
+
* },
|
|
2619
|
+
* });
|
|
2620
|
+
* ```
|
|
2338
2621
|
*/
|
|
2339
2622
|
declare function createFtpsProviderFactory(options?: FtpsProviderOptions): ProviderFactory;
|
|
2340
2623
|
|
|
@@ -2514,6 +2797,28 @@ interface SftpRawSession {
|
|
|
2514
2797
|
*
|
|
2515
2798
|
* @param options - Optional ssh2 host-key verifier and timeout defaults.
|
|
2516
2799
|
* @returns Provider factory suitable for `createTransferClient({ providers: [...] })`.
|
|
2800
|
+
*
|
|
2801
|
+
* @example Register and use
|
|
2802
|
+
* ```ts
|
|
2803
|
+
* import { createSftpProviderFactory, createTransferClient } from "@zero-transfer/sdk";
|
|
2804
|
+
*
|
|
2805
|
+
* const client = createTransferClient({ providers: [createSftpProviderFactory()] });
|
|
2806
|
+
*
|
|
2807
|
+
* const session = await client.connect({
|
|
2808
|
+
* host: "sftp.example.com",
|
|
2809
|
+
* provider: "sftp",
|
|
2810
|
+
* username: "deploy",
|
|
2811
|
+
* ssh: {
|
|
2812
|
+
* privateKey: { path: "./keys/id_ed25519" },
|
|
2813
|
+
* // Optional but recommended for production:
|
|
2814
|
+
* pinnedHostKeySha256: "SHA256:abc123basesixfourpinFromKnownHosts=",
|
|
2815
|
+
* },
|
|
2816
|
+
* });
|
|
2817
|
+
* ```
|
|
2818
|
+
*
|
|
2819
|
+
* Host-key verification (`ssh.knownHosts` and/or `ssh.pinnedHostKeySha256`) is
|
|
2820
|
+
* optional; without either, the client trusts whatever host key the server
|
|
2821
|
+
* presents. Use one for any non-lab deployment.
|
|
2517
2822
|
*/
|
|
2518
2823
|
declare function createSftpProviderFactory(options?: SftpProviderOptions): ProviderFactory;
|
|
2519
2824
|
|
package/dist/index.mjs
CHANGED
|
@@ -3473,7 +3473,8 @@ function normalizeFeatureLines(input) {
|
|
|
3473
3473
|
// src/providers/classic/sftp/SftpProvider.ts
|
|
3474
3474
|
import { Buffer as Buffer5 } from "buffer";
|
|
3475
3475
|
import { createHash, createHmac, timingSafeEqual } from "crypto";
|
|
3476
|
-
import
|
|
3476
|
+
import ssh2 from "ssh2";
|
|
3477
|
+
var { Client: SshClientCtor, utils } = ssh2;
|
|
3477
3478
|
var SFTP_PROVIDER_ID = "sftp";
|
|
3478
3479
|
var SFTP_DEFAULT_PORT = 22;
|
|
3479
3480
|
var SFTP_PROVIDER_CAPABILITIES = {
|
|
@@ -3633,7 +3634,7 @@ var SftpFileSystem = class {
|
|
|
3633
3634
|
}
|
|
3634
3635
|
};
|
|
3635
3636
|
async function connectSshClient(profile, options, username, authentication) {
|
|
3636
|
-
const client = new
|
|
3637
|
+
const client = new SshClientCtor();
|
|
3637
3638
|
let config;
|
|
3638
3639
|
try {
|
|
3639
3640
|
config = await createConnectConfig(profile, options, username, authentication);
|
|
@@ -4349,7 +4350,8 @@ function noop() {
|
|
|
4349
4350
|
|
|
4350
4351
|
// src/providers/classic/sftp/jumpHost.ts
|
|
4351
4352
|
import { Buffer as Buffer6 } from "buffer";
|
|
4352
|
-
import
|
|
4353
|
+
import ssh22 from "ssh2";
|
|
4354
|
+
var { Client: SshClientCtor2 } = ssh22;
|
|
4353
4355
|
function createSftpJumpHostSocketFactory(options) {
|
|
4354
4356
|
if (options.bastion === void 0 && options.buildBastion === void 0) {
|
|
4355
4357
|
throw new ConfigurationError({
|
|
@@ -4370,7 +4372,7 @@ function createSftpJumpHostSocketFactory(options) {
|
|
|
4370
4372
|
}
|
|
4371
4373
|
function openJumpHostChannel(options) {
|
|
4372
4374
|
const { bastionConfig, context } = options;
|
|
4373
|
-
const client = options.createClient ? options.createClient() : new
|
|
4375
|
+
const client = options.createClient ? options.createClient() : new SshClientCtor2();
|
|
4374
4376
|
if (context.signal?.aborted === true) {
|
|
4375
4377
|
return Promise.reject(
|
|
4376
4378
|
new AbortError({
|
|
@@ -7019,6 +7021,11 @@ function normalizeLocalProviderPath(input) {
|
|
|
7019
7021
|
}
|
|
7020
7022
|
function resolveLocalPath(rootPath, remotePath) {
|
|
7021
7023
|
const normalizedRemotePath = normalizeLocalProviderPath(remotePath);
|
|
7024
|
+
const resolvedRootPath = path.resolve(rootPath);
|
|
7025
|
+
const candidateAbsolute = path.resolve(normalizedRemotePath.split("/").join(path.sep));
|
|
7026
|
+
if (candidateAbsolute === resolvedRootPath || candidateAbsolute.startsWith(resolvedRootPath + path.sep)) {
|
|
7027
|
+
return candidateAbsolute;
|
|
7028
|
+
}
|
|
7022
7029
|
const relativePath = normalizedRemotePath === "/" ? "." : normalizedRemotePath.slice(1);
|
|
7023
7030
|
const resolvedPath = path.resolve(rootPath, relativePath.split("/").join(path.sep));
|
|
7024
7031
|
const relativeToRoot = path.relative(rootPath, resolvedPath);
|