@zero-transfer/sdk 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/README.md +124 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +600 -13
- package/dist/index.d.ts +600 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -71,7 +71,7 @@ Requires Node.js **>=20**.
|
|
|
71
71
|
|
|
72
72
|
## Scoped packages
|
|
73
73
|
|
|
74
|
-
ZeroTransfer publishes
|
|
74
|
+
ZeroTransfer publishes 14 scoped packages under the [`@zero-transfer`](https://www.npmjs.com/org/zero-transfer) npm organization. [`@zero-transfer/sdk`](https://www.npmjs.com/package/@zero-transfer/sdk) is the batteries-included distribution; the other 13 are **narrowly scoped** packages that publish only the symbols listed in their [scope page](docs/scopes/README.md). Pick one to keep your dependency tree tight, or install the SDK if you want every provider in one go.
|
|
75
75
|
|
|
76
76
|
| Package | Summary | Docs |
|
|
77
77
|
| ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------- | ----------------------------------------- |
|
|
@@ -81,6 +81,7 @@ ZeroTransfer publishes 13 scoped packages under the [`@zero-transfer`](https://w
|
|
|
81
81
|
| [`@zero-transfer/ftp`](https://www.npmjs.com/package/@zero-transfer/ftp) | Classic FTP with EPSV/PASV streaming and REST resume. | [Scope page](docs/scopes/ftp.md) |
|
|
82
82
|
| [`@zero-transfer/ftps`](https://www.npmjs.com/package/@zero-transfer/ftps) | Explicit + implicit FTPS with full TLS profile support. | [Scope page](docs/scopes/ftps.md) |
|
|
83
83
|
| [`@zero-transfer/sftp`](https://www.npmjs.com/package/@zero-transfer/sftp) | SFTP with SSH key auth, known_hosts, and jump-host support. | [Scope page](docs/scopes/sftp.md) |
|
|
84
|
+
| [`@zero-transfer/ssh`](https://www.npmjs.com/package/@zero-transfer/ssh) | Standalone SSH 2.0 transport, auth, and channel primitives (exec/subsystem). | [Scope page](docs/scopes/ssh.md) |
|
|
84
85
|
| [`@zero-transfer/http`](https://www.npmjs.com/package/@zero-transfer/http) | HTTP(S) and signed-URL provider with ranged downloads. | [Scope page](docs/scopes/http.md) |
|
|
85
86
|
| [`@zero-transfer/webdav`](https://www.npmjs.com/package/@zero-transfer/webdav) | WebDAV with PROPFIND listings and ranged downloads. | [Scope page](docs/scopes/webdav.md) |
|
|
86
87
|
| [`@zero-transfer/s3`](https://www.npmjs.com/package/@zero-transfer/s3) | S3-compatible storage with SigV4, multipart upload, and cross-process resume. | [Scope page](docs/scopes/s3.md) |
|
|
@@ -120,7 +121,17 @@ await session.disconnect();
|
|
|
120
121
|
### 2. Move a file with one call
|
|
121
122
|
|
|
122
123
|
```ts
|
|
123
|
-
import { uploadFile } from "@zero-transfer/sdk";
|
|
124
|
+
import { uploadFile, type ConnectionProfile } from "@zero-transfer/sdk";
|
|
125
|
+
|
|
126
|
+
const sftpProfile: ConnectionProfile = {
|
|
127
|
+
host: "files.example.com",
|
|
128
|
+
provider: "sftp",
|
|
129
|
+
username: { env: "ZT_USER" },
|
|
130
|
+
ssh: {
|
|
131
|
+
privateKey: { path: "./keys/id_ed25519" },
|
|
132
|
+
pinnedHostKeySha256: "SHA256:base64-encoded-host-key-digest",
|
|
133
|
+
},
|
|
134
|
+
};
|
|
124
135
|
|
|
125
136
|
await uploadFile({
|
|
126
137
|
client,
|
|
@@ -130,6 +141,8 @@ await uploadFile({
|
|
|
130
141
|
});
|
|
131
142
|
```
|
|
132
143
|
|
|
144
|
+
> The `profile` shape is the same provider-neutral [`ConnectionProfile`](docs/api-md/interfaces/ConnectionProfile.md) used by `client.connect()`. See **[Connection profiles](#connection-profiles)** below for the full field reference and security guidance.
|
|
145
|
+
|
|
133
146
|
### 3. Plan a sync without touching bytes
|
|
134
147
|
|
|
135
148
|
```ts
|
|
@@ -174,6 +187,114 @@ const scheduler = new MftScheduler({
|
|
|
174
187
|
scheduler.start();
|
|
175
188
|
```
|
|
176
189
|
|
|
190
|
+
## Connection profiles
|
|
191
|
+
|
|
192
|
+
Every operation that touches a remote system takes a [`ConnectionProfile`](docs/api-md/interfaces/ConnectionProfile.md). Profiles are provider-neutral data — you build one once and pass it to `client.connect()`, `uploadFile()`, `downloadFile()`, `copyBetween()`, MFT routes, and diagnostics. The same shape works for every provider; only the optional auth blocks (`ssh`, `tls`, `oauth`, `s3`, …) change.
|
|
193
|
+
|
|
194
|
+
### Required fields
|
|
195
|
+
|
|
196
|
+
| Field | Type | Notes |
|
|
197
|
+
| ---------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
198
|
+
| `host` | `string` | Remote hostname / IP / bucket / drive identifier (provider-specific). Always required. |
|
|
199
|
+
| `provider` | [`ProviderId`](docs/api-md/type-aliases/ProviderId.md) | One of `"ftp"`, `"ftps"`, `"sftp"`, `"http"`, `"https"`, `"webdav"`, `"s3"`, `"azure-blob"`, `"gcs"`, `"google-drive"`, `"dropbox"`, `"one-drive"`, `"local"`, `"memory"`, or any custom id you registered. |
|
|
200
|
+
|
|
201
|
+
### Optional top-level fields
|
|
202
|
+
|
|
203
|
+
| Field | Type | Notes |
|
|
204
|
+
| ----------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
205
|
+
| `port` | `number` | Provider applies a sensible default when omitted. |
|
|
206
|
+
| `username` | [`SecretSource`](docs/api-md/type-aliases/SecretSource.md) | String, `{ env }`, `{ path }`, `{ base64Env }`, `{ value }`, or callback. |
|
|
207
|
+
| `password` | [`SecretSource`](docs/api-md/type-aliases/SecretSource.md) | Same shapes as `username`. Used as bearer token for cloud providers. |
|
|
208
|
+
| `secure` | `boolean` | Request encrypted transport when the protocol allows opt-in TLS. |
|
|
209
|
+
| `tls` | [`TlsProfile`](docs/api-md/interfaces/TlsProfile.md) | CA bundle, mTLS cert/key, fingerprint pinning, min/max TLS version. |
|
|
210
|
+
| `ssh` | [`SshProfile`](docs/api-md/interfaces/SshProfile.md) | Private key, passphrase, `known_hosts`, host-key pin, agent, algorithms. |
|
|
211
|
+
| `timeoutMs` | `number` | Connection / operation timeout. |
|
|
212
|
+
| `signal` | `AbortSignal` | Cancels connection setup and long-running operations. |
|
|
213
|
+
| `logger` | [`ZeroTransferLogger`](docs/api-md/interfaces/ZeroTransferLogger.md) | Per-profile structured logger override (still redaction-safe). |
|
|
214
|
+
|
|
215
|
+
### Secret-bearing fields use `SecretSource`
|
|
216
|
+
|
|
217
|
+
Every credential field (`username`, `password`, `tls.ca`, `tls.key`, `ssh.privateKey`, `ssh.knownHosts`, `ssh.passphrase`, …) accepts a [`SecretSource`](docs/api-md/type-aliases/SecretSource.md). Inline strings work for prototypes, but production code should pull from the environment, a file, or a callback so secrets stay out of source control and out of process memory dumps.
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
// Inline string — fine for tests, avoid in production.
|
|
221
|
+
password: "hunter2";
|
|
222
|
+
|
|
223
|
+
// Read from an environment variable.
|
|
224
|
+
password: {
|
|
225
|
+
env: "SFTP_PASSWORD";
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Read from a file (e.g. a Docker / Kubernetes secret mount).
|
|
229
|
+
privateKey: {
|
|
230
|
+
path: "/run/secrets/sftp_id_ed25519";
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Read base64-encoded binary from an environment variable.
|
|
234
|
+
ca: {
|
|
235
|
+
base64Env: "FTPS_CA_BUNDLE_B64";
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Pull from your vault / credential broker on demand.
|
|
239
|
+
password: async () => await vault.read("kv/sftp/deploy");
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Profiles are run through [`redactConnectionProfile()`](docs/api-md/functions/redactConnectionProfile.md) before any log line is emitted, so secret values never appear in logs, audit entries, or diagnostics.
|
|
243
|
+
|
|
244
|
+
### Worked examples
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
// SFTP with public-key auth + host-key pin (production-hardened)
|
|
248
|
+
const sftpProfile: ConnectionProfile = {
|
|
249
|
+
host: "sftp.example.com",
|
|
250
|
+
provider: "sftp",
|
|
251
|
+
username: "deploy",
|
|
252
|
+
ssh: {
|
|
253
|
+
privateKey: { path: "./keys/id_ed25519" },
|
|
254
|
+
pinnedHostKeySha256: "SHA256:abc123basesixfourpinFromKnownHosts=",
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// FTPS with mTLS + private CA bundle
|
|
259
|
+
const ftpsProfile: ConnectionProfile = {
|
|
260
|
+
host: "ftps.internal.example",
|
|
261
|
+
provider: "ftps",
|
|
262
|
+
username: "audit",
|
|
263
|
+
tls: {
|
|
264
|
+
ca: { path: "./certs/ca-bundle.pem" },
|
|
265
|
+
cert: { path: "./certs/client.crt" },
|
|
266
|
+
key: { path: "./certs/client.key" },
|
|
267
|
+
pinnedFingerprint256:
|
|
268
|
+
"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",
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
// S3-compatible bucket
|
|
273
|
+
const s3Profile: ConnectionProfile = {
|
|
274
|
+
host: "data-lake-bronze",
|
|
275
|
+
provider: "s3",
|
|
276
|
+
username: { env: "AWS_ACCESS_KEY_ID" },
|
|
277
|
+
password: { env: "AWS_SECRET_ACCESS_KEY" },
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
// Cloud drive (OAuth bearer token in `password`)
|
|
281
|
+
const dropboxProfile: ConnectionProfile = {
|
|
282
|
+
host: "",
|
|
283
|
+
provider: "dropbox",
|
|
284
|
+
password: { env: "DROPBOX_ACCESS_TOKEN" },
|
|
285
|
+
};
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Security guidance
|
|
289
|
+
|
|
290
|
+
- **Pin host keys for SSH/SFTP.** Without `ssh.knownHosts` or `ssh.pinnedHostKeySha256` the SSH session accepts any key the server presents — a MITM risk.
|
|
291
|
+
- **Pin TLS fingerprints when you control the server.** `tls.pinnedFingerprint256` is defence-in-depth on top of `rejectUnauthorized: true` and a CA bundle.
|
|
292
|
+
- **Never set `tls.rejectUnauthorized: false` in production.** Pair self-signed servers with `tls.ca` instead.
|
|
293
|
+
- **Prefer `{ env }`, `{ path }`, or callback secrets** over inline strings or hard-coded values.
|
|
294
|
+
- See [`examples/sftp-private-key.ts`](examples/sftp-private-key.ts), [`examples/ftps-client-certificate.ts`](examples/ftps-client-certificate.ts), and [`examples/profile-from-env.ts`](examples/profile-from-env.ts) for end-to-end hardened profile builds.
|
|
295
|
+
|
|
296
|
+
Full per-field reference: [`ConnectionProfile`](docs/api-md/interfaces/ConnectionProfile.md), [`SshProfile`](docs/api-md/interfaces/SshProfile.md), [`TlsProfile`](docs/api-md/interfaces/TlsProfile.md), [`SecretSource`](docs/api-md/type-aliases/SecretSource.md).
|
|
297
|
+
|
|
177
298
|
## Capability matrix
|
|
178
299
|
|
|
179
300
|
Every provider advertises its own [`CapabilitySet`](docs/api-md/interfaces/CapabilitySet.md). The full programmatic matrix is exposed via [`getBuiltinCapabilityMatrix()`](docs/api-md/functions/getBuiltinCapabilityMatrix.md) and renders to Markdown via [`formatCapabilityMatrixMarkdown()`](docs/api-md/functions/formatCapabilityMatrixMarkdown.md).
|
|
@@ -206,6 +327,7 @@ Real-world examples live in [`examples/`](https://github.com/tonywied17/zero-tra
|
|
|
206
327
|
| [`ftps-client-certificate.ts`](examples/ftps-client-certificate.ts) | FTPS hardened: mTLS + private CA bundle + fingerprint pinning. |
|
|
207
328
|
| [`sftp-basic.ts`](examples/sftp-basic.ts) | Minimal SFTP with username/password (no host-key pinning). |
|
|
208
329
|
| [`sftp-private-key.ts`](examples/sftp-private-key.ts) | SFTP hardened: private-key auth + pinned host-key SHA-256. |
|
|
330
|
+
| [`ssh-exec-command.ts`](examples/ssh-exec-command.ts) | Standalone SSH stack: handshake, auth, run a remote command. |
|
|
209
331
|
| [`s3-compatible-upload.ts`](examples/s3-compatible-upload.ts) | S3 multipart upload with cross-process resume store. |
|
|
210
332
|
| [`webdav-sync.ts`](examples/webdav-sync.ts) | WebDAV diff + sync plan with deterministic ordering. |
|
|
211
333
|
| [`signed-url-download.ts`](examples/signed-url-download.ts) | HTTPS signed-URL download with progress reporting. |
|