@zero-transfer/sdk 0.1.1 → 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
  /**
@@ -3793,6 +3861,101 @@ var SftpFileSystem = class {
3793
3861
  throw mapSftpError(error, { command: "LSTAT", path: remotePath });
3794
3862
  }
3795
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
+ }
3796
3959
  };
3797
3960
  async function connectSshClient(profile, options, username, authentication) {
3798
3961
  const client = new SshClientCtor();
@@ -4184,6 +4347,50 @@ function readSftpStats(sftp, path2) {
4184
4347
  });
4185
4348
  });
4186
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
+ }
4187
4394
  async function* createSftpReadSource(sftp, path2, range, request) {
4188
4395
  if (range.length <= 0) {
4189
4396
  return;
@@ -7019,7 +7226,55 @@ var LocalFileSystem = class {
7019
7226
  async stat(path2) {
7020
7227
  return readLocalEntry(this.rootPath, normalizeLocalProviderPath(path2));
7021
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
+ }
7022
7274
  };
7275
+ function isNodeErrno(error, code) {
7276
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
7277
+ }
7023
7278
  function resolveReadRange2(size, range) {
7024
7279
  if (range === void 0) {
7025
7280
  return { length: size, offset: 0 };
@@ -7338,6 +7593,96 @@ var MemoryFileSystem = class {
7338
7593
  () => cloneRemoteStat(this.requireEntry(normalizeMemoryPath(path2)))
7339
7594
  );
7340
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
+ }
7341
7686
  requireEntry(path2) {
7342
7687
  const entry = this.state.entries.get(path2);
7343
7688
  if (entry === void 0) {