@zero-transfer/ssh 0.4.0 → 0.4.6
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/README.md +11 -5
- package/dist/index.cjs +97 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +356 -43
- package/dist/index.d.ts +356 -43
- package/dist/index.mjs +95 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
2
|
import { SecureVersion, PeerCertificate } from 'node:tls';
|
|
3
3
|
import { Readable } from 'node:stream';
|
|
4
|
-
import { Buffer } from 'node:buffer';
|
|
4
|
+
import { Buffer as Buffer$1 } from 'node:buffer';
|
|
5
5
|
import { Socket } from 'node:net';
|
|
6
6
|
import { KeyObject } from 'node:crypto';
|
|
7
7
|
|
|
@@ -183,7 +183,7 @@ interface CapabilitySet {
|
|
|
183
183
|
*/
|
|
184
184
|
|
|
185
185
|
/** Resolved secret value accepted by profile credential fields. */
|
|
186
|
-
type SecretValue = string | Buffer;
|
|
186
|
+
type SecretValue = string | Buffer$1;
|
|
187
187
|
/** Callback source used by applications to integrate vaults or credential brokers. */
|
|
188
188
|
type SecretProvider = () => SecretValue | Promise<SecretValue>;
|
|
189
189
|
/** Inline secret descriptor. Prefer env, path, or callback sources for real applications. */
|
|
@@ -215,7 +215,7 @@ interface ResolveSecretOptions {
|
|
|
215
215
|
/** Environment source. Defaults to `process.env`. */
|
|
216
216
|
env?: NodeJS.ProcessEnv;
|
|
217
217
|
/** File reader. Defaults to `fs.promises.readFile`. */
|
|
218
|
-
readFile?: (path: string) => Promise<Buffer> | Buffer;
|
|
218
|
+
readFile?: (path: string) => Promise<Buffer$1> | Buffer$1;
|
|
219
219
|
}
|
|
220
220
|
/**
|
|
221
221
|
* Resolves a secret source into a string or Buffer without logging the value.
|
|
@@ -396,7 +396,7 @@ interface TlsProfile {
|
|
|
396
396
|
* hex form with or without colons. When present, the TLS handshake additionally requires the
|
|
397
397
|
* leaf certificate's SHA-256 fingerprint to match one of these values.
|
|
398
398
|
*
|
|
399
|
-
* Not required for normal CA-trusted endpoints
|
|
399
|
+
* Not required for normal CA-trusted endpoints - public CAs and `ca` bundles already gate
|
|
400
400
|
* trust via `rejectUnauthorized`. Pinning is **recommended for production** when you control
|
|
401
401
|
* the server and want defence-in-depth against rogue certificates issued by trusted CAs.
|
|
402
402
|
*
|
|
@@ -835,7 +835,41 @@ interface TransferEngineOptions {
|
|
|
835
835
|
/** Clock used for receipts and progress events. Defaults to `new Date()`. */
|
|
836
836
|
now?: () => Date;
|
|
837
837
|
}
|
|
838
|
-
/**
|
|
838
|
+
/**
|
|
839
|
+
* Executes transfer jobs and produces audit-friendly receipts.
|
|
840
|
+
*
|
|
841
|
+
* The engine is the lowest-level entry point in the transfer stack: it owns
|
|
842
|
+
* retry policy, attempt history, abort propagation, progress event
|
|
843
|
+
* normalization, and receipt construction. Most callers reach the engine
|
|
844
|
+
* indirectly through {@link runRoute}, {@link uploadFile}, {@link downloadFile},
|
|
845
|
+
* {@link copyBetween}, or {@link TransferQueue}; instantiate it directly when
|
|
846
|
+
* you need full control over execution semantics.
|
|
847
|
+
*
|
|
848
|
+
* @example Execute a single job with a custom executor
|
|
849
|
+
* ```ts
|
|
850
|
+
* import { TransferEngine, type TransferExecutor, type TransferJob } from "@zero-transfer/sdk";
|
|
851
|
+
*
|
|
852
|
+
* const engine = new TransferEngine();
|
|
853
|
+
*
|
|
854
|
+
* const executor: TransferExecutor = async ({ job, signal, onProgress }) => {
|
|
855
|
+
* onProgress?.({ jobId: job.id, bytesTransferred: 0 });
|
|
856
|
+
* // … perform the bytes here, honoring `signal` …
|
|
857
|
+
* return { jobId: job.id, bytesTransferred: 1234, completedAt: new Date() };
|
|
858
|
+
* };
|
|
859
|
+
*
|
|
860
|
+
* const job: TransferJob = {
|
|
861
|
+
* id: "manual-1",
|
|
862
|
+
* operation: "upload",
|
|
863
|
+
* source: { profile: localProfile, path: "./data.bin" },
|
|
864
|
+
* destination: { profile: s3Profile, path: "/data/data.bin" },
|
|
865
|
+
* };
|
|
866
|
+
*
|
|
867
|
+
* const receipt = await engine.execute(job, executor, {
|
|
868
|
+
* retry: { maxAttempts: 3, baseDelayMs: 250 },
|
|
869
|
+
* });
|
|
870
|
+
* console.log(receipt.attempts.length); // 1 on success
|
|
871
|
+
* ```
|
|
872
|
+
*/
|
|
839
873
|
declare class TransferEngine {
|
|
840
874
|
private readonly now;
|
|
841
875
|
/**
|
|
@@ -1586,8 +1620,20 @@ interface ClientDiagnostics {
|
|
|
1586
1620
|
/**
|
|
1587
1621
|
* Returns a redaction-safe snapshot of the providers registered with a client.
|
|
1588
1622
|
*
|
|
1623
|
+
* Use this when rendering a setup screen, generating a support bundle, or
|
|
1624
|
+
* asserting in tests that the expected provider factories were registered.
|
|
1625
|
+
*
|
|
1589
1626
|
* @param client - Transfer client to inspect.
|
|
1590
1627
|
* @returns Provider id and capability snapshot tuples.
|
|
1628
|
+
*
|
|
1629
|
+
* @example List registered providers
|
|
1630
|
+
* ```ts
|
|
1631
|
+
* import { summarizeClientDiagnostics } from "@zero-transfer/sdk";
|
|
1632
|
+
*
|
|
1633
|
+
* for (const { id, capabilities } of summarizeClientDiagnostics(client).providers) {
|
|
1634
|
+
* console.log(`${id}: streaming=${capabilities.readStream} resume=${capabilities.resumeDownload}`);
|
|
1635
|
+
* }
|
|
1636
|
+
* ```
|
|
1591
1637
|
*/
|
|
1592
1638
|
declare function summarizeClientDiagnostics(client: TransferClient): ClientDiagnostics;
|
|
1593
1639
|
/** Per-step duration measurements collected by {@link runConnectionDiagnostics}. */
|
|
@@ -1640,8 +1686,36 @@ interface RunConnectionDiagnosticsOptions {
|
|
|
1640
1686
|
/**
|
|
1641
1687
|
* Connects to a profile, captures capability and listing samples, and returns a redaction-safe report.
|
|
1642
1688
|
*
|
|
1689
|
+
* Useful for connectivity "ping" pages, smoke tests, and bug reports. Secrets
|
|
1690
|
+
* in the profile are redacted via {@link redactConnectionProfile} before being
|
|
1691
|
+
* returned. The session is always disconnected before the function returns,
|
|
1692
|
+
* including when probes throw.
|
|
1693
|
+
*
|
|
1643
1694
|
* @param options - Diagnostic probe options.
|
|
1644
1695
|
* @returns Diagnostic report including timings and any captured error.
|
|
1696
|
+
*
|
|
1697
|
+
* @example Probe an SFTP connection
|
|
1698
|
+
* ```ts
|
|
1699
|
+
* import { runConnectionDiagnostics } from "@zero-transfer/sdk";
|
|
1700
|
+
*
|
|
1701
|
+
* const report = await runConnectionDiagnostics({
|
|
1702
|
+
* client,
|
|
1703
|
+
* profile: {
|
|
1704
|
+
* host: "sftp.example.com",
|
|
1705
|
+
* provider: "sftp",
|
|
1706
|
+
* username: "deploy",
|
|
1707
|
+
* ssh: { privateKey: { path: "./keys/id_ed25519" } },
|
|
1708
|
+
* },
|
|
1709
|
+
* listPath: "/uploads",
|
|
1710
|
+
* });
|
|
1711
|
+
*
|
|
1712
|
+
* if (!report.ok) {
|
|
1713
|
+
* console.error("connection failed:", report.error);
|
|
1714
|
+
* } else {
|
|
1715
|
+
* console.log(`connect=${report.timings.connectMs}ms list=${report.timings.listMs}ms`);
|
|
1716
|
+
* console.log(report.sample); // up to 5 entries from /uploads
|
|
1717
|
+
* }
|
|
1718
|
+
* ```
|
|
1645
1719
|
*/
|
|
1646
1720
|
declare function runConnectionDiagnostics(options: RunConnectionDiagnosticsOptions): Promise<ConnectionDiagnosticsResult>;
|
|
1647
1721
|
|
|
@@ -1650,7 +1724,7 @@ interface ConnectionPoolOptions {
|
|
|
1650
1724
|
/**
|
|
1651
1725
|
* Maximum number of *idle* sessions retained per pool key.
|
|
1652
1726
|
*
|
|
1653
|
-
* Active leases are not counted against this limit
|
|
1727
|
+
* Active leases are not counted against this limit - the cap only applies
|
|
1654
1728
|
* to sessions waiting in the pool. When more than `maxIdlePerKey` sessions
|
|
1655
1729
|
* become idle simultaneously, the oldest ones are disconnected. Defaults
|
|
1656
1730
|
* to `4`.
|
|
@@ -1748,8 +1822,29 @@ interface MemoryProviderOptions {
|
|
|
1748
1822
|
/**
|
|
1749
1823
|
* Creates a provider factory backed by deterministic in-memory fixture entries.
|
|
1750
1824
|
*
|
|
1825
|
+
* Useful for tests and examples where you want a real `TransferSession` without
|
|
1826
|
+
* touching disk or the network. Entries are pre-seeded; mutations made through
|
|
1827
|
+
* the session are visible to subsequent operations on the same provider.
|
|
1828
|
+
*
|
|
1751
1829
|
* @param options - Optional fixture entries to expose through the memory provider.
|
|
1752
1830
|
* @returns Provider factory suitable for `createTransferClient({ providers: [...] })`.
|
|
1831
|
+
*
|
|
1832
|
+
* @example Seed entries and read them back
|
|
1833
|
+
* ```ts
|
|
1834
|
+
* import { createMemoryProviderFactory, createTransferClient } from "@zero-transfer/sdk";
|
|
1835
|
+
*
|
|
1836
|
+
* const client = createTransferClient({
|
|
1837
|
+
* providers: [createMemoryProviderFactory({
|
|
1838
|
+
* entries: [
|
|
1839
|
+
* { path: "/fixtures/hello.txt", content: "hello world" },
|
|
1840
|
+
* { path: "/fixtures/data.bin", content: new Uint8Array([1, 2, 3]) },
|
|
1841
|
+
* ],
|
|
1842
|
+
* })],
|
|
1843
|
+
* });
|
|
1844
|
+
*
|
|
1845
|
+
* const session = await client.connect({ host: "fixtures", provider: "memory" });
|
|
1846
|
+
* console.log(await session.fs.list("/fixtures"));
|
|
1847
|
+
* ```
|
|
1753
1848
|
*/
|
|
1754
1849
|
declare function createMemoryProviderFactory(options?: MemoryProviderOptions): ProviderFactory;
|
|
1755
1850
|
|
|
@@ -2487,9 +2582,47 @@ interface TransferPlanSummary {
|
|
|
2487
2582
|
/** Counts grouped by action. */
|
|
2488
2583
|
actions: Record<string, number>;
|
|
2489
2584
|
}
|
|
2490
|
-
/**
|
|
2585
|
+
/**
|
|
2586
|
+
* Creates a transfer plan from dry-run planning input.
|
|
2587
|
+
*
|
|
2588
|
+
* Plans are immutable, structured descriptions of intended work. Pair with
|
|
2589
|
+
* {@link createSyncPlan} or {@link createAtomicDeployPlan} for end-to-end
|
|
2590
|
+
* planning, or build steps by hand when you need full control. Pass the plan
|
|
2591
|
+
* to {@link createTransferJobsFromPlan} to materialize executable jobs.
|
|
2592
|
+
*
|
|
2593
|
+
* @example Build a plan with two upload steps and inspect it
|
|
2594
|
+
* ```ts
|
|
2595
|
+
* import { createTransferPlan, summarizeTransferPlan } from "@zero-transfer/sdk";
|
|
2596
|
+
*
|
|
2597
|
+
* const plan = createTransferPlan({
|
|
2598
|
+
* id: "manual-batch",
|
|
2599
|
+
* steps: [
|
|
2600
|
+
* { action: "upload", source: "./a.bin", destination: "/lake/a.bin", expectedBytes: 1024 },
|
|
2601
|
+
* { action: "upload", source: "./b.bin", destination: "/lake/b.bin", expectedBytes: 2048 },
|
|
2602
|
+
* ],
|
|
2603
|
+
* });
|
|
2604
|
+
*
|
|
2605
|
+
* console.table(summarizeTransferPlan(plan));
|
|
2606
|
+
* ```
|
|
2607
|
+
*/
|
|
2491
2608
|
declare function createTransferPlan(input: TransferPlanInput): TransferPlan;
|
|
2492
|
-
/**
|
|
2609
|
+
/**
|
|
2610
|
+
* Summarizes a transfer plan for diagnostics, previews, and tests.
|
|
2611
|
+
*
|
|
2612
|
+
* Returns aggregate counts (total / executable / skipped / destructive),
|
|
2613
|
+
* total expected bytes, and a per-action histogram. Useful for printing a
|
|
2614
|
+
* one-line plan summary before executing or for asserting plan shape in
|
|
2615
|
+
* tests.
|
|
2616
|
+
*
|
|
2617
|
+
* @example Print a plan preview
|
|
2618
|
+
* ```ts
|
|
2619
|
+
* import { summarizeTransferPlan } from "@zero-transfer/sdk";
|
|
2620
|
+
*
|
|
2621
|
+
* const summary = summarizeTransferPlan(plan);
|
|
2622
|
+
* console.log(`${summary.executableSteps} steps, ${summary.totalExpectedBytes} bytes total`);
|
|
2623
|
+
* console.log("Actions:", summary.actions);
|
|
2624
|
+
* ```
|
|
2625
|
+
*/
|
|
2493
2626
|
declare function summarizeTransferPlan(plan: TransferPlan): TransferPlanSummary;
|
|
2494
2627
|
/** Converts executable plan steps into transfer jobs while preserving order. */
|
|
2495
2628
|
declare function createTransferJobsFromPlan(plan: TransferPlan): TransferJob[];
|
|
@@ -2566,7 +2699,41 @@ interface TransferQueueSummary {
|
|
|
2566
2699
|
/** Failed queue items in queue order. */
|
|
2567
2700
|
failures: TransferQueueItem[];
|
|
2568
2701
|
}
|
|
2569
|
-
/**
|
|
2702
|
+
/**
|
|
2703
|
+
* Minimal transfer queue with concurrency, pause/resume, cancellation, and drain summaries.
|
|
2704
|
+
*
|
|
2705
|
+
* Wrap a {@link TransferEngine} with a queue when you need to run many transfers
|
|
2706
|
+
* concurrently with bounded parallelism, observe per-job progress, or drive
|
|
2707
|
+
* a UI from a single source of truth. Items are FIFO; failures and successes
|
|
2708
|
+
* are surfaced via observers and in the final {@link TransferQueueSummary}.
|
|
2709
|
+
*
|
|
2710
|
+
* @example Run a batch of uploads with concurrency=4
|
|
2711
|
+
* ```ts
|
|
2712
|
+
* import {
|
|
2713
|
+
* TransferQueue,
|
|
2714
|
+
* createProviderTransferExecutor,
|
|
2715
|
+
* } from "@zero-transfer/sdk";
|
|
2716
|
+
*
|
|
2717
|
+
* const queue = new TransferQueue({
|
|
2718
|
+
* concurrency: 4,
|
|
2719
|
+
* executor: createProviderTransferExecutor({ client }),
|
|
2720
|
+
* onProgress: (e) => console.log(`${e.jobId}: ${e.bytesTransferred}`),
|
|
2721
|
+
* onError: (item, err) => console.error(`${item.job.id} failed`, err),
|
|
2722
|
+
* });
|
|
2723
|
+
*
|
|
2724
|
+
* for (const file of files) {
|
|
2725
|
+
* queue.enqueue({
|
|
2726
|
+
* id: file.name,
|
|
2727
|
+
* operation: "upload",
|
|
2728
|
+
* source: { profile: localProfile, path: file.path },
|
|
2729
|
+
* destination: { profile: s3Profile, path: `/lake/${file.name}` },
|
|
2730
|
+
* });
|
|
2731
|
+
* }
|
|
2732
|
+
*
|
|
2733
|
+
* const summary = await queue.drain();
|
|
2734
|
+
* console.log(`Completed ${summary.completed} / ${summary.total}`);
|
|
2735
|
+
* ```
|
|
2736
|
+
*/
|
|
2570
2737
|
declare class TransferQueue {
|
|
2571
2738
|
private readonly engine;
|
|
2572
2739
|
private readonly items;
|
|
@@ -2837,7 +3004,7 @@ interface DiffRemoteTreesOptions {
|
|
|
2837
3004
|
* Compares two remote subtrees and produces an entry-level diff.
|
|
2838
3005
|
*
|
|
2839
3006
|
* Source and destination paths are walked independently; entries are then aligned by
|
|
2840
|
-
* the relative path from each tree root. Directory equality is structural
|
|
3007
|
+
* the relative path from each tree root. Directory equality is structural - directories
|
|
2841
3008
|
* are equal when their relative paths match and the entry types agree.
|
|
2842
3009
|
*
|
|
2843
3010
|
* @param source - Source-side remote file system.
|
|
@@ -2846,6 +3013,26 @@ interface DiffRemoteTreesOptions {
|
|
|
2846
3013
|
* @param destinationPath - Destination-side root path being compared.
|
|
2847
3014
|
* @param options - Optional comparison controls.
|
|
2848
3015
|
* @returns Diff result containing entries and a summary.
|
|
3016
|
+
*
|
|
3017
|
+
* @example Diff two SFTP subtrees and feed the result into createSyncPlan
|
|
3018
|
+
* ```ts
|
|
3019
|
+
* import { createSyncPlan, diffRemoteTrees } from "@zero-transfer/sdk";
|
|
3020
|
+
*
|
|
3021
|
+
* const diff = await diffRemoteTrees(
|
|
3022
|
+
* srcSession.fs, "/exports",
|
|
3023
|
+
* dstSession.fs, "/exports",
|
|
3024
|
+
* { compareUniqueId: true },
|
|
3025
|
+
* );
|
|
3026
|
+
*
|
|
3027
|
+
* console.log(diff.summary); // { added, removed, changed, unchanged }
|
|
3028
|
+
*
|
|
3029
|
+
* const plan = createSyncPlan({
|
|
3030
|
+
* id: "exports-sync",
|
|
3031
|
+
* diff,
|
|
3032
|
+
* source: { provider: "sftp", rootPath: "/exports" },
|
|
3033
|
+
* destination: { provider: "sftp", rootPath: "/exports" },
|
|
3034
|
+
* });
|
|
3035
|
+
* ```
|
|
2849
3036
|
*/
|
|
2850
3037
|
declare function diffRemoteTrees(source: RemoteFileSystem, sourcePath: string, destination: RemoteFileSystem, destinationPath: string, options?: DiffRemoteTreesOptions): Promise<RemoteTreeDiff>;
|
|
2851
3038
|
|
|
@@ -2917,6 +3104,31 @@ interface CreateSyncPlanOptions {
|
|
|
2917
3104
|
* @param options - Inputs and policies that shape the plan.
|
|
2918
3105
|
* @returns Transfer plan ready for `createTransferJobsFromPlan` or queue execution.
|
|
2919
3106
|
* @throws {@link ConfigurationError} When `conflictPolicy: "error"` encounters a conflict.
|
|
3107
|
+
*
|
|
3108
|
+
* @example Mirror SFTP → S3 with deletes
|
|
3109
|
+
* ```ts
|
|
3110
|
+
* import {
|
|
3111
|
+
* createSyncPlan,
|
|
3112
|
+
* diffRemoteTrees,
|
|
3113
|
+
* summarizeTransferPlan,
|
|
3114
|
+
* } from "@zero-transfer/sdk";
|
|
3115
|
+
*
|
|
3116
|
+
* const diff = await diffRemoteTrees(
|
|
3117
|
+
* srcSession.fs, "/dist",
|
|
3118
|
+
* dstSession.fs, "/releases/current",
|
|
3119
|
+
* );
|
|
3120
|
+
*
|
|
3121
|
+
* const plan = createSyncPlan({
|
|
3122
|
+
* id: "release-mirror",
|
|
3123
|
+
* diff,
|
|
3124
|
+
* source: { provider: "sftp", rootPath: "/dist" },
|
|
3125
|
+
* destination: { provider: "s3", rootPath: "/releases/current" },
|
|
3126
|
+
* deletePolicy: "mirror",
|
|
3127
|
+
* conflictPolicy: "overwrite",
|
|
3128
|
+
* });
|
|
3129
|
+
*
|
|
3130
|
+
* console.table(summarizeTransferPlan(plan));
|
|
3131
|
+
* ```
|
|
2920
3132
|
*/
|
|
2921
3133
|
declare function createSyncPlan(options: CreateSyncPlanOptions): TransferPlan;
|
|
2922
3134
|
|
|
@@ -3032,9 +3244,39 @@ interface CreateAtomicDeployPlanOptions {
|
|
|
3032
3244
|
/**
|
|
3033
3245
|
* Builds an {@link AtomicDeployPlan} that stages a release, swaps it live, and prunes old releases.
|
|
3034
3246
|
*
|
|
3247
|
+
* The plan describes a blue/green-style deploy:
|
|
3248
|
+
* 1. Upload to a timestamped staging directory under `<destination>/.releases/`.
|
|
3249
|
+
* 2. Atomically swap the `current` symlink/rename to point at the new release.
|
|
3250
|
+
* 3. Optionally prune old releases beyond `retain`.
|
|
3251
|
+
*
|
|
3252
|
+
* No I/O is performed - the host executes the plan steps. Pair with
|
|
3253
|
+
* {@link createTransferPlan} or {@link createTransferJobsFromPlan} to execute.
|
|
3254
|
+
*
|
|
3035
3255
|
* @param options - Inputs and policies that shape the deploy.
|
|
3036
3256
|
* @returns Structured deploy plan ready for execution by the calling host.
|
|
3037
3257
|
* @throws {@link ConfigurationError} When `retain` is less than `1` or the destination root is empty.
|
|
3258
|
+
*
|
|
3259
|
+
* @example Plan a release with rollback path
|
|
3260
|
+
* ```ts
|
|
3261
|
+
* import { createAtomicDeployPlan } from "@zero-transfer/sdk";
|
|
3262
|
+
*
|
|
3263
|
+
* const plan = createAtomicDeployPlan({
|
|
3264
|
+
* id: "web-2026-04-28",
|
|
3265
|
+
* source: { rootPath: "./dist" },
|
|
3266
|
+
* destination: {
|
|
3267
|
+
* profile: { host: "web1.example.com", provider: "sftp", username: "deploy" },
|
|
3268
|
+
* rootPath: "/srv/www",
|
|
3269
|
+
* },
|
|
3270
|
+
* retain: 5,
|
|
3271
|
+
* existingReleases: [
|
|
3272
|
+
* "/srv/www/.releases/2026-04-21T00-00-00Z",
|
|
3273
|
+
* "/srv/www/.releases/2026-04-14T00-00-00Z",
|
|
3274
|
+
* ],
|
|
3275
|
+
* });
|
|
3276
|
+
*
|
|
3277
|
+
* console.log(plan.swap); // staging → current rename
|
|
3278
|
+
* console.log(plan.prune); // releases scheduled for removal
|
|
3279
|
+
* ```
|
|
3038
3280
|
*/
|
|
3039
3281
|
declare function createAtomicDeployPlan(options: CreateAtomicDeployPlanOptions): AtomicDeployPlan;
|
|
3040
3282
|
|
|
@@ -3227,6 +3469,12 @@ declare function joinRemotePath(...segments: string[]): string;
|
|
|
3227
3469
|
*/
|
|
3228
3470
|
declare function basenameRemotePath(input: string): string;
|
|
3229
3471
|
|
|
3472
|
+
/**
|
|
3473
|
+
* Returns `true` when the file containing `import.meta.url` is the entry point
|
|
3474
|
+
* of the current Node.js process. Returns `false` outside Node.
|
|
3475
|
+
*/
|
|
3476
|
+
declare function isMainModule(importMetaUrl: string): boolean;
|
|
3477
|
+
|
|
3230
3478
|
/** Algorithm lists exchanged during SSH KEXINIT negotiation. */
|
|
3231
3479
|
interface SshAlgorithmPreferences {
|
|
3232
3480
|
compressionClientToServer: readonly string[];
|
|
@@ -3272,7 +3520,7 @@ interface SshIdentification {
|
|
|
3272
3520
|
|
|
3273
3521
|
/** Parsed SSH_MSG_KEXINIT payload. */
|
|
3274
3522
|
interface SshKexInitMessage extends SshAlgorithmPreferences {
|
|
3275
|
-
cookie: Buffer;
|
|
3523
|
+
cookie: Buffer$1;
|
|
3276
3524
|
firstKexPacketFollows: boolean;
|
|
3277
3525
|
messageType: number;
|
|
3278
3526
|
reserved: number;
|
|
@@ -3280,31 +3528,31 @@ interface SshKexInitMessage extends SshAlgorithmPreferences {
|
|
|
3280
3528
|
|
|
3281
3529
|
/** Directional key material used after SSH NEWKEYS. */
|
|
3282
3530
|
interface SshTransportDirectionKeys {
|
|
3283
|
-
encryptionKey: Buffer;
|
|
3284
|
-
iv: Buffer;
|
|
3285
|
-
macKey: Buffer;
|
|
3531
|
+
encryptionKey: Buffer$1;
|
|
3532
|
+
iv: Buffer$1;
|
|
3533
|
+
macKey: Buffer$1;
|
|
3286
3534
|
}
|
|
3287
3535
|
/** Session key bundle derived from K, H, and session id. */
|
|
3288
3536
|
interface SshDerivedSessionKeys {
|
|
3289
3537
|
clientToServer: SshTransportDirectionKeys;
|
|
3290
|
-
exchangeHash: Buffer;
|
|
3538
|
+
exchangeHash: Buffer$1;
|
|
3291
3539
|
serverToClient: SshTransportDirectionKeys;
|
|
3292
|
-
sessionId: Buffer;
|
|
3540
|
+
sessionId: Buffer$1;
|
|
3293
3541
|
}
|
|
3294
3542
|
|
|
3295
3543
|
/** Initial client-side handshake state before key exchange math starts. */
|
|
3296
3544
|
interface SshTransportHandshakeResult {
|
|
3297
3545
|
keyExchange: {
|
|
3298
3546
|
algorithm: string;
|
|
3299
|
-
clientKexInitPayload: Buffer;
|
|
3300
|
-
clientPublicKey: Buffer;
|
|
3301
|
-
exchangeHash: Buffer;
|
|
3302
|
-
serverHostKey: Buffer;
|
|
3303
|
-
serverKexInitPayload: Buffer;
|
|
3304
|
-
serverPublicKey: Buffer;
|
|
3305
|
-
serverSignature: Buffer;
|
|
3306
|
-
sessionId: Buffer;
|
|
3307
|
-
sharedSecret: Buffer;
|
|
3547
|
+
clientKexInitPayload: Buffer$1;
|
|
3548
|
+
clientPublicKey: Buffer$1;
|
|
3549
|
+
exchangeHash: Buffer$1;
|
|
3550
|
+
serverHostKey: Buffer$1;
|
|
3551
|
+
serverKexInitPayload: Buffer$1;
|
|
3552
|
+
serverPublicKey: Buffer$1;
|
|
3553
|
+
serverSignature: Buffer$1;
|
|
3554
|
+
sessionId: Buffer$1;
|
|
3555
|
+
sharedSecret: Buffer$1;
|
|
3308
3556
|
transportKeys: {
|
|
3309
3557
|
clientToServer: SshDerivedSessionKeys["clientToServer"];
|
|
3310
3558
|
serverToClient: SshDerivedSessionKeys["serverToClient"];
|
|
@@ -3357,18 +3605,18 @@ declare class SshTransportHandshake {
|
|
|
3357
3605
|
* to enforce known_hosts or pinned-fingerprint policies.
|
|
3358
3606
|
*/
|
|
3359
3607
|
verifyHostKey?: (input: {
|
|
3360
|
-
hostKeyBlob: Buffer;
|
|
3361
|
-
hostKeySha256: Buffer;
|
|
3608
|
+
hostKeyBlob: Buffer$1;
|
|
3609
|
+
hostKeySha256: Buffer$1;
|
|
3362
3610
|
algorithmName: string;
|
|
3363
3611
|
}) => void | Promise<void>;
|
|
3364
3612
|
});
|
|
3365
3613
|
/** Creates the first outbound bytes (client identification line). */
|
|
3366
|
-
createInitialClientBytes(): Buffer;
|
|
3614
|
+
createInitialClientBytes(): Buffer$1;
|
|
3367
3615
|
/**
|
|
3368
3616
|
* Feeds raw server bytes into the handshake state machine.
|
|
3369
3617
|
*/
|
|
3370
3618
|
pushServerBytes(chunk: Uint8Array): {
|
|
3371
|
-
outbound: Buffer[];
|
|
3619
|
+
outbound: Buffer$1[];
|
|
3372
3620
|
result?: SshTransportHandshakeResult;
|
|
3373
3621
|
};
|
|
3374
3622
|
getServerBannerLines(): readonly string[];
|
|
@@ -3378,7 +3626,7 @@ declare class SshTransportHandshake {
|
|
|
3378
3626
|
* Call this once after `pushServerBytes` returns a result to drain bytes that belong to the
|
|
3379
3627
|
* post-NEWKEYS encrypted phase but arrived in the same TCP segment as NEWKEYS.
|
|
3380
3628
|
*/
|
|
3381
|
-
takeRemainingBytes(): Buffer;
|
|
3629
|
+
takeRemainingBytes(): Buffer$1;
|
|
3382
3630
|
private pushServerBytesWithPhase;
|
|
3383
3631
|
}
|
|
3384
3632
|
|
|
@@ -3426,8 +3674,8 @@ interface SshTransportConnectionOptions {
|
|
|
3426
3674
|
* exchange hash is verified. Throw to reject the server's identity.
|
|
3427
3675
|
*/
|
|
3428
3676
|
verifyHostKey?: (input: {
|
|
3429
|
-
hostKeyBlob: Buffer;
|
|
3430
|
-
hostKeySha256: Buffer;
|
|
3677
|
+
hostKeyBlob: Buffer$1;
|
|
3678
|
+
hostKeySha256: Buffer$1;
|
|
3431
3679
|
algorithmName: string;
|
|
3432
3680
|
}) => void;
|
|
3433
3681
|
}
|
|
@@ -3474,7 +3722,7 @@ declare class SshTransportConnection {
|
|
|
3474
3722
|
* Sends an SSH payload over the encrypted transport.
|
|
3475
3723
|
* The payload must start with the SSH message type byte.
|
|
3476
3724
|
*/
|
|
3477
|
-
sendPayload(payload: Buffer | Uint8Array): void;
|
|
3725
|
+
sendPayload(payload: Buffer$1 | Uint8Array): void;
|
|
3478
3726
|
/**
|
|
3479
3727
|
* Async generator that yields inbound SSH payloads (post-NEWKEYS).
|
|
3480
3728
|
*
|
|
@@ -3483,7 +3731,7 @@ declare class SshTransportConnection {
|
|
|
3483
3731
|
* - SSH_MSG_DISCONNECT (1) from the server throws a `ConnectionError`.
|
|
3484
3732
|
* - Socket error or close terminates the generator.
|
|
3485
3733
|
*/
|
|
3486
|
-
receivePayloads(): AsyncGenerator<Buffer>;
|
|
3734
|
+
receivePayloads(): AsyncGenerator<Buffer$1>;
|
|
3487
3735
|
/**
|
|
3488
3736
|
* Sends SSH_MSG_DISCONNECT and ends the socket.
|
|
3489
3737
|
* Safe to call multiple times; subsequent calls are no-ops.
|
|
@@ -3533,7 +3781,7 @@ interface SshKeyboardInteractiveCredential {
|
|
|
3533
3781
|
type SshCredential = SshPasswordCredential | SshPublickeyCredential | SshKeyboardInteractiveCredential;
|
|
3534
3782
|
interface SshAuthOptions {
|
|
3535
3783
|
credential: SshCredential;
|
|
3536
|
-
/** SSH session id (exchange hash) from key exchange
|
|
3784
|
+
/** SSH session id (exchange hash) from key exchange - required for publickey signing. */
|
|
3537
3785
|
sessionId: Uint8Array;
|
|
3538
3786
|
/** Maximum number of USERAUTH_FAILURE retries before giving up. Defaults to 4. */
|
|
3539
3787
|
maxAttempts?: number;
|
|
@@ -3650,7 +3898,7 @@ declare class SshSessionChannel {
|
|
|
3650
3898
|
* Async generator that yields raw data buffers from the channel.
|
|
3651
3899
|
* Returns (done) when the channel receives EOF or CLOSE.
|
|
3652
3900
|
*/
|
|
3653
|
-
receiveData(): AsyncGenerator<Buffer, void, undefined>;
|
|
3901
|
+
receiveData(): AsyncGenerator<Buffer$1, void, undefined>;
|
|
3654
3902
|
/**
|
|
3655
3903
|
* Sends EOF and CLOSE. Should be called when the client is done sending.
|
|
3656
3904
|
*/
|
|
@@ -3659,7 +3907,7 @@ declare class SshSessionChannel {
|
|
|
3659
3907
|
* Feed an inbound transport payload to this channel.
|
|
3660
3908
|
* Called by the channel multiplexer (`SshConnectionManager`).
|
|
3661
3909
|
*/
|
|
3662
|
-
dispatch(payload: Buffer): void;
|
|
3910
|
+
dispatch(payload: Buffer$1): void;
|
|
3663
3911
|
dispatchError(error: Error): void;
|
|
3664
3912
|
private consumeLocalWindow;
|
|
3665
3913
|
private enqueueInbound;
|
|
@@ -3699,7 +3947,7 @@ declare class SshConnectionManager {
|
|
|
3699
3947
|
* Channel setup happens sequentially before `start()` begins pumping, so we
|
|
3700
3948
|
* pull directly from the transport iterator here.
|
|
3701
3949
|
*/
|
|
3702
|
-
nextSetupPayload(): Promise<Buffer>;
|
|
3950
|
+
nextSetupPayload(): Promise<Buffer$1>;
|
|
3703
3951
|
/**
|
|
3704
3952
|
* Opens a session channel and starts the SFTP subsystem on it.
|
|
3705
3953
|
* Must be called before `start()`.
|
|
@@ -3740,10 +3988,10 @@ declare class SshDataReader {
|
|
|
3740
3988
|
hasMore(): boolean;
|
|
3741
3989
|
readByte(): number;
|
|
3742
3990
|
readBoolean(): boolean;
|
|
3743
|
-
readBytes(length: number): Buffer;
|
|
3991
|
+
readBytes(length: number): Buffer$1;
|
|
3744
3992
|
readUint32(): number;
|
|
3745
3993
|
readUint64(): bigint;
|
|
3746
|
-
readString(): Buffer;
|
|
3994
|
+
readString(): Buffer$1;
|
|
3747
3995
|
readUtf8String(): string;
|
|
3748
3996
|
readNameList(): string[];
|
|
3749
3997
|
/**
|
|
@@ -3751,7 +3999,7 @@ declare class SshDataReader {
|
|
|
3751
3999
|
* big-endian integer. Returns the raw magnitude bytes (non-negative integers
|
|
3752
4000
|
* may have a leading 0x00 byte preserved by the caller as needed).
|
|
3753
4001
|
*/
|
|
3754
|
-
readMpint(): Buffer;
|
|
4002
|
+
readMpint(): Buffer$1;
|
|
3755
4003
|
assertFinished(): void;
|
|
3756
4004
|
private ensureAvailable;
|
|
3757
4005
|
}
|
|
@@ -3770,9 +4018,74 @@ declare class SshDataWriter {
|
|
|
3770
4018
|
writeString(value: string | Uint8Array, encoding?: BufferEncoding): this;
|
|
3771
4019
|
writeMpint(value: Uint8Array): this;
|
|
3772
4020
|
writeNameList(values: readonly string[]): this;
|
|
3773
|
-
toBuffer(): Buffer;
|
|
4021
|
+
toBuffer(): Buffer$1;
|
|
3774
4022
|
private push;
|
|
3775
4023
|
private assertByte;
|
|
3776
4024
|
}
|
|
3777
4025
|
|
|
3778
|
-
|
|
4026
|
+
/**
|
|
4027
|
+
* Options for {@link runSshCommand}.
|
|
4028
|
+
*/
|
|
4029
|
+
interface RunSshCommandOptions {
|
|
4030
|
+
/** Hostname or IP of the SSH server. */
|
|
4031
|
+
host: string;
|
|
4032
|
+
/** TCP port. Defaults to `22`. */
|
|
4033
|
+
port?: number;
|
|
4034
|
+
/** Command to execute on the remote shell. */
|
|
4035
|
+
command: string;
|
|
4036
|
+
/**
|
|
4037
|
+
* Authentication credential. Use one of:
|
|
4038
|
+
*
|
|
4039
|
+
* - `{ type: "password", username, password }`
|
|
4040
|
+
* - `{ type: "publickey", username, algorithmName, publicKeyBlob, sign }`
|
|
4041
|
+
* (build one from a private-key file with `buildPublickeyCredential`)
|
|
4042
|
+
* - `{ type: "keyboard-interactive", username, respond }`
|
|
4043
|
+
*/
|
|
4044
|
+
auth: SshCredential;
|
|
4045
|
+
/**
|
|
4046
|
+
* Forwarded to {@link SshTransportConnection}; covers host-key pinning,
|
|
4047
|
+
* algorithm overrides, and handshake timeout. The default
|
|
4048
|
+
* `handshakeTimeoutMs` is 10 seconds.
|
|
4049
|
+
*/
|
|
4050
|
+
transport?: SshTransportConnectionOptions;
|
|
4051
|
+
/** TCP connect timeout in milliseconds. Defaults to 10 000. */
|
|
4052
|
+
connectTimeoutMs?: number;
|
|
4053
|
+
/** Maximum total bytes captured from stdout. Defaults to 16 MiB. */
|
|
4054
|
+
maxOutputBytes?: number;
|
|
4055
|
+
}
|
|
4056
|
+
/**
|
|
4057
|
+
* Result of {@link runSshCommand}. The full captured stdout is provided as
|
|
4058
|
+
* both a `Buffer` (for binary output) and as a UTF-8 decoded `string`.
|
|
4059
|
+
*
|
|
4060
|
+
* Note: stderr (CHANNEL_EXTENDED_DATA) and exit-status are not currently
|
|
4061
|
+
* surfaced - drop down to {@link SshConnectionManager}/{@link SshSessionChannel}
|
|
4062
|
+
* directly if you need them.
|
|
4063
|
+
*/
|
|
4064
|
+
interface RunSshCommandResult {
|
|
4065
|
+
/** Captured stdout as raw bytes. */
|
|
4066
|
+
stdout: Buffer;
|
|
4067
|
+
/** Captured stdout decoded as UTF-8. */
|
|
4068
|
+
stdoutText: string;
|
|
4069
|
+
/** Bytes received before the channel closed. */
|
|
4070
|
+
bytesReceived: number;
|
|
4071
|
+
}
|
|
4072
|
+
/**
|
|
4073
|
+
* Connects, authenticates, runs `command` on a fresh exec channel, drains
|
|
4074
|
+
* stdout, and disconnects. The TCP socket, transport, auth session, and
|
|
4075
|
+
* channel are all owned by this helper and torn down before it returns.
|
|
4076
|
+
*
|
|
4077
|
+
* @example Run `uname -a` with a password credential
|
|
4078
|
+
* ```ts
|
|
4079
|
+
* import { runSshCommand } from "@zero-transfer/ssh";
|
|
4080
|
+
*
|
|
4081
|
+
* const { stdoutText } = await runSshCommand({
|
|
4082
|
+
* host: "ssh.example.com",
|
|
4083
|
+
* auth: { type: "password", username: "deploy", password: process.env.SSH_PASSWORD! },
|
|
4084
|
+
* command: "uname -a",
|
|
4085
|
+
* });
|
|
4086
|
+
* console.log(stdoutText);
|
|
4087
|
+
* ```
|
|
4088
|
+
*/
|
|
4089
|
+
declare function runSshCommand(options: RunSshCommandOptions): Promise<RunSshCommandResult>;
|
|
4090
|
+
|
|
4091
|
+
export { AbortError, type AtomicDeployActivateOperation, type AtomicDeployActivateStep, type AtomicDeployPlan, type AtomicDeployPruneStep, type AtomicDeployStrategy, type AuthenticationCapability, AuthenticationError, AuthorizationError, type BandwidthSleep, type BandwidthThrottle, type BandwidthThrottleOptions, type Base64EnvSecretSource, type BuiltInProviderId, CLASSIC_PROVIDER_IDS, type CapabilitySet, type ChecksumCapability, type ClassicProviderId, type ClientDiagnostics, type CompareRemoteManifestsOptions, ConfigurationError, type ConnectionDiagnosticTimings, type ConnectionDiagnosticsResult, ConnectionError, type ConnectionPoolOptions, type ConnectionProfile, type CopyBetweenOptions, type CreateAtomicDeployPlanOptions, type CreateRemoteBrowserOptions, type CreateRemoteManifestOptions, type CreateSyncPlanOptions, DEFAULT_SSH_ALGORITHM_PREFERENCES, type DiffRemoteTreesOptions, type DownloadFileOptions, type EnvSecretSource, type FileSecretSource, type FileZillaSite, type FriendlyTransferOptions, type FtpReplyErrorInput, type ImportFileZillaSitesResult, type ImportOpenSshConfigOptions, type ImportOpenSshConfigResult, type ImportWinScpSessionsResult, type KnownHostsEntry, type KnownHostsMarker, type ListOptions, type LocalProviderOptions, type LogLevel, type LogRecord, type LogRecordInput, type LoggerMethod, type MemoryProviderEntry, type MemoryProviderOptions, type MetadataCapability, type MkdirOptions, type NegotiatedSshAlgorithms, type OAuthAccessToken, type OAuthRefreshCallback, type OAuthTokenSecretSourceOptions, type OpenSshConfigEntry, ParseError, PathAlreadyExistsError, PathNotFoundError, PermissionDeniedError, type PooledTransferClient, type ProgressEventInput, ProtocolError, type AuthenticationCapability as ProviderAuthenticationCapability, type CapabilitySet as ProviderCapabilities, type ChecksumCapability as ProviderChecksumCapability, type ProviderFactory, type ProviderId, type MetadataCapability as ProviderMetadataCapability, ProviderRegistry, type ProviderSelection, type ProviderTransferEndpointRole, type ProviderTransferExecutorOptions, type ProviderTransferOperations, type ProviderTransferReadRequest, type ProviderTransferReadResult, type ProviderTransferRequest, type ProviderTransferSessionResolver, type ProviderTransferSessionResolverInput, type ProviderTransferWriteRequest, type ProviderTransferWriteResult, REDACTED, REMOTE_MANIFEST_FORMAT_VERSION, type RemoteBreadcrumb, type RemoteBrowser, type RemoteBrowserFilter, type RemoteBrowserSnapshot, type RemoteEntry, type RemoteEntrySortKey, type RemoteEntrySortOrder, type RemoteEntryType, type RemoteFileAdapter, type RemoteFileEndpoint, type RemoteFileSystem, type RemoteManifest, type RemoteManifestEntry, type RemotePermissions, type RemoteProtocol, type RemoteStat, type RemoteTreeDiff, type RemoteTreeDiffEntry, type RemoteTreeDiffReason, type RemoteTreeDiffStatus, type RemoteTreeDiffSummary, type RemoteTreeEntry, type RemoteTreeFilter, type RemoveOptions, type RenameOptions, type ResolveSecretOptions, type ResolvedConnectionProfile, type ResolvedOpenSshHost, type ResolvedSshProfile, type ResolvedTlsProfile, type RmdirOptions, type RunConnectionDiagnosticsOptions, type RunSshCommandOptions, type RunSshCommandResult, type SecretProvider, type SecretSource, type SecretValue, type SpecializedErrorDetails, type SshAgentSource, type SshAlgorithmPreferences, type SshAlgorithms, SshAuthSession, SshConnectionManager, SshDataReader, SshDataWriter, SshDisconnectReason, type SshKeyboardInteractiveChallenge, type SshKeyboardInteractiveCredential, type SshKeyboardInteractiveHandler, type SshKeyboardInteractivePrompt, type SshKnownHostsSource, type SshPasswordCredential, type SshProfile, type SshPublickeyCredential, SshSessionChannel, type SshSocketFactory, type SshSocketFactoryContext, SshTransportConnection, type SshTransportConnectionOptions, SshTransportHandshake, type SshTransportHandshakeResult, type StatOptions, type SyncConflictPolicy, type SyncDeletePolicy, type SyncDirection, type SyncEndpointInput, TimeoutError, type TlsProfile, type TlsSecretSource, type TransferAttempt, type TransferAttemptError, type TransferBandwidthLimit, type TransferByteRange, TransferClient, type TransferClientOptions, type TransferDataChunk, type TransferDataSource, type TransferEndpoint, TransferEngine, type TransferEngineExecuteOptions, type TransferEngineOptions, TransferError, type TransferExecutionContext, type TransferExecutionResult, type TransferExecutor, type TransferJob, type TransferOperation, type TransferPlan, type TransferPlanAction, type TransferPlanInput, type TransferPlanStep, type TransferPlanSummary, type TransferProgressEvent, type TransferProvider, TransferQueue, type TransferQueueExecutorResolver, type TransferQueueItem, type TransferQueueItemStatus, type TransferQueueOptions, type TransferQueueRunOptions, type TransferQueueSummary, type TransferReceipt, type TransferResult, type TransferResultInput, type TransferRetryDecisionInput, type TransferRetryPolicy, type TransferSession, type TransferTimeoutPolicy, type TransferVerificationResult, UnsupportedFeatureError, type UploadFileOptions, type ValueSecretSource, VerificationError, type WalkRemoteTreeOptions, type WinScpSession, ZeroTransfer, type ZeroTransferCapabilities, ZeroTransferError, type ZeroTransferErrorDetails, type ZeroTransferLogger, type ZeroTransferOptions, assertSafeFtpArgument, basenameRemotePath, buildPublickeyCredential, buildRemoteBreadcrumbs, compareRemoteManifests, copyBetween, createAtomicDeployPlan, createBandwidthThrottle, createLocalProviderFactory, createMemoryProviderFactory, createOAuthTokenSecretSource, createPooledTransferClient, createProgressEvent, createProviderTransferExecutor, createRemoteBrowser, createRemoteManifest, createSyncPlan, createTransferClient, createTransferJobsFromPlan, createTransferPlan, createTransferResult, diffRemoteTrees, downloadFile, emitLog, errorFromFtpReply, filterRemoteEntries, importFileZillaSites, importOpenSshConfig, importWinScpSessions, isClassicProviderId, isMainModule, isSensitiveKey, joinRemotePath, matchKnownHosts, matchKnownHostsEntry, negotiateSshAlgorithms, noopLogger, normalizeRemotePath, parentRemotePath, parseKnownHosts, parseOpenSshConfig, parseRemoteManifest, redactCommand, redactConnectionProfile, redactObject, redactSecretSource, redactValue, resolveConnectionProfileSecrets, resolveOpenSshHost, resolveProviderId, resolveSecret, runConnectionDiagnostics, runSshCommand, serializeRemoteManifest, sortRemoteEntries, summarizeClientDiagnostics, summarizeTransferPlan, throttleByteIterable, uploadFile, validateConnectionProfile, walkRemoteTree };
|