@zero-transfer/sftp 0.4.0 → 0.4.2
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.map +1 -1
- package/dist/index.d.mts +246 -4
- package/dist/index.d.ts +246 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -834,7 +834,41 @@ interface TransferEngineOptions {
|
|
|
834
834
|
/** Clock used for receipts and progress events. Defaults to `new Date()`. */
|
|
835
835
|
now?: () => Date;
|
|
836
836
|
}
|
|
837
|
-
/**
|
|
837
|
+
/**
|
|
838
|
+
* Executes transfer jobs and produces audit-friendly receipts.
|
|
839
|
+
*
|
|
840
|
+
* The engine is the lowest-level entry point in the transfer stack: it owns
|
|
841
|
+
* retry policy, attempt history, abort propagation, progress event
|
|
842
|
+
* normalization, and receipt construction. Most callers reach the engine
|
|
843
|
+
* indirectly through {@link runRoute}, {@link uploadFile}, {@link downloadFile},
|
|
844
|
+
* {@link copyBetween}, or {@link TransferQueue}; instantiate it directly when
|
|
845
|
+
* you need full control over execution semantics.
|
|
846
|
+
*
|
|
847
|
+
* @example Execute a single job with a custom executor
|
|
848
|
+
* ```ts
|
|
849
|
+
* import { TransferEngine, type TransferExecutor, type TransferJob } from "@zero-transfer/sdk";
|
|
850
|
+
*
|
|
851
|
+
* const engine = new TransferEngine();
|
|
852
|
+
*
|
|
853
|
+
* const executor: TransferExecutor = async ({ job, signal, onProgress }) => {
|
|
854
|
+
* onProgress?.({ jobId: job.id, bytesTransferred: 0 });
|
|
855
|
+
* // … perform the bytes here, honoring `signal` …
|
|
856
|
+
* return { jobId: job.id, bytesTransferred: 1234, completedAt: new Date() };
|
|
857
|
+
* };
|
|
858
|
+
*
|
|
859
|
+
* const job: TransferJob = {
|
|
860
|
+
* id: "manual-1",
|
|
861
|
+
* operation: "upload",
|
|
862
|
+
* source: { profile: localProfile, path: "./data.bin" },
|
|
863
|
+
* destination: { profile: s3Profile, path: "/data/data.bin" },
|
|
864
|
+
* };
|
|
865
|
+
*
|
|
866
|
+
* const receipt = await engine.execute(job, executor, {
|
|
867
|
+
* retry: { maxAttempts: 3, baseDelayMs: 250 },
|
|
868
|
+
* });
|
|
869
|
+
* console.log(receipt.attempts.length); // 1 on success
|
|
870
|
+
* ```
|
|
871
|
+
*/
|
|
838
872
|
declare class TransferEngine {
|
|
839
873
|
private readonly now;
|
|
840
874
|
/**
|
|
@@ -1585,8 +1619,20 @@ interface ClientDiagnostics {
|
|
|
1585
1619
|
/**
|
|
1586
1620
|
* Returns a redaction-safe snapshot of the providers registered with a client.
|
|
1587
1621
|
*
|
|
1622
|
+
* Use this when rendering a setup screen, generating a support bundle, or
|
|
1623
|
+
* asserting in tests that the expected provider factories were registered.
|
|
1624
|
+
*
|
|
1588
1625
|
* @param client - Transfer client to inspect.
|
|
1589
1626
|
* @returns Provider id and capability snapshot tuples.
|
|
1627
|
+
*
|
|
1628
|
+
* @example List registered providers
|
|
1629
|
+
* ```ts
|
|
1630
|
+
* import { summarizeClientDiagnostics } from "@zero-transfer/sdk";
|
|
1631
|
+
*
|
|
1632
|
+
* for (const { id, capabilities } of summarizeClientDiagnostics(client).providers) {
|
|
1633
|
+
* console.log(`${id}: streaming=${capabilities.readStream} resume=${capabilities.resumeDownload}`);
|
|
1634
|
+
* }
|
|
1635
|
+
* ```
|
|
1590
1636
|
*/
|
|
1591
1637
|
declare function summarizeClientDiagnostics(client: TransferClient): ClientDiagnostics;
|
|
1592
1638
|
/** Per-step duration measurements collected by {@link runConnectionDiagnostics}. */
|
|
@@ -1639,8 +1685,36 @@ interface RunConnectionDiagnosticsOptions {
|
|
|
1639
1685
|
/**
|
|
1640
1686
|
* Connects to a profile, captures capability and listing samples, and returns a redaction-safe report.
|
|
1641
1687
|
*
|
|
1688
|
+
* Useful for connectivity "ping" pages, smoke tests, and bug reports. Secrets
|
|
1689
|
+
* in the profile are redacted via {@link redactConnectionProfile} before being
|
|
1690
|
+
* returned. The session is always disconnected before the function returns,
|
|
1691
|
+
* including when probes throw.
|
|
1692
|
+
*
|
|
1642
1693
|
* @param options - Diagnostic probe options.
|
|
1643
1694
|
* @returns Diagnostic report including timings and any captured error.
|
|
1695
|
+
*
|
|
1696
|
+
* @example Probe an SFTP connection
|
|
1697
|
+
* ```ts
|
|
1698
|
+
* import { runConnectionDiagnostics } from "@zero-transfer/sdk";
|
|
1699
|
+
*
|
|
1700
|
+
* const report = await runConnectionDiagnostics({
|
|
1701
|
+
* client,
|
|
1702
|
+
* profile: {
|
|
1703
|
+
* host: "sftp.example.com",
|
|
1704
|
+
* provider: "sftp",
|
|
1705
|
+
* username: "deploy",
|
|
1706
|
+
* ssh: { privateKey: { path: "./keys/id_ed25519" } },
|
|
1707
|
+
* },
|
|
1708
|
+
* listPath: "/uploads",
|
|
1709
|
+
* });
|
|
1710
|
+
*
|
|
1711
|
+
* if (!report.ok) {
|
|
1712
|
+
* console.error("connection failed:", report.error);
|
|
1713
|
+
* } else {
|
|
1714
|
+
* console.log(`connect=${report.timings.connectMs}ms list=${report.timings.listMs}ms`);
|
|
1715
|
+
* console.log(report.sample); // up to 5 entries from /uploads
|
|
1716
|
+
* }
|
|
1717
|
+
* ```
|
|
1644
1718
|
*/
|
|
1645
1719
|
declare function runConnectionDiagnostics(options: RunConnectionDiagnosticsOptions): Promise<ConnectionDiagnosticsResult>;
|
|
1646
1720
|
|
|
@@ -1747,8 +1821,29 @@ interface MemoryProviderOptions {
|
|
|
1747
1821
|
/**
|
|
1748
1822
|
* Creates a provider factory backed by deterministic in-memory fixture entries.
|
|
1749
1823
|
*
|
|
1824
|
+
* Useful for tests and examples where you want a real `TransferSession` without
|
|
1825
|
+
* touching disk or the network. Entries are pre-seeded; mutations made through
|
|
1826
|
+
* the session are visible to subsequent operations on the same provider.
|
|
1827
|
+
*
|
|
1750
1828
|
* @param options - Optional fixture entries to expose through the memory provider.
|
|
1751
1829
|
* @returns Provider factory suitable for `createTransferClient({ providers: [...] })`.
|
|
1830
|
+
*
|
|
1831
|
+
* @example Seed entries and read them back
|
|
1832
|
+
* ```ts
|
|
1833
|
+
* import { createMemoryProviderFactory, createTransferClient } from "@zero-transfer/sdk";
|
|
1834
|
+
*
|
|
1835
|
+
* const client = createTransferClient({
|
|
1836
|
+
* providers: [createMemoryProviderFactory({
|
|
1837
|
+
* entries: [
|
|
1838
|
+
* { path: "/fixtures/hello.txt", content: "hello world" },
|
|
1839
|
+
* { path: "/fixtures/data.bin", content: new Uint8Array([1, 2, 3]) },
|
|
1840
|
+
* ],
|
|
1841
|
+
* })],
|
|
1842
|
+
* });
|
|
1843
|
+
*
|
|
1844
|
+
* const session = await client.connect({ host: "fixtures", provider: "memory" });
|
|
1845
|
+
* console.log(await session.fs.list("/fixtures"));
|
|
1846
|
+
* ```
|
|
1752
1847
|
*/
|
|
1753
1848
|
declare function createMemoryProviderFactory(options?: MemoryProviderOptions): ProviderFactory;
|
|
1754
1849
|
|
|
@@ -2486,9 +2581,47 @@ interface TransferPlanSummary {
|
|
|
2486
2581
|
/** Counts grouped by action. */
|
|
2487
2582
|
actions: Record<string, number>;
|
|
2488
2583
|
}
|
|
2489
|
-
/**
|
|
2584
|
+
/**
|
|
2585
|
+
* Creates a transfer plan from dry-run planning input.
|
|
2586
|
+
*
|
|
2587
|
+
* Plans are immutable, structured descriptions of intended work. Pair with
|
|
2588
|
+
* {@link createSyncPlan} or {@link createAtomicDeployPlan} for end-to-end
|
|
2589
|
+
* planning, or build steps by hand when you need full control. Pass the plan
|
|
2590
|
+
* to {@link createTransferJobsFromPlan} to materialize executable jobs.
|
|
2591
|
+
*
|
|
2592
|
+
* @example Build a plan with two upload steps and inspect it
|
|
2593
|
+
* ```ts
|
|
2594
|
+
* import { createTransferPlan, summarizeTransferPlan } from "@zero-transfer/sdk";
|
|
2595
|
+
*
|
|
2596
|
+
* const plan = createTransferPlan({
|
|
2597
|
+
* id: "manual-batch",
|
|
2598
|
+
* steps: [
|
|
2599
|
+
* { action: "upload", source: "./a.bin", destination: "/lake/a.bin", expectedBytes: 1024 },
|
|
2600
|
+
* { action: "upload", source: "./b.bin", destination: "/lake/b.bin", expectedBytes: 2048 },
|
|
2601
|
+
* ],
|
|
2602
|
+
* });
|
|
2603
|
+
*
|
|
2604
|
+
* console.table(summarizeTransferPlan(plan));
|
|
2605
|
+
* ```
|
|
2606
|
+
*/
|
|
2490
2607
|
declare function createTransferPlan(input: TransferPlanInput): TransferPlan;
|
|
2491
|
-
/**
|
|
2608
|
+
/**
|
|
2609
|
+
* Summarizes a transfer plan for diagnostics, previews, and tests.
|
|
2610
|
+
*
|
|
2611
|
+
* Returns aggregate counts (total / executable / skipped / destructive),
|
|
2612
|
+
* total expected bytes, and a per-action histogram. Useful for printing a
|
|
2613
|
+
* one-line plan summary before executing or for asserting plan shape in
|
|
2614
|
+
* tests.
|
|
2615
|
+
*
|
|
2616
|
+
* @example Print a plan preview
|
|
2617
|
+
* ```ts
|
|
2618
|
+
* import { summarizeTransferPlan } from "@zero-transfer/sdk";
|
|
2619
|
+
*
|
|
2620
|
+
* const summary = summarizeTransferPlan(plan);
|
|
2621
|
+
* console.log(`${summary.executableSteps} steps, ${summary.totalExpectedBytes} bytes total`);
|
|
2622
|
+
* console.log("Actions:", summary.actions);
|
|
2623
|
+
* ```
|
|
2624
|
+
*/
|
|
2492
2625
|
declare function summarizeTransferPlan(plan: TransferPlan): TransferPlanSummary;
|
|
2493
2626
|
/** Converts executable plan steps into transfer jobs while preserving order. */
|
|
2494
2627
|
declare function createTransferJobsFromPlan(plan: TransferPlan): TransferJob[];
|
|
@@ -2565,7 +2698,41 @@ interface TransferQueueSummary {
|
|
|
2565
2698
|
/** Failed queue items in queue order. */
|
|
2566
2699
|
failures: TransferQueueItem[];
|
|
2567
2700
|
}
|
|
2568
|
-
/**
|
|
2701
|
+
/**
|
|
2702
|
+
* Minimal transfer queue with concurrency, pause/resume, cancellation, and drain summaries.
|
|
2703
|
+
*
|
|
2704
|
+
* Wrap a {@link TransferEngine} with a queue when you need to run many transfers
|
|
2705
|
+
* concurrently with bounded parallelism, observe per-job progress, or drive
|
|
2706
|
+
* a UI from a single source of truth. Items are FIFO; failures and successes
|
|
2707
|
+
* are surfaced via observers and in the final {@link TransferQueueSummary}.
|
|
2708
|
+
*
|
|
2709
|
+
* @example Run a batch of uploads with concurrency=4
|
|
2710
|
+
* ```ts
|
|
2711
|
+
* import {
|
|
2712
|
+
* TransferQueue,
|
|
2713
|
+
* createProviderTransferExecutor,
|
|
2714
|
+
* } from "@zero-transfer/sdk";
|
|
2715
|
+
*
|
|
2716
|
+
* const queue = new TransferQueue({
|
|
2717
|
+
* concurrency: 4,
|
|
2718
|
+
* executor: createProviderTransferExecutor({ client }),
|
|
2719
|
+
* onProgress: (e) => console.log(`${e.jobId}: ${e.bytesTransferred}`),
|
|
2720
|
+
* onError: (item, err) => console.error(`${item.job.id} failed`, err),
|
|
2721
|
+
* });
|
|
2722
|
+
*
|
|
2723
|
+
* for (const file of files) {
|
|
2724
|
+
* queue.enqueue({
|
|
2725
|
+
* id: file.name,
|
|
2726
|
+
* operation: "upload",
|
|
2727
|
+
* source: { profile: localProfile, path: file.path },
|
|
2728
|
+
* destination: { profile: s3Profile, path: `/lake/${file.name}` },
|
|
2729
|
+
* });
|
|
2730
|
+
* }
|
|
2731
|
+
*
|
|
2732
|
+
* const summary = await queue.drain();
|
|
2733
|
+
* console.log(`Completed ${summary.completed} / ${summary.total}`);
|
|
2734
|
+
* ```
|
|
2735
|
+
*/
|
|
2569
2736
|
declare class TransferQueue {
|
|
2570
2737
|
private readonly engine;
|
|
2571
2738
|
private readonly items;
|
|
@@ -2845,6 +3012,26 @@ interface DiffRemoteTreesOptions {
|
|
|
2845
3012
|
* @param destinationPath - Destination-side root path being compared.
|
|
2846
3013
|
* @param options - Optional comparison controls.
|
|
2847
3014
|
* @returns Diff result containing entries and a summary.
|
|
3015
|
+
*
|
|
3016
|
+
* @example Diff two SFTP subtrees and feed the result into createSyncPlan
|
|
3017
|
+
* ```ts
|
|
3018
|
+
* import { createSyncPlan, diffRemoteTrees } from "@zero-transfer/sdk";
|
|
3019
|
+
*
|
|
3020
|
+
* const diff = await diffRemoteTrees(
|
|
3021
|
+
* srcSession.fs, "/exports",
|
|
3022
|
+
* dstSession.fs, "/exports",
|
|
3023
|
+
* { compareUniqueId: true },
|
|
3024
|
+
* );
|
|
3025
|
+
*
|
|
3026
|
+
* console.log(diff.summary); // { added, removed, changed, unchanged }
|
|
3027
|
+
*
|
|
3028
|
+
* const plan = createSyncPlan({
|
|
3029
|
+
* id: "exports-sync",
|
|
3030
|
+
* diff,
|
|
3031
|
+
* source: { provider: "sftp", rootPath: "/exports" },
|
|
3032
|
+
* destination: { provider: "sftp", rootPath: "/exports" },
|
|
3033
|
+
* });
|
|
3034
|
+
* ```
|
|
2848
3035
|
*/
|
|
2849
3036
|
declare function diffRemoteTrees(source: RemoteFileSystem, sourcePath: string, destination: RemoteFileSystem, destinationPath: string, options?: DiffRemoteTreesOptions): Promise<RemoteTreeDiff>;
|
|
2850
3037
|
|
|
@@ -2916,6 +3103,31 @@ interface CreateSyncPlanOptions {
|
|
|
2916
3103
|
* @param options - Inputs and policies that shape the plan.
|
|
2917
3104
|
* @returns Transfer plan ready for `createTransferJobsFromPlan` or queue execution.
|
|
2918
3105
|
* @throws {@link ConfigurationError} When `conflictPolicy: "error"` encounters a conflict.
|
|
3106
|
+
*
|
|
3107
|
+
* @example Mirror SFTP → S3 with deletes
|
|
3108
|
+
* ```ts
|
|
3109
|
+
* import {
|
|
3110
|
+
* createSyncPlan,
|
|
3111
|
+
* diffRemoteTrees,
|
|
3112
|
+
* summarizeTransferPlan,
|
|
3113
|
+
* } from "@zero-transfer/sdk";
|
|
3114
|
+
*
|
|
3115
|
+
* const diff = await diffRemoteTrees(
|
|
3116
|
+
* srcSession.fs, "/dist",
|
|
3117
|
+
* dstSession.fs, "/releases/current",
|
|
3118
|
+
* );
|
|
3119
|
+
*
|
|
3120
|
+
* const plan = createSyncPlan({
|
|
3121
|
+
* id: "release-mirror",
|
|
3122
|
+
* diff,
|
|
3123
|
+
* source: { provider: "sftp", rootPath: "/dist" },
|
|
3124
|
+
* destination: { provider: "s3", rootPath: "/releases/current" },
|
|
3125
|
+
* deletePolicy: "mirror",
|
|
3126
|
+
* conflictPolicy: "overwrite",
|
|
3127
|
+
* });
|
|
3128
|
+
*
|
|
3129
|
+
* console.table(summarizeTransferPlan(plan));
|
|
3130
|
+
* ```
|
|
2919
3131
|
*/
|
|
2920
3132
|
declare function createSyncPlan(options: CreateSyncPlanOptions): TransferPlan;
|
|
2921
3133
|
|
|
@@ -3031,9 +3243,39 @@ interface CreateAtomicDeployPlanOptions {
|
|
|
3031
3243
|
/**
|
|
3032
3244
|
* Builds an {@link AtomicDeployPlan} that stages a release, swaps it live, and prunes old releases.
|
|
3033
3245
|
*
|
|
3246
|
+
* The plan describes a blue/green-style deploy:
|
|
3247
|
+
* 1. Upload to a timestamped staging directory under `<destination>/.releases/`.
|
|
3248
|
+
* 2. Atomically swap the `current` symlink/rename to point at the new release.
|
|
3249
|
+
* 3. Optionally prune old releases beyond `retain`.
|
|
3250
|
+
*
|
|
3251
|
+
* No I/O is performed — the host executes the plan steps. Pair with
|
|
3252
|
+
* {@link createTransferPlan} or {@link createTransferJobsFromPlan} to execute.
|
|
3253
|
+
*
|
|
3034
3254
|
* @param options - Inputs and policies that shape the deploy.
|
|
3035
3255
|
* @returns Structured deploy plan ready for execution by the calling host.
|
|
3036
3256
|
* @throws {@link ConfigurationError} When `retain` is less than `1` or the destination root is empty.
|
|
3257
|
+
*
|
|
3258
|
+
* @example Plan a release with rollback path
|
|
3259
|
+
* ```ts
|
|
3260
|
+
* import { createAtomicDeployPlan } from "@zero-transfer/sdk";
|
|
3261
|
+
*
|
|
3262
|
+
* const plan = createAtomicDeployPlan({
|
|
3263
|
+
* id: "web-2026-04-28",
|
|
3264
|
+
* source: { rootPath: "./dist" },
|
|
3265
|
+
* destination: {
|
|
3266
|
+
* profile: { host: "web1.example.com", provider: "sftp", username: "deploy" },
|
|
3267
|
+
* rootPath: "/srv/www",
|
|
3268
|
+
* },
|
|
3269
|
+
* retain: 5,
|
|
3270
|
+
* existingReleases: [
|
|
3271
|
+
* "/srv/www/.releases/2026-04-21T00-00-00Z",
|
|
3272
|
+
* "/srv/www/.releases/2026-04-14T00-00-00Z",
|
|
3273
|
+
* ],
|
|
3274
|
+
* });
|
|
3275
|
+
*
|
|
3276
|
+
* console.log(plan.swap); // staging → current rename
|
|
3277
|
+
* console.log(plan.prune); // releases scheduled for removal
|
|
3278
|
+
* ```
|
|
3037
3279
|
*/
|
|
3038
3280
|
declare function createAtomicDeployPlan(options: CreateAtomicDeployPlanOptions): AtomicDeployPlan;
|
|
3039
3281
|
|
package/dist/index.d.ts
CHANGED
|
@@ -834,7 +834,41 @@ interface TransferEngineOptions {
|
|
|
834
834
|
/** Clock used for receipts and progress events. Defaults to `new Date()`. */
|
|
835
835
|
now?: () => Date;
|
|
836
836
|
}
|
|
837
|
-
/**
|
|
837
|
+
/**
|
|
838
|
+
* Executes transfer jobs and produces audit-friendly receipts.
|
|
839
|
+
*
|
|
840
|
+
* The engine is the lowest-level entry point in the transfer stack: it owns
|
|
841
|
+
* retry policy, attempt history, abort propagation, progress event
|
|
842
|
+
* normalization, and receipt construction. Most callers reach the engine
|
|
843
|
+
* indirectly through {@link runRoute}, {@link uploadFile}, {@link downloadFile},
|
|
844
|
+
* {@link copyBetween}, or {@link TransferQueue}; instantiate it directly when
|
|
845
|
+
* you need full control over execution semantics.
|
|
846
|
+
*
|
|
847
|
+
* @example Execute a single job with a custom executor
|
|
848
|
+
* ```ts
|
|
849
|
+
* import { TransferEngine, type TransferExecutor, type TransferJob } from "@zero-transfer/sdk";
|
|
850
|
+
*
|
|
851
|
+
* const engine = new TransferEngine();
|
|
852
|
+
*
|
|
853
|
+
* const executor: TransferExecutor = async ({ job, signal, onProgress }) => {
|
|
854
|
+
* onProgress?.({ jobId: job.id, bytesTransferred: 0 });
|
|
855
|
+
* // … perform the bytes here, honoring `signal` …
|
|
856
|
+
* return { jobId: job.id, bytesTransferred: 1234, completedAt: new Date() };
|
|
857
|
+
* };
|
|
858
|
+
*
|
|
859
|
+
* const job: TransferJob = {
|
|
860
|
+
* id: "manual-1",
|
|
861
|
+
* operation: "upload",
|
|
862
|
+
* source: { profile: localProfile, path: "./data.bin" },
|
|
863
|
+
* destination: { profile: s3Profile, path: "/data/data.bin" },
|
|
864
|
+
* };
|
|
865
|
+
*
|
|
866
|
+
* const receipt = await engine.execute(job, executor, {
|
|
867
|
+
* retry: { maxAttempts: 3, baseDelayMs: 250 },
|
|
868
|
+
* });
|
|
869
|
+
* console.log(receipt.attempts.length); // 1 on success
|
|
870
|
+
* ```
|
|
871
|
+
*/
|
|
838
872
|
declare class TransferEngine {
|
|
839
873
|
private readonly now;
|
|
840
874
|
/**
|
|
@@ -1585,8 +1619,20 @@ interface ClientDiagnostics {
|
|
|
1585
1619
|
/**
|
|
1586
1620
|
* Returns a redaction-safe snapshot of the providers registered with a client.
|
|
1587
1621
|
*
|
|
1622
|
+
* Use this when rendering a setup screen, generating a support bundle, or
|
|
1623
|
+
* asserting in tests that the expected provider factories were registered.
|
|
1624
|
+
*
|
|
1588
1625
|
* @param client - Transfer client to inspect.
|
|
1589
1626
|
* @returns Provider id and capability snapshot tuples.
|
|
1627
|
+
*
|
|
1628
|
+
* @example List registered providers
|
|
1629
|
+
* ```ts
|
|
1630
|
+
* import { summarizeClientDiagnostics } from "@zero-transfer/sdk";
|
|
1631
|
+
*
|
|
1632
|
+
* for (const { id, capabilities } of summarizeClientDiagnostics(client).providers) {
|
|
1633
|
+
* console.log(`${id}: streaming=${capabilities.readStream} resume=${capabilities.resumeDownload}`);
|
|
1634
|
+
* }
|
|
1635
|
+
* ```
|
|
1590
1636
|
*/
|
|
1591
1637
|
declare function summarizeClientDiagnostics(client: TransferClient): ClientDiagnostics;
|
|
1592
1638
|
/** Per-step duration measurements collected by {@link runConnectionDiagnostics}. */
|
|
@@ -1639,8 +1685,36 @@ interface RunConnectionDiagnosticsOptions {
|
|
|
1639
1685
|
/**
|
|
1640
1686
|
* Connects to a profile, captures capability and listing samples, and returns a redaction-safe report.
|
|
1641
1687
|
*
|
|
1688
|
+
* Useful for connectivity "ping" pages, smoke tests, and bug reports. Secrets
|
|
1689
|
+
* in the profile are redacted via {@link redactConnectionProfile} before being
|
|
1690
|
+
* returned. The session is always disconnected before the function returns,
|
|
1691
|
+
* including when probes throw.
|
|
1692
|
+
*
|
|
1642
1693
|
* @param options - Diagnostic probe options.
|
|
1643
1694
|
* @returns Diagnostic report including timings and any captured error.
|
|
1695
|
+
*
|
|
1696
|
+
* @example Probe an SFTP connection
|
|
1697
|
+
* ```ts
|
|
1698
|
+
* import { runConnectionDiagnostics } from "@zero-transfer/sdk";
|
|
1699
|
+
*
|
|
1700
|
+
* const report = await runConnectionDiagnostics({
|
|
1701
|
+
* client,
|
|
1702
|
+
* profile: {
|
|
1703
|
+
* host: "sftp.example.com",
|
|
1704
|
+
* provider: "sftp",
|
|
1705
|
+
* username: "deploy",
|
|
1706
|
+
* ssh: { privateKey: { path: "./keys/id_ed25519" } },
|
|
1707
|
+
* },
|
|
1708
|
+
* listPath: "/uploads",
|
|
1709
|
+
* });
|
|
1710
|
+
*
|
|
1711
|
+
* if (!report.ok) {
|
|
1712
|
+
* console.error("connection failed:", report.error);
|
|
1713
|
+
* } else {
|
|
1714
|
+
* console.log(`connect=${report.timings.connectMs}ms list=${report.timings.listMs}ms`);
|
|
1715
|
+
* console.log(report.sample); // up to 5 entries from /uploads
|
|
1716
|
+
* }
|
|
1717
|
+
* ```
|
|
1644
1718
|
*/
|
|
1645
1719
|
declare function runConnectionDiagnostics(options: RunConnectionDiagnosticsOptions): Promise<ConnectionDiagnosticsResult>;
|
|
1646
1720
|
|
|
@@ -1747,8 +1821,29 @@ interface MemoryProviderOptions {
|
|
|
1747
1821
|
/**
|
|
1748
1822
|
* Creates a provider factory backed by deterministic in-memory fixture entries.
|
|
1749
1823
|
*
|
|
1824
|
+
* Useful for tests and examples where you want a real `TransferSession` without
|
|
1825
|
+
* touching disk or the network. Entries are pre-seeded; mutations made through
|
|
1826
|
+
* the session are visible to subsequent operations on the same provider.
|
|
1827
|
+
*
|
|
1750
1828
|
* @param options - Optional fixture entries to expose through the memory provider.
|
|
1751
1829
|
* @returns Provider factory suitable for `createTransferClient({ providers: [...] })`.
|
|
1830
|
+
*
|
|
1831
|
+
* @example Seed entries and read them back
|
|
1832
|
+
* ```ts
|
|
1833
|
+
* import { createMemoryProviderFactory, createTransferClient } from "@zero-transfer/sdk";
|
|
1834
|
+
*
|
|
1835
|
+
* const client = createTransferClient({
|
|
1836
|
+
* providers: [createMemoryProviderFactory({
|
|
1837
|
+
* entries: [
|
|
1838
|
+
* { path: "/fixtures/hello.txt", content: "hello world" },
|
|
1839
|
+
* { path: "/fixtures/data.bin", content: new Uint8Array([1, 2, 3]) },
|
|
1840
|
+
* ],
|
|
1841
|
+
* })],
|
|
1842
|
+
* });
|
|
1843
|
+
*
|
|
1844
|
+
* const session = await client.connect({ host: "fixtures", provider: "memory" });
|
|
1845
|
+
* console.log(await session.fs.list("/fixtures"));
|
|
1846
|
+
* ```
|
|
1752
1847
|
*/
|
|
1753
1848
|
declare function createMemoryProviderFactory(options?: MemoryProviderOptions): ProviderFactory;
|
|
1754
1849
|
|
|
@@ -2486,9 +2581,47 @@ interface TransferPlanSummary {
|
|
|
2486
2581
|
/** Counts grouped by action. */
|
|
2487
2582
|
actions: Record<string, number>;
|
|
2488
2583
|
}
|
|
2489
|
-
/**
|
|
2584
|
+
/**
|
|
2585
|
+
* Creates a transfer plan from dry-run planning input.
|
|
2586
|
+
*
|
|
2587
|
+
* Plans are immutable, structured descriptions of intended work. Pair with
|
|
2588
|
+
* {@link createSyncPlan} or {@link createAtomicDeployPlan} for end-to-end
|
|
2589
|
+
* planning, or build steps by hand when you need full control. Pass the plan
|
|
2590
|
+
* to {@link createTransferJobsFromPlan} to materialize executable jobs.
|
|
2591
|
+
*
|
|
2592
|
+
* @example Build a plan with two upload steps and inspect it
|
|
2593
|
+
* ```ts
|
|
2594
|
+
* import { createTransferPlan, summarizeTransferPlan } from "@zero-transfer/sdk";
|
|
2595
|
+
*
|
|
2596
|
+
* const plan = createTransferPlan({
|
|
2597
|
+
* id: "manual-batch",
|
|
2598
|
+
* steps: [
|
|
2599
|
+
* { action: "upload", source: "./a.bin", destination: "/lake/a.bin", expectedBytes: 1024 },
|
|
2600
|
+
* { action: "upload", source: "./b.bin", destination: "/lake/b.bin", expectedBytes: 2048 },
|
|
2601
|
+
* ],
|
|
2602
|
+
* });
|
|
2603
|
+
*
|
|
2604
|
+
* console.table(summarizeTransferPlan(plan));
|
|
2605
|
+
* ```
|
|
2606
|
+
*/
|
|
2490
2607
|
declare function createTransferPlan(input: TransferPlanInput): TransferPlan;
|
|
2491
|
-
/**
|
|
2608
|
+
/**
|
|
2609
|
+
* Summarizes a transfer plan for diagnostics, previews, and tests.
|
|
2610
|
+
*
|
|
2611
|
+
* Returns aggregate counts (total / executable / skipped / destructive),
|
|
2612
|
+
* total expected bytes, and a per-action histogram. Useful for printing a
|
|
2613
|
+
* one-line plan summary before executing or for asserting plan shape in
|
|
2614
|
+
* tests.
|
|
2615
|
+
*
|
|
2616
|
+
* @example Print a plan preview
|
|
2617
|
+
* ```ts
|
|
2618
|
+
* import { summarizeTransferPlan } from "@zero-transfer/sdk";
|
|
2619
|
+
*
|
|
2620
|
+
* const summary = summarizeTransferPlan(plan);
|
|
2621
|
+
* console.log(`${summary.executableSteps} steps, ${summary.totalExpectedBytes} bytes total`);
|
|
2622
|
+
* console.log("Actions:", summary.actions);
|
|
2623
|
+
* ```
|
|
2624
|
+
*/
|
|
2492
2625
|
declare function summarizeTransferPlan(plan: TransferPlan): TransferPlanSummary;
|
|
2493
2626
|
/** Converts executable plan steps into transfer jobs while preserving order. */
|
|
2494
2627
|
declare function createTransferJobsFromPlan(plan: TransferPlan): TransferJob[];
|
|
@@ -2565,7 +2698,41 @@ interface TransferQueueSummary {
|
|
|
2565
2698
|
/** Failed queue items in queue order. */
|
|
2566
2699
|
failures: TransferQueueItem[];
|
|
2567
2700
|
}
|
|
2568
|
-
/**
|
|
2701
|
+
/**
|
|
2702
|
+
* Minimal transfer queue with concurrency, pause/resume, cancellation, and drain summaries.
|
|
2703
|
+
*
|
|
2704
|
+
* Wrap a {@link TransferEngine} with a queue when you need to run many transfers
|
|
2705
|
+
* concurrently with bounded parallelism, observe per-job progress, or drive
|
|
2706
|
+
* a UI from a single source of truth. Items are FIFO; failures and successes
|
|
2707
|
+
* are surfaced via observers and in the final {@link TransferQueueSummary}.
|
|
2708
|
+
*
|
|
2709
|
+
* @example Run a batch of uploads with concurrency=4
|
|
2710
|
+
* ```ts
|
|
2711
|
+
* import {
|
|
2712
|
+
* TransferQueue,
|
|
2713
|
+
* createProviderTransferExecutor,
|
|
2714
|
+
* } from "@zero-transfer/sdk";
|
|
2715
|
+
*
|
|
2716
|
+
* const queue = new TransferQueue({
|
|
2717
|
+
* concurrency: 4,
|
|
2718
|
+
* executor: createProviderTransferExecutor({ client }),
|
|
2719
|
+
* onProgress: (e) => console.log(`${e.jobId}: ${e.bytesTransferred}`),
|
|
2720
|
+
* onError: (item, err) => console.error(`${item.job.id} failed`, err),
|
|
2721
|
+
* });
|
|
2722
|
+
*
|
|
2723
|
+
* for (const file of files) {
|
|
2724
|
+
* queue.enqueue({
|
|
2725
|
+
* id: file.name,
|
|
2726
|
+
* operation: "upload",
|
|
2727
|
+
* source: { profile: localProfile, path: file.path },
|
|
2728
|
+
* destination: { profile: s3Profile, path: `/lake/${file.name}` },
|
|
2729
|
+
* });
|
|
2730
|
+
* }
|
|
2731
|
+
*
|
|
2732
|
+
* const summary = await queue.drain();
|
|
2733
|
+
* console.log(`Completed ${summary.completed} / ${summary.total}`);
|
|
2734
|
+
* ```
|
|
2735
|
+
*/
|
|
2569
2736
|
declare class TransferQueue {
|
|
2570
2737
|
private readonly engine;
|
|
2571
2738
|
private readonly items;
|
|
@@ -2845,6 +3012,26 @@ interface DiffRemoteTreesOptions {
|
|
|
2845
3012
|
* @param destinationPath - Destination-side root path being compared.
|
|
2846
3013
|
* @param options - Optional comparison controls.
|
|
2847
3014
|
* @returns Diff result containing entries and a summary.
|
|
3015
|
+
*
|
|
3016
|
+
* @example Diff two SFTP subtrees and feed the result into createSyncPlan
|
|
3017
|
+
* ```ts
|
|
3018
|
+
* import { createSyncPlan, diffRemoteTrees } from "@zero-transfer/sdk";
|
|
3019
|
+
*
|
|
3020
|
+
* const diff = await diffRemoteTrees(
|
|
3021
|
+
* srcSession.fs, "/exports",
|
|
3022
|
+
* dstSession.fs, "/exports",
|
|
3023
|
+
* { compareUniqueId: true },
|
|
3024
|
+
* );
|
|
3025
|
+
*
|
|
3026
|
+
* console.log(diff.summary); // { added, removed, changed, unchanged }
|
|
3027
|
+
*
|
|
3028
|
+
* const plan = createSyncPlan({
|
|
3029
|
+
* id: "exports-sync",
|
|
3030
|
+
* diff,
|
|
3031
|
+
* source: { provider: "sftp", rootPath: "/exports" },
|
|
3032
|
+
* destination: { provider: "sftp", rootPath: "/exports" },
|
|
3033
|
+
* });
|
|
3034
|
+
* ```
|
|
2848
3035
|
*/
|
|
2849
3036
|
declare function diffRemoteTrees(source: RemoteFileSystem, sourcePath: string, destination: RemoteFileSystem, destinationPath: string, options?: DiffRemoteTreesOptions): Promise<RemoteTreeDiff>;
|
|
2850
3037
|
|
|
@@ -2916,6 +3103,31 @@ interface CreateSyncPlanOptions {
|
|
|
2916
3103
|
* @param options - Inputs and policies that shape the plan.
|
|
2917
3104
|
* @returns Transfer plan ready for `createTransferJobsFromPlan` or queue execution.
|
|
2918
3105
|
* @throws {@link ConfigurationError} When `conflictPolicy: "error"` encounters a conflict.
|
|
3106
|
+
*
|
|
3107
|
+
* @example Mirror SFTP → S3 with deletes
|
|
3108
|
+
* ```ts
|
|
3109
|
+
* import {
|
|
3110
|
+
* createSyncPlan,
|
|
3111
|
+
* diffRemoteTrees,
|
|
3112
|
+
* summarizeTransferPlan,
|
|
3113
|
+
* } from "@zero-transfer/sdk";
|
|
3114
|
+
*
|
|
3115
|
+
* const diff = await diffRemoteTrees(
|
|
3116
|
+
* srcSession.fs, "/dist",
|
|
3117
|
+
* dstSession.fs, "/releases/current",
|
|
3118
|
+
* );
|
|
3119
|
+
*
|
|
3120
|
+
* const plan = createSyncPlan({
|
|
3121
|
+
* id: "release-mirror",
|
|
3122
|
+
* diff,
|
|
3123
|
+
* source: { provider: "sftp", rootPath: "/dist" },
|
|
3124
|
+
* destination: { provider: "s3", rootPath: "/releases/current" },
|
|
3125
|
+
* deletePolicy: "mirror",
|
|
3126
|
+
* conflictPolicy: "overwrite",
|
|
3127
|
+
* });
|
|
3128
|
+
*
|
|
3129
|
+
* console.table(summarizeTransferPlan(plan));
|
|
3130
|
+
* ```
|
|
2919
3131
|
*/
|
|
2920
3132
|
declare function createSyncPlan(options: CreateSyncPlanOptions): TransferPlan;
|
|
2921
3133
|
|
|
@@ -3031,9 +3243,39 @@ interface CreateAtomicDeployPlanOptions {
|
|
|
3031
3243
|
/**
|
|
3032
3244
|
* Builds an {@link AtomicDeployPlan} that stages a release, swaps it live, and prunes old releases.
|
|
3033
3245
|
*
|
|
3246
|
+
* The plan describes a blue/green-style deploy:
|
|
3247
|
+
* 1. Upload to a timestamped staging directory under `<destination>/.releases/`.
|
|
3248
|
+
* 2. Atomically swap the `current` symlink/rename to point at the new release.
|
|
3249
|
+
* 3. Optionally prune old releases beyond `retain`.
|
|
3250
|
+
*
|
|
3251
|
+
* No I/O is performed — the host executes the plan steps. Pair with
|
|
3252
|
+
* {@link createTransferPlan} or {@link createTransferJobsFromPlan} to execute.
|
|
3253
|
+
*
|
|
3034
3254
|
* @param options - Inputs and policies that shape the deploy.
|
|
3035
3255
|
* @returns Structured deploy plan ready for execution by the calling host.
|
|
3036
3256
|
* @throws {@link ConfigurationError} When `retain` is less than `1` or the destination root is empty.
|
|
3257
|
+
*
|
|
3258
|
+
* @example Plan a release with rollback path
|
|
3259
|
+
* ```ts
|
|
3260
|
+
* import { createAtomicDeployPlan } from "@zero-transfer/sdk";
|
|
3261
|
+
*
|
|
3262
|
+
* const plan = createAtomicDeployPlan({
|
|
3263
|
+
* id: "web-2026-04-28",
|
|
3264
|
+
* source: { rootPath: "./dist" },
|
|
3265
|
+
* destination: {
|
|
3266
|
+
* profile: { host: "web1.example.com", provider: "sftp", username: "deploy" },
|
|
3267
|
+
* rootPath: "/srv/www",
|
|
3268
|
+
* },
|
|
3269
|
+
* retain: 5,
|
|
3270
|
+
* existingReleases: [
|
|
3271
|
+
* "/srv/www/.releases/2026-04-21T00-00-00Z",
|
|
3272
|
+
* "/srv/www/.releases/2026-04-14T00-00-00Z",
|
|
3273
|
+
* ],
|
|
3274
|
+
* });
|
|
3275
|
+
*
|
|
3276
|
+
* console.log(plan.swap); // staging → current rename
|
|
3277
|
+
* console.log(plan.prune); // releases scheduled for removal
|
|
3278
|
+
* ```
|
|
3037
3279
|
*/
|
|
3038
3280
|
declare function createAtomicDeployPlan(options: CreateAtomicDeployPlanOptions): AtomicDeployPlan;
|
|
3039
3281
|
|