@zero-transfer/sdk 0.1.0-alpha.0 → 0.1.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 CHANGED
@@ -2601,6 +2601,74 @@ var FtpFileSystem = class {
2601
2601
  path: remotePath
2602
2602
  };
2603
2603
  }
2604
+ async remove(path2, options = {}) {
2605
+ const remotePath = normalizeFtpPath(path2);
2606
+ const response = await this.control.sendCommand(`DELE ${remotePath}`);
2607
+ if (response.completion) return;
2608
+ if (response.code === 550 && options.ignoreMissing) return;
2609
+ assertPathCommandSucceeded(response, "DELE", remotePath, this.control.providerId);
2610
+ }
2611
+ async rename(from, to) {
2612
+ const fromPath = normalizeFtpPath(from);
2613
+ const toPath = normalizeFtpPath(to);
2614
+ const rnfr = await this.control.sendCommand(`RNFR ${fromPath}`);
2615
+ if (!rnfr.intermediate && !rnfr.completion) {
2616
+ assertPathCommandSucceeded(rnfr, "RNFR", fromPath, this.control.providerId);
2617
+ }
2618
+ await expectCompletion(this.control, `RNTO ${toPath}`, toPath);
2619
+ }
2620
+ async mkdir(path2, options = {}) {
2621
+ const remotePath = normalizeFtpPath(path2);
2622
+ if (!options.recursive) {
2623
+ await expectCompletion(this.control, `MKD ${remotePath}`, remotePath);
2624
+ return;
2625
+ }
2626
+ const segments = remotePath.split("/").filter((s) => s.length > 0);
2627
+ let current = "";
2628
+ for (const segment of segments) {
2629
+ current = `${current}/${segment}`;
2630
+ const response = await this.control.sendCommand(`MKD ${current}`);
2631
+ if (response.completion) continue;
2632
+ if (response.code === 550) continue;
2633
+ assertPathCommandSucceeded(response, "MKD", current, this.control.providerId);
2634
+ }
2635
+ }
2636
+ async rmdir(path2, options = {}) {
2637
+ const remotePath = normalizeFtpPath(path2);
2638
+ if (options.recursive) {
2639
+ await this.removeDirectoryRecursive(remotePath);
2640
+ return;
2641
+ }
2642
+ const response = await this.control.sendCommand(`RMD ${remotePath}`);
2643
+ if (response.completion) return;
2644
+ if (response.code === 550 && options.ignoreMissing) return;
2645
+ assertPathCommandSucceeded(response, "RMD", remotePath, this.control.providerId);
2646
+ }
2647
+ async removeDirectoryRecursive(remotePath) {
2648
+ let entries;
2649
+ try {
2650
+ entries = await readDirectoryEntries(this.control, remotePath);
2651
+ } catch (error) {
2652
+ if (error instanceof PathNotFoundError) return;
2653
+ throw error;
2654
+ }
2655
+ for (const entry of entries) {
2656
+ if (entry.name === "." || entry.name === "..") continue;
2657
+ const childPath = entry.path.startsWith("/") ? entry.path : normalizeFtpPath(`${remotePath.replace(/\/+$/, "")}/${entry.name}`);
2658
+ if (entry.type === "directory") {
2659
+ await this.removeDirectoryRecursive(childPath);
2660
+ } else {
2661
+ const del = await this.control.sendCommand(`DELE ${childPath}`);
2662
+ if (!del.completion && del.code !== 550) {
2663
+ assertPathCommandSucceeded(del, "DELE", childPath, this.control.providerId);
2664
+ }
2665
+ }
2666
+ }
2667
+ const response = await this.control.sendCommand(`RMD ${remotePath}`);
2668
+ if (response.completion) return;
2669
+ if (response.code === 550) return;
2670
+ assertPathCommandSucceeded(response, "RMD", remotePath, this.control.providerId);
2671
+ }
2604
2672
  };
2605
2673
  var FtpControlConnection = class _FtpControlConnection {
2606
2674
  /**
@@ -3634,7 +3702,8 @@ function normalizeFeatureLines(input) {
3634
3702
  // src/providers/classic/sftp/SftpProvider.ts
3635
3703
  var import_node_buffer4 = require("buffer");
3636
3704
  var import_node_crypto = require("crypto");
3637
- var import_ssh2 = require("ssh2");
3705
+ var import_ssh2 = __toESM(require("ssh2"));
3706
+ var { Client: SshClientCtor, utils } = import_ssh2.default;
3638
3707
  var SFTP_PROVIDER_ID = "sftp";
3639
3708
  var SFTP_DEFAULT_PORT = 22;
3640
3709
  var SFTP_PROVIDER_CAPABILITIES = {
@@ -3792,9 +3861,104 @@ var SftpFileSystem = class {
3792
3861
  throw mapSftpError(error, { command: "LSTAT", path: remotePath });
3793
3862
  }
3794
3863
  }
3864
+ async remove(path2, options = {}) {
3865
+ throwIfAborted2(options.signal, path2, "remove");
3866
+ const remotePath = normalizeSftpPath(path2);
3867
+ try {
3868
+ await sftpUnlink(this.sftp, remotePath);
3869
+ } catch (error) {
3870
+ const mapped = mapSftpError(error, { command: "REMOVE", path: remotePath });
3871
+ if (options.ignoreMissing && mapped instanceof PathNotFoundError) return;
3872
+ throw mapped;
3873
+ }
3874
+ }
3875
+ async rename(from, to, options = {}) {
3876
+ throwIfAborted2(options.signal, from, "rename");
3877
+ const fromPath = normalizeSftpPath(from);
3878
+ const toPath = normalizeSftpPath(to);
3879
+ try {
3880
+ await sftpRename(this.sftp, fromPath, toPath);
3881
+ } catch (error) {
3882
+ throw mapSftpError(error, { command: "RENAME", path: fromPath });
3883
+ }
3884
+ }
3885
+ async mkdir(path2, options = {}) {
3886
+ throwIfAborted2(options.signal, path2, "mkdir");
3887
+ const remotePath = normalizeSftpPath(path2);
3888
+ if (!options.recursive) {
3889
+ try {
3890
+ await sftpMkdir(this.sftp, remotePath);
3891
+ } catch (error) {
3892
+ throw mapSftpError(error, { command: "MKDIR", path: remotePath });
3893
+ }
3894
+ return;
3895
+ }
3896
+ const segments = remotePath.split("/").filter((s) => s.length > 0);
3897
+ let current = "";
3898
+ for (const segment of segments) {
3899
+ current = `${current}/${segment}`;
3900
+ try {
3901
+ await sftpMkdir(this.sftp, current);
3902
+ } catch (error) {
3903
+ try {
3904
+ const stats = await readSftpStats(this.sftp, current);
3905
+ if (stats.isDirectory()) continue;
3906
+ } catch {
3907
+ }
3908
+ throw mapSftpError(error, { command: "MKDIR", path: current });
3909
+ }
3910
+ }
3911
+ }
3912
+ async rmdir(path2, options = {}) {
3913
+ throwIfAborted2(options.signal, path2, "rmdir");
3914
+ const remotePath = normalizeSftpPath(path2);
3915
+ if (options.recursive) {
3916
+ await this.removeDirectoryRecursive(remotePath);
3917
+ return;
3918
+ }
3919
+ try {
3920
+ await sftpRmdir(this.sftp, remotePath);
3921
+ } catch (error) {
3922
+ const mapped = mapSftpError(error, { command: "RMDIR", path: remotePath });
3923
+ if (options.ignoreMissing && mapped instanceof PathNotFoundError) return;
3924
+ throw mapped;
3925
+ }
3926
+ }
3927
+ async removeDirectoryRecursive(remotePath) {
3928
+ let entries;
3929
+ try {
3930
+ entries = await readSftpDirectory(this.sftp, remotePath);
3931
+ } catch (error) {
3932
+ const mapped = mapSftpError(error, { command: "READDIR", path: remotePath });
3933
+ if (mapped instanceof PathNotFoundError) return;
3934
+ throw mapped;
3935
+ }
3936
+ for (const entry of entries) {
3937
+ if (entry.filename === "." || entry.filename === "..") continue;
3938
+ const childPath = `${remotePath.replace(/\/+$/, "")}/${entry.filename}`.replace(/\/+/g, "/");
3939
+ const isDir = entry.attrs.isDirectory();
3940
+ try {
3941
+ if (isDir) {
3942
+ await this.removeDirectoryRecursive(childPath);
3943
+ } else {
3944
+ await sftpUnlink(this.sftp, childPath);
3945
+ }
3946
+ } catch (error) {
3947
+ throw mapSftpError(error, {
3948
+ command: isDir ? "RMDIR" : "REMOVE",
3949
+ path: childPath
3950
+ });
3951
+ }
3952
+ }
3953
+ try {
3954
+ await sftpRmdir(this.sftp, remotePath);
3955
+ } catch (error) {
3956
+ throw mapSftpError(error, { command: "RMDIR", path: remotePath });
3957
+ }
3958
+ }
3795
3959
  };
3796
3960
  async function connectSshClient(profile, options, username, authentication) {
3797
- const client = new import_ssh2.Client();
3961
+ const client = new SshClientCtor();
3798
3962
  let config;
3799
3963
  try {
3800
3964
  config = await createConnectConfig(profile, options, username, authentication);
@@ -3993,7 +4157,7 @@ function parseKnownHostsLine(line, lineNumber) {
3993
4157
  };
3994
4158
  }
3995
4159
  function parseKnownHostPublicKey(value, lineNumber) {
3996
- const parsed = import_ssh2.utils.parseKey(value);
4160
+ const parsed = utils.parseKey(value);
3997
4161
  if (parsed instanceof Error) {
3998
4162
  throw createKnownHostsConfigurationError(lineNumber, parsed.message);
3999
4163
  }
@@ -4183,6 +4347,50 @@ function readSftpStats(sftp, path2) {
4183
4347
  });
4184
4348
  });
4185
4349
  }
4350
+ function sftpUnlink(sftp, path2) {
4351
+ return new Promise((resolve, reject) => {
4352
+ sftp.unlink(path2, (error) => {
4353
+ if (error !== void 0 && error !== null) {
4354
+ reject(error);
4355
+ return;
4356
+ }
4357
+ resolve();
4358
+ });
4359
+ });
4360
+ }
4361
+ function sftpRename(sftp, from, to) {
4362
+ return new Promise((resolve, reject) => {
4363
+ sftp.rename(from, to, (error) => {
4364
+ if (error !== void 0 && error !== null) {
4365
+ reject(error);
4366
+ return;
4367
+ }
4368
+ resolve();
4369
+ });
4370
+ });
4371
+ }
4372
+ function sftpMkdir(sftp, path2) {
4373
+ return new Promise((resolve, reject) => {
4374
+ sftp.mkdir(path2, (error) => {
4375
+ if (error !== void 0 && error !== null) {
4376
+ reject(error);
4377
+ return;
4378
+ }
4379
+ resolve();
4380
+ });
4381
+ });
4382
+ }
4383
+ function sftpRmdir(sftp, path2) {
4384
+ return new Promise((resolve, reject) => {
4385
+ sftp.rmdir(path2, (error) => {
4386
+ if (error !== void 0 && error !== null) {
4387
+ reject(error);
4388
+ return;
4389
+ }
4390
+ resolve();
4391
+ });
4392
+ });
4393
+ }
4186
4394
  async function* createSftpReadSource(sftp, path2, range, request) {
4187
4395
  if (range.length <= 0) {
4188
4396
  return;
@@ -4510,7 +4718,8 @@ function noop() {
4510
4718
 
4511
4719
  // src/providers/classic/sftp/jumpHost.ts
4512
4720
  var import_node_buffer5 = require("buffer");
4513
- var import_ssh22 = require("ssh2");
4721
+ var import_ssh22 = __toESM(require("ssh2"));
4722
+ var { Client: SshClientCtor2 } = import_ssh22.default;
4514
4723
  function createSftpJumpHostSocketFactory(options) {
4515
4724
  if (options.bastion === void 0 && options.buildBastion === void 0) {
4516
4725
  throw new ConfigurationError({
@@ -4531,7 +4740,7 @@ function createSftpJumpHostSocketFactory(options) {
4531
4740
  }
4532
4741
  function openJumpHostChannel(options) {
4533
4742
  const { bastionConfig, context } = options;
4534
- const client = options.createClient ? options.createClient() : new import_ssh22.Client();
4743
+ const client = options.createClient ? options.createClient() : new SshClientCtor2();
4535
4744
  if (context.signal?.aborted === true) {
4536
4745
  return Promise.reject(
4537
4746
  new AbortError({
@@ -7017,7 +7226,55 @@ var LocalFileSystem = class {
7017
7226
  async stat(path2) {
7018
7227
  return readLocalEntry(this.rootPath, normalizeLocalProviderPath(path2));
7019
7228
  }
7229
+ async remove(remote, options = {}) {
7230
+ const remotePath = normalizeLocalProviderPath(remote);
7231
+ const localPath = resolveLocalPath(this.rootPath, remotePath);
7232
+ try {
7233
+ await (0, import_promises2.unlink)(localPath);
7234
+ } catch (error) {
7235
+ if (options.ignoreMissing && isNodeErrno(error, "ENOENT")) return;
7236
+ if (isNodeErrno(error, "ENOENT")) {
7237
+ throw createPathNotFoundError(remotePath, `Local path not found: ${remotePath}`);
7238
+ }
7239
+ throw error;
7240
+ }
7241
+ }
7242
+ async rename(from, to) {
7243
+ const fromRemote = normalizeLocalProviderPath(from);
7244
+ const toRemote = normalizeLocalProviderPath(to);
7245
+ const fromLocal = resolveLocalPath(this.rootPath, fromRemote);
7246
+ const toLocal = resolveLocalPath(this.rootPath, toRemote);
7247
+ try {
7248
+ await (0, import_promises2.rename)(fromLocal, toLocal);
7249
+ } catch (error) {
7250
+ if (isNodeErrno(error, "ENOENT")) {
7251
+ throw createPathNotFoundError(fromRemote, `Local path not found: ${fromRemote}`);
7252
+ }
7253
+ throw error;
7254
+ }
7255
+ }
7256
+ async mkdir(remote, options = {}) {
7257
+ const remotePath = normalizeLocalProviderPath(remote);
7258
+ const localPath = resolveLocalPath(this.rootPath, remotePath);
7259
+ await (0, import_promises2.mkdir)(localPath, { recursive: options.recursive === true });
7260
+ }
7261
+ async rmdir(remote, options = {}) {
7262
+ const remotePath = normalizeLocalProviderPath(remote);
7263
+ const localPath = resolveLocalPath(this.rootPath, remotePath);
7264
+ try {
7265
+ await (0, import_promises2.rm)(localPath, { recursive: options.recursive === true, force: false });
7266
+ } catch (error) {
7267
+ if (isNodeErrno(error, "ENOENT")) {
7268
+ if (options.ignoreMissing) return;
7269
+ throw createPathNotFoundError(remotePath, `Local path not found: ${remotePath}`);
7270
+ }
7271
+ throw error;
7272
+ }
7273
+ }
7020
7274
  };
7275
+ function isNodeErrno(error, code) {
7276
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
7277
+ }
7021
7278
  function resolveReadRange2(size, range) {
7022
7279
  if (range === void 0) {
7023
7280
  return { length: size, offset: 0 };
@@ -7180,6 +7437,11 @@ function normalizeLocalProviderPath(input) {
7180
7437
  }
7181
7438
  function resolveLocalPath(rootPath, remotePath) {
7182
7439
  const normalizedRemotePath = normalizeLocalProviderPath(remotePath);
7440
+ const resolvedRootPath = import_node_path2.default.resolve(rootPath);
7441
+ const candidateAbsolute = import_node_path2.default.resolve(normalizedRemotePath.split("/").join(import_node_path2.default.sep));
7442
+ if (candidateAbsolute === resolvedRootPath || candidateAbsolute.startsWith(resolvedRootPath + import_node_path2.default.sep)) {
7443
+ return candidateAbsolute;
7444
+ }
7183
7445
  const relativePath = normalizedRemotePath === "/" ? "." : normalizedRemotePath.slice(1);
7184
7446
  const resolvedPath = import_node_path2.default.resolve(rootPath, relativePath.split("/").join(import_node_path2.default.sep));
7185
7447
  const relativeToRoot = import_node_path2.default.relative(rootPath, resolvedPath);
@@ -7331,6 +7593,96 @@ var MemoryFileSystem = class {
7331
7593
  () => cloneRemoteStat(this.requireEntry(normalizeMemoryPath(path2)))
7332
7594
  );
7333
7595
  }
7596
+ remove(path2, options = {}) {
7597
+ return Promise.resolve().then(() => {
7598
+ const normalized = normalizeMemoryPath(path2);
7599
+ const entry = this.state.entries.get(normalized);
7600
+ if (entry === void 0) {
7601
+ if (options.ignoreMissing) return;
7602
+ throw createPathNotFoundError2(normalized, `Memory path not found: ${normalized}`);
7603
+ }
7604
+ if (entry.type === "directory") {
7605
+ throw createPathNotFoundError2(
7606
+ normalized,
7607
+ `Memory path is a directory; use rmdir: ${normalized}`
7608
+ );
7609
+ }
7610
+ this.state.entries.delete(normalized);
7611
+ this.state.content.delete(normalized);
7612
+ });
7613
+ }
7614
+ rename(from, to) {
7615
+ return Promise.resolve().then(() => {
7616
+ const fromPath = normalizeMemoryPath(from);
7617
+ const toPath = normalizeMemoryPath(to);
7618
+ const entry = this.state.entries.get(fromPath);
7619
+ if (entry === void 0) {
7620
+ throw createPathNotFoundError2(fromPath, `Memory path not found: ${fromPath}`);
7621
+ }
7622
+ ensureParentDirectories(this.state.entries, toPath);
7623
+ const moved = { ...entry, path: toPath, name: basenameRemotePath(toPath) };
7624
+ this.state.entries.delete(fromPath);
7625
+ this.state.entries.set(toPath, moved);
7626
+ const content = this.state.content.get(fromPath);
7627
+ if (content !== void 0) {
7628
+ this.state.content.delete(fromPath);
7629
+ this.state.content.set(toPath, content);
7630
+ }
7631
+ });
7632
+ }
7633
+ mkdir(path2, options = {}) {
7634
+ return Promise.resolve().then(() => {
7635
+ const normalized = normalizeMemoryPath(path2);
7636
+ const existing = this.state.entries.get(normalized);
7637
+ if (existing !== void 0) {
7638
+ if (existing.type === "directory" && options.recursive) return;
7639
+ throw createInvalidFixtureError(normalized, `Memory path already exists: ${normalized}`);
7640
+ }
7641
+ if (options.recursive) {
7642
+ ensureParentDirectories(this.state.entries, normalized);
7643
+ } else {
7644
+ const parent = getParentPath2(normalized);
7645
+ if (parent !== void 0 && !this.state.entries.has(parent)) {
7646
+ throw createPathNotFoundError2(parent, `Memory parent not found: ${parent}`);
7647
+ }
7648
+ }
7649
+ this.state.entries.set(normalized, createDirectoryEntry(normalized));
7650
+ });
7651
+ }
7652
+ rmdir(path2, options = {}) {
7653
+ return Promise.resolve().then(() => {
7654
+ const normalized = normalizeMemoryPath(path2);
7655
+ const entry = this.state.entries.get(normalized);
7656
+ if (entry === void 0) {
7657
+ if (options.ignoreMissing) return;
7658
+ throw createPathNotFoundError2(normalized, `Memory path not found: ${normalized}`);
7659
+ }
7660
+ if (entry.type !== "directory") {
7661
+ throw createPathNotFoundError2(normalized, `Memory path is not a directory: ${normalized}`);
7662
+ }
7663
+ const children = [...this.state.entries.values()].filter(
7664
+ (child) => child.path !== normalized && getParentPath2(child.path) === normalized
7665
+ );
7666
+ if (children.length > 0 && !options.recursive) {
7667
+ throw createInvalidFixtureError(normalized, `Memory directory not empty: ${normalized}`);
7668
+ }
7669
+ const stack = [...children];
7670
+ while (stack.length > 0) {
7671
+ const next = stack.pop();
7672
+ if (!next) continue;
7673
+ if (next.type === "directory") {
7674
+ for (const grand of this.state.entries.values()) {
7675
+ if (grand.path !== next.path && getParentPath2(grand.path) === next.path) {
7676
+ stack.push(grand);
7677
+ }
7678
+ }
7679
+ }
7680
+ this.state.entries.delete(next.path);
7681
+ this.state.content.delete(next.path);
7682
+ }
7683
+ this.state.entries.delete(normalized);
7684
+ });
7685
+ }
7334
7686
  requireEntry(path2) {
7335
7687
  const entry = this.state.entries.get(path2);
7336
7688
  if (entry === void 0) {