@simplysm/storage 13.0.77 → 13.0.80
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 +104 -209
- package/dist/clients/ftp-storage-client.d.ts +3 -3
- package/dist/clients/ftp-storage-client.d.ts.map +1 -1
- package/dist/clients/ftp-storage-client.js +2 -2
- package/dist/clients/ftp-storage-client.js.map +1 -1
- package/dist/clients/sftp-storage-client.d.ts +3 -3
- package/dist/clients/sftp-storage-client.d.ts.map +1 -1
- package/dist/clients/sftp-storage-client.js +3 -3
- package/dist/clients/sftp-storage-client.js.map +1 -1
- package/dist/storage-factory.d.ts +3 -3
- package/dist/storage-factory.d.ts.map +1 -1
- package/dist/storage-factory.js.map +1 -1
- package/dist/types/storage-conn-config.d.ts +1 -1
- package/dist/types/storage-conn-config.d.ts.map +1 -1
- package/dist/types/storage-type.d.ts +1 -1
- package/dist/types/storage-type.d.ts.map +1 -1
- package/dist/types/storage.d.ts +2 -2
- package/dist/types/storage.d.ts.map +1 -1
- package/package.json +4 -3
- package/src/clients/ftp-storage-client.ts +4 -4
- package/src/clients/sftp-storage-client.ts +5 -5
- package/src/storage-factory.ts +5 -5
- package/src/types/storage-conn-config.ts +1 -1
- package/src/types/storage-type.ts +1 -1
- package/src/types/storage.ts +2 -2
- package/tests/ftp-storage-client.spec.ts +5 -5
- package/tests/sftp-storage-client.spec.ts +6 -6
package/README.md
CHANGED
|
@@ -1,265 +1,160 @@
|
|
|
1
1
|
# @simplysm/storage
|
|
2
2
|
|
|
3
|
-
Simplysm Package - Storage Module (node)
|
|
3
|
+
> Simplysm Package - Storage Module (node)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A unified storage client library for Node.js that provides a consistent API for FTP, FTPS, and SFTP file operations. The factory pattern with automatic connection management makes it easy to perform remote file operations without worrying about connection lifecycle. Internally uses [basic-ftp](https://www.npmjs.com/package/basic-ftp) for FTP/FTPS and [ssh2-sftp-client](https://www.npmjs.com/package/ssh2-sftp-client) for SFTP.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## API Reference
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
pnpm add @simplysm/storage
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Main Modules
|
|
14
|
-
|
|
15
|
-
### Types
|
|
16
|
-
|
|
17
|
-
#### `StorageConnConfig`
|
|
9
|
+
### StorageProtocol
|
|
18
10
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
```ts
|
|
22
|
-
import { StorageConnConfig } from "@simplysm/storage";
|
|
23
|
-
|
|
24
|
-
const config: StorageConnConfig = {
|
|
25
|
-
host: "storage.example.com",
|
|
26
|
-
port: 22, // optional — defaults to the protocol default
|
|
27
|
-
user: "admin", // optional
|
|
28
|
-
pass: "secret", // optional
|
|
29
|
-
};
|
|
11
|
+
```typescript
|
|
12
|
+
type StorageProtocol = "ftp" | "ftps" | "sftp";
|
|
30
13
|
```
|
|
31
14
|
|
|
32
|
-
|
|
33
|
-
| -------- | -------- | -------- | ---------------------------------------- |
|
|
34
|
-
| `host` | `string` | yes | Hostname or IP address of the server |
|
|
35
|
-
| `port` | `number` | no | Port number (defaults to protocol default) |
|
|
36
|
-
| `user` | `string` | no | Username for authentication |
|
|
37
|
-
| `pass` | `string` | no | Password for authentication |
|
|
15
|
+
Union type representing the supported storage protocols.
|
|
38
16
|
|
|
39
17
|
---
|
|
40
18
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
Describes a single entry returned by `readdir`.
|
|
19
|
+
### StorageConnConfig
|
|
44
20
|
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
21
|
+
```typescript
|
|
22
|
+
interface StorageConnConfig {
|
|
23
|
+
host: string;
|
|
24
|
+
port?: number;
|
|
25
|
+
user?: string;
|
|
26
|
+
password?: string;
|
|
27
|
+
}
|
|
50
28
|
```
|
|
51
29
|
|
|
52
|
-
|
|
53
|
-
| -------- | --------- | -------------------------------------------- |
|
|
54
|
-
| `name` | `string` | File or directory name (not the full path) |
|
|
55
|
-
| `isFile` | `boolean` | `true` if it is a file, `false` if directory |
|
|
30
|
+
Connection configuration shared across all protocols. When `password` is omitted for SFTP, authentication falls back to SSH agent and `~/.ssh/id_ed25519` key file.
|
|
56
31
|
|
|
57
32
|
---
|
|
58
33
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
The unified storage interface implemented by all client classes. Use this type when writing code that is protocol-agnostic.
|
|
62
|
-
|
|
63
|
-
```ts
|
|
64
|
-
import { Storage } from "@simplysm/storage";
|
|
34
|
+
### FileInfo
|
|
65
35
|
|
|
66
|
-
|
|
67
|
-
|
|
36
|
+
```typescript
|
|
37
|
+
interface FileInfo {
|
|
38
|
+
name: string;
|
|
39
|
+
isFile: boolean;
|
|
68
40
|
}
|
|
69
41
|
```
|
|
70
42
|
|
|
71
|
-
|
|
72
|
-
| ------------------------------------------------------------- | --------------------- | ------------------------------------------------------------- |
|
|
73
|
-
| `connect(config: StorageConnConfig)` | `Promise<void>` | Open a connection to the server |
|
|
74
|
-
| `mkdir(dirPath: string)` | `Promise<void>` | Create a directory (including parents) |
|
|
75
|
-
| `rename(fromPath: string, toPath: string)` | `Promise<void>` | Rename or move a remote path |
|
|
76
|
-
| `readdir(dirPath: string)` | `Promise<FileInfo[]>` | List entries in a directory |
|
|
77
|
-
| `readFile(filePath: string)` | `Promise<Bytes>` | Download a file as raw bytes |
|
|
78
|
-
| `exists(filePath: string)` | `Promise<boolean>` | Check whether a path exists |
|
|
79
|
-
| `put(localPathOrBuffer: string \| Bytes, storageFilePath: string)` | `Promise<void>` | Upload a local file path or byte buffer to the remote path |
|
|
80
|
-
| `uploadDir(fromPath: string, toPath: string)` | `Promise<void>` | Upload an entire local directory to a remote path |
|
|
81
|
-
| `remove(filePath: string)` | `Promise<void>` | Delete a remote file |
|
|
82
|
-
| `close()` | `Promise<void>` | Close the connection |
|
|
43
|
+
Represents a file or directory entry returned by `list()`.
|
|
83
44
|
|
|
84
45
|
---
|
|
85
46
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
47
|
+
### StorageClient
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
interface StorageClient {
|
|
51
|
+
connect(config: StorageConnConfig): Promise<void>;
|
|
52
|
+
mkdir(dirPath: string): Promise<void>;
|
|
53
|
+
rename(fromPath: string, toPath: string): Promise<void>;
|
|
54
|
+
list(dirPath: string): Promise<FileInfo[]>;
|
|
55
|
+
readFile(filePath: string): Promise<Bytes>;
|
|
56
|
+
exists(filePath: string): Promise<boolean>;
|
|
57
|
+
put(localPathOrBuffer: string | Bytes, storageFilePath: string): Promise<void>;
|
|
58
|
+
uploadDir(fromPath: string, toPath: string): Promise<void>;
|
|
59
|
+
remove(filePath: string): Promise<void>;
|
|
60
|
+
close(): Promise<void>;
|
|
61
|
+
}
|
|
94
62
|
```
|
|
95
63
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
|
99
|
-
|
|
100
|
-
| `
|
|
64
|
+
Common interface implemented by all storage clients. Using `StorageFactory.connect()` is recommended over calling these methods directly, as it manages the connection lifecycle automatically.
|
|
65
|
+
|
|
66
|
+
| Method | Description |
|
|
67
|
+
|--------|-------------|
|
|
68
|
+
| `connect` | Open a connection to the remote server. |
|
|
69
|
+
| `mkdir` | Create a directory, including parent directories. |
|
|
70
|
+
| `rename` | Rename or move a remote file/directory. |
|
|
71
|
+
| `list` | List entries in a remote directory. |
|
|
72
|
+
| `readFile` | Read the contents of a remote file as `Bytes`. |
|
|
73
|
+
| `exists` | Check whether a remote file or directory exists. |
|
|
74
|
+
| `put` | Upload a local file path or byte data to a remote path. |
|
|
75
|
+
| `uploadDir` | Upload an entire local directory to a remote path. |
|
|
76
|
+
| `remove` | Delete a remote file. |
|
|
77
|
+
| `close` | Close the connection. Safe to call when already closed. |
|
|
101
78
|
|
|
102
79
|
---
|
|
103
80
|
|
|
104
|
-
###
|
|
81
|
+
### StorageFactory
|
|
105
82
|
|
|
106
|
-
|
|
83
|
+
```typescript
|
|
84
|
+
class StorageFactory {
|
|
85
|
+
static connect<R>(
|
|
86
|
+
type: StorageProtocol,
|
|
87
|
+
config: StorageConnConfig,
|
|
88
|
+
fn: (storage: StorageClient) => R | Promise<R>,
|
|
89
|
+
): Promise<R>;
|
|
90
|
+
}
|
|
91
|
+
```
|
|
107
92
|
|
|
108
|
-
|
|
93
|
+
Factory class that creates protocol-specific clients and manages the connection lifecycle. The `connect` method opens a connection, passes the client to the callback, and guarantees the connection is closed afterwards (even if the callback throws).
|
|
109
94
|
|
|
110
|
-
|
|
111
|
-
Using `StorageFactory.connect` is recommended over direct instantiation.
|
|
95
|
+
---
|
|
112
96
|
|
|
113
|
-
|
|
114
|
-
import { FtpStorageClient } from "@simplysm/storage";
|
|
97
|
+
### FtpStorageClient
|
|
115
98
|
|
|
116
|
-
|
|
117
|
-
|
|
99
|
+
```typescript
|
|
100
|
+
class FtpStorageClient implements StorageClient {
|
|
101
|
+
constructor(secure?: boolean);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
118
104
|
|
|
119
|
-
|
|
120
|
-
const secureClient = new FtpStorageClient(true);
|
|
105
|
+
FTP/FTPS storage client built on [basic-ftp](https://www.npmjs.com/package/basic-ftp). Pass `true` for the `secure` parameter to use FTPS. Using `StorageFactory.connect()` is recommended over direct instantiation.
|
|
121
106
|
|
|
122
|
-
|
|
107
|
+
---
|
|
123
108
|
|
|
124
|
-
|
|
125
|
-
const entries = await client.readdir("/uploads");
|
|
126
|
-
console.log(entries);
|
|
109
|
+
### SftpStorageClient
|
|
127
110
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
console.log(exists); // true
|
|
131
|
-
} finally {
|
|
132
|
-
await client.close();
|
|
111
|
+
```typescript
|
|
112
|
+
class SftpStorageClient implements StorageClient {
|
|
133
113
|
}
|
|
134
114
|
```
|
|
135
115
|
|
|
136
|
-
|
|
116
|
+
SFTP storage client built on [ssh2-sftp-client](https://www.npmjs.com/package/ssh2-sftp-client). When no password is provided, authenticates via SSH agent or `~/.ssh/id_ed25519` key file. Using `StorageFactory.connect()` is recommended over direct instantiation.
|
|
137
117
|
|
|
138
|
-
|
|
139
|
-
new FtpStorageClient(secure?: boolean)
|
|
140
|
-
```
|
|
118
|
+
---
|
|
141
119
|
|
|
142
|
-
|
|
143
|
-
| --------- | --------- | ------- | ---------------------------------------- |
|
|
144
|
-
| `secure` | `boolean` | `false` | `true` to use FTPS (TLS), `false` for FTP |
|
|
145
|
-
|
|
146
|
-
**Methods** — all defined by the `Storage` interface.
|
|
147
|
-
|
|
148
|
-
| Method | Notes |
|
|
149
|
-
| -------------- | --------------------------------------------------------------------------------------------------- |
|
|
150
|
-
| `connect` | Throws if already connected. Use `StorageFactory.connect` to avoid manual lifecycle management. |
|
|
151
|
-
| `mkdir` | Creates parent directories automatically. |
|
|
152
|
-
| `rename` | Renames or moves a remote path. |
|
|
153
|
-
| `readdir` | Returns a list of `FileInfo` entries for the given directory. |
|
|
154
|
-
| `readFile` | Downloads and returns file content as `Bytes`. |
|
|
155
|
-
| `exists` | Uses `size()` for files (O(1)) and `list()` for directories. Returns `false` on any error. |
|
|
156
|
-
| `put` | Accepts a local file path string or a `Bytes` buffer. |
|
|
157
|
-
| `uploadDir` | Recursively uploads a local directory. |
|
|
158
|
-
| `remove` | Deletes a remote file. |
|
|
159
|
-
| `close` | Safe to call when already closed. Can reconnect on the same instance after closing. |
|
|
120
|
+
## Usage Examples
|
|
160
121
|
|
|
161
|
-
|
|
122
|
+
### Recommended: Using StorageFactory (auto-managed connection)
|
|
162
123
|
|
|
163
|
-
|
|
124
|
+
```typescript
|
|
125
|
+
import { StorageFactory } from "@simplysm/storage";
|
|
164
126
|
|
|
165
|
-
|
|
127
|
+
// Upload a file via SFTP
|
|
128
|
+
await StorageFactory.connect("sftp", { host: "example.com", user: "deploy" }, async (storage) => {
|
|
129
|
+
await storage.mkdir("/uploads/2024");
|
|
130
|
+
await storage.put("/local/path/file.txt", "/uploads/2024/file.txt");
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// List files via FTP
|
|
134
|
+
const files = await StorageFactory.connect("ftp", { host: "ftp.example.com", user: "admin", password: "secret" }, async (storage) => {
|
|
135
|
+
return await storage.list("/data");
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Upload a directory via FTPS
|
|
139
|
+
await StorageFactory.connect("ftps", { host: "secure.example.com", user: "admin", password: "secret" }, async (storage) => {
|
|
140
|
+
await storage.uploadDir("/local/dist", "/remote/dist");
|
|
141
|
+
});
|
|
142
|
+
```
|
|
166
143
|
|
|
167
|
-
|
|
168
|
-
Using `StorageFactory.connect` is recommended over direct instantiation.
|
|
144
|
+
### Direct client usage
|
|
169
145
|
|
|
170
|
-
```
|
|
146
|
+
```typescript
|
|
171
147
|
import { SftpStorageClient } from "@simplysm/storage";
|
|
172
148
|
|
|
173
149
|
const client = new SftpStorageClient();
|
|
174
|
-
|
|
175
|
-
// Password authentication
|
|
176
|
-
await client.connect({ host: "sftp.example.com", port: 22, user: "user", pass: "pass" });
|
|
177
|
-
|
|
178
|
-
// Key-based authentication (omit pass)
|
|
179
|
-
await client.connect({ host: "sftp.example.com", user: "user" });
|
|
180
|
-
|
|
150
|
+
await client.connect({ host: "example.com", user: "deploy", password: "secret" });
|
|
181
151
|
try {
|
|
182
|
-
await client.
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
152
|
+
const exists = await client.exists("/remote/file.txt");
|
|
153
|
+
if (exists) {
|
|
154
|
+
const data = await client.readFile("/remote/file.txt");
|
|
155
|
+
}
|
|
156
|
+
await client.put(Buffer.from("hello"), "/remote/hello.txt");
|
|
186
157
|
} finally {
|
|
187
158
|
await client.close();
|
|
188
159
|
}
|
|
189
160
|
```
|
|
190
|
-
|
|
191
|
-
**Constructor**
|
|
192
|
-
|
|
193
|
-
```ts
|
|
194
|
-
new SftpStorageClient()
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
No constructor parameters.
|
|
198
|
-
|
|
199
|
-
**Methods** — all defined by the `Storage` interface.
|
|
200
|
-
|
|
201
|
-
| Method | Notes |
|
|
202
|
-
| -------------- | ------------------------------------------------------------------------------------------------------- |
|
|
203
|
-
| `connect` | Throws if already connected. When `pass` is absent, authenticates via SSH agent / `~/.ssh/id_ed25519`. |
|
|
204
|
-
| `mkdir` | Creates parent directories automatically. |
|
|
205
|
-
| `rename` | Renames or moves a remote path. |
|
|
206
|
-
| `readdir` | Returns a list of `FileInfo` entries for the given directory. |
|
|
207
|
-
| `readFile` | Downloads and returns file content as `Bytes`. |
|
|
208
|
-
| `exists` | Returns `false` even when the parent directory does not exist, or on any error. |
|
|
209
|
-
| `put` | Accepts a local file path string (uses `fastPut`) or a `Bytes` buffer. |
|
|
210
|
-
| `uploadDir` | Recursively uploads a local directory. |
|
|
211
|
-
| `remove` | Deletes a remote file. |
|
|
212
|
-
| `close` | Safe to call when already closed. Can reconnect on the same instance after closing. |
|
|
213
|
-
|
|
214
|
-
---
|
|
215
|
-
|
|
216
|
-
### Factory
|
|
217
|
-
|
|
218
|
-
#### `StorageFactory`
|
|
219
|
-
|
|
220
|
-
Creates and manages storage client connections. Preferred over constructing clients directly.
|
|
221
|
-
|
|
222
|
-
**`StorageFactory.connect`** (static)
|
|
223
|
-
|
|
224
|
-
Connects to storage, executes the callback, and closes the connection automatically — even if the callback throws.
|
|
225
|
-
|
|
226
|
-
```ts
|
|
227
|
-
import { StorageFactory } from "@simplysm/storage";
|
|
228
|
-
|
|
229
|
-
const result = await StorageFactory.connect(
|
|
230
|
-
"sftp",
|
|
231
|
-
{ host: "sftp.example.com", user: "deploy", pass: "secret" },
|
|
232
|
-
async (storage) => {
|
|
233
|
-
await storage.mkdir("/var/www/releases/v2");
|
|
234
|
-
await storage.uploadDir("/local/build", "/var/www/releases/v2");
|
|
235
|
-
return await storage.readdir("/var/www/releases/v2");
|
|
236
|
-
},
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
console.log(result); // FileInfo[]
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
```ts
|
|
243
|
-
static connect<R>(
|
|
244
|
-
type: StorageType,
|
|
245
|
-
config: StorageConnConfig,
|
|
246
|
-
fn: (storage: Storage) => R | Promise<R>,
|
|
247
|
-
): Promise<R>
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
| Parameter | Type | Description |
|
|
251
|
-
| --------- | --------------------------------- | ---------------------------------------------------- |
|
|
252
|
-
| `type` | `StorageType` | Protocol: `"ftp"`, `"ftps"`, or `"sftp"` |
|
|
253
|
-
| `config` | `StorageConnConfig` | Connection parameters (host, port, user, pass) |
|
|
254
|
-
| `fn` | `(storage: Storage) => R \| Promise<R>` | Callback that receives the connected client |
|
|
255
|
-
|
|
256
|
-
Returns a `Promise<R>` that resolves to the value returned by `fn`.
|
|
257
|
-
|
|
258
|
-
## Types
|
|
259
|
-
|
|
260
|
-
| Name | Kind | Description |
|
|
261
|
-
| ------------------- | ----------- | --------------------------------------------------- |
|
|
262
|
-
| `StorageConnConfig` | `interface` | Connection configuration (host, port, user, pass) |
|
|
263
|
-
| `FileInfo` | `interface` | File/directory entry returned by `readdir` |
|
|
264
|
-
| `Storage` | `interface` | Unified interface implemented by all storage clients |
|
|
265
|
-
| `StorageType` | `type` | Protocol discriminant: `"ftp" \| "ftps" \| "sftp"` |
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Bytes } from "@simplysm/core-common";
|
|
2
|
-
import type {
|
|
2
|
+
import type { StorageClient, FileInfo } from "../types/storage";
|
|
3
3
|
import type { StorageConnConfig } from "../types/storage-conn-config";
|
|
4
4
|
/**
|
|
5
5
|
* Storage client using FTP/FTPS protocol.
|
|
@@ -8,7 +8,7 @@ import type { StorageConnConfig } from "../types/storage-conn-config";
|
|
|
8
8
|
* The `secure` constructor parameter configures whether to use FTPS.
|
|
9
9
|
* Using {@link StorageFactory.connect} is recommended over direct usage.
|
|
10
10
|
*/
|
|
11
|
-
export declare class FtpStorageClient implements
|
|
11
|
+
export declare class FtpStorageClient implements StorageClient {
|
|
12
12
|
private readonly _secure;
|
|
13
13
|
private _client;
|
|
14
14
|
constructor(_secure?: boolean);
|
|
@@ -25,7 +25,7 @@ export declare class FtpStorageClient implements Storage {
|
|
|
25
25
|
/** Create a directory. Creates parent directories if they do not exist. */
|
|
26
26
|
mkdir(dirPath: string): Promise<void>;
|
|
27
27
|
rename(fromPath: string, toPath: string): Promise<void>;
|
|
28
|
-
|
|
28
|
+
list(dirPath: string): Promise<FileInfo[]>;
|
|
29
29
|
readFile(filePath: string): Promise<Bytes>;
|
|
30
30
|
/**
|
|
31
31
|
* Check whether a file or directory exists.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ftp-storage-client.d.ts","sourceRoot":"","sources":["..\\..\\src\\clients\\ftp-storage-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAInD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"ftp-storage-client.d.ts","sourceRoot":"","sources":["..\\..\\src\\clients\\ftp-storage-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAInD,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEtE;;;;;;GAMG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IAGxC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,OAAO,CAAyB;gBAEX,OAAO,GAAE,OAAe;IAErD;;;;;;;OAOG;IACG,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBvD,OAAO,CAAC,cAAc;IAOtB,2EAA2E;IACrE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAK1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAWhD;;;;;;;;;;;OAWG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmB1C,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,gEAAgE;IAC1D,GAAG,CAAC,iBAAiB,EAAE,MAAM,GAAG,KAAK,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9E,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE;;;;;;OAMG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CASvB"}
|
|
@@ -24,7 +24,7 @@ class FtpStorageClient {
|
|
|
24
24
|
host: config.host,
|
|
25
25
|
port: config.port,
|
|
26
26
|
user: config.user,
|
|
27
|
-
password: config.
|
|
27
|
+
password: config.password,
|
|
28
28
|
secure: this._secure
|
|
29
29
|
});
|
|
30
30
|
this._client = client;
|
|
@@ -46,7 +46,7 @@ class FtpStorageClient {
|
|
|
46
46
|
async rename(fromPath, toPath) {
|
|
47
47
|
await this._requireClient().rename(fromPath, toPath);
|
|
48
48
|
}
|
|
49
|
-
async
|
|
49
|
+
async list(dirPath) {
|
|
50
50
|
const fileInfos = await this._requireClient().list(dirPath);
|
|
51
51
|
return fileInfos.map((item) => ({ name: item.name, isFile: item.isFile }));
|
|
52
52
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/clients/ftp-storage-client.ts"],
|
|
4
|
-
"mappings": "AACA,SAAS,OAAO,eAAe;AAC/B,OAAO,SAAS;AAChB,SAAS,aAAa,gBAAgB;AAW/B,MAAM,
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Bytes } from "@simplysm/core-common";
|
|
2
|
-
import type {
|
|
2
|
+
import type { StorageClient, FileInfo } from "../types/storage";
|
|
3
3
|
import type { StorageConnConfig } from "../types/storage-conn-config";
|
|
4
4
|
/**
|
|
5
5
|
* Storage client using SFTP protocol.
|
|
@@ -7,7 +7,7 @@ import type { StorageConnConfig } from "../types/storage-conn-config";
|
|
|
7
7
|
* @remarks
|
|
8
8
|
* Using {@link StorageFactory.connect} is recommended over direct usage.
|
|
9
9
|
*/
|
|
10
|
-
export declare class SftpStorageClient implements
|
|
10
|
+
export declare class SftpStorageClient implements StorageClient {
|
|
11
11
|
private _client;
|
|
12
12
|
/**
|
|
13
13
|
* Connect to the SFTP server.
|
|
@@ -30,7 +30,7 @@ export declare class SftpStorageClient implements Storage {
|
|
|
30
30
|
* Returns false for all exceptions including network errors and permission errors.
|
|
31
31
|
*/
|
|
32
32
|
exists(filePath: string): Promise<boolean>;
|
|
33
|
-
|
|
33
|
+
list(dirPath: string): Promise<FileInfo[]>;
|
|
34
34
|
readFile(filePath: string): Promise<Bytes>;
|
|
35
35
|
remove(filePath: string): Promise<void>;
|
|
36
36
|
/** Upload a local file path or byte data to the remote path. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sftp-storage-client.d.ts","sourceRoot":"","sources":["..\\..\\src\\clients\\sftp-storage-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAGnD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"sftp-storage-client.d.ts","sourceRoot":"","sources":["..\\..\\src\\clients\\sftp-storage-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAGnD,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAKtE;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IACrD,OAAO,CAAC,OAAO,CAAyB;IAExC;;;;;;;OAOG;IACG,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IA6CvD,OAAO,CAAC,cAAc;IAOtB,2EAA2E;IACrE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7D;;;;;;OAMG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAW1C,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAQ1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAc1C,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,gEAAgE;IAC1D,GAAG,CAAC,iBAAiB,EAAE,MAAM,GAAG,KAAK,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS9E,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE;;;;;;OAMG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B"}
|
|
@@ -16,12 +16,12 @@ class SftpStorageClient {
|
|
|
16
16
|
}
|
|
17
17
|
const client = new SftpClient();
|
|
18
18
|
try {
|
|
19
|
-
if (config.
|
|
19
|
+
if (config.password != null) {
|
|
20
20
|
await client.connect({
|
|
21
21
|
host: config.host,
|
|
22
22
|
port: config.port,
|
|
23
23
|
username: config.user,
|
|
24
|
-
password: config.
|
|
24
|
+
password: config.password
|
|
25
25
|
});
|
|
26
26
|
} else {
|
|
27
27
|
const fsP = await import("fs/promises");
|
|
@@ -77,7 +77,7 @@ class SftpStorageClient {
|
|
|
77
77
|
return false;
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
-
async
|
|
80
|
+
async list(dirPath) {
|
|
81
81
|
const list = await this._requireClient().list(dirPath);
|
|
82
82
|
return list.map((item) => ({
|
|
83
83
|
name: item.name,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/clients/sftp-storage-client.ts"],
|
|
4
|
-
"mappings": "AACA,SAAS,eAAe;AACxB,OAAO,gBAAgB;AAahB,MAAM,
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { StorageConnConfig } from "./types/storage-conn-config";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { StorageClient } from "./types/storage";
|
|
3
|
+
import type { StorageProtocol } from "./types/storage-type";
|
|
4
4
|
/**
|
|
5
5
|
* Storage client factory
|
|
6
6
|
*
|
|
@@ -14,7 +14,7 @@ export declare class StorageFactory {
|
|
|
14
14
|
* The callback pattern auto-manages connection/close, so this is preferred over direct client usage.
|
|
15
15
|
* The connection is automatically closed even if the callback throws an exception.
|
|
16
16
|
*/
|
|
17
|
-
static connect<R>(type:
|
|
17
|
+
static connect<R>(type: StorageProtocol, config: StorageConnConfig, fn: (storage: StorageClient) => R | Promise<R>): Promise<R>;
|
|
18
18
|
private static _createClient;
|
|
19
19
|
}
|
|
20
20
|
//# sourceMappingURL=storage-factory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-factory.d.ts","sourceRoot":"","sources":["..\\src\\storage-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"storage-factory.d.ts","sourceRoot":"","sources":["..\\src\\storage-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAI5D;;;;GAIG;AACH,qBAAa,cAAc;IACzB;;;;;;OAMG;WACU,OAAO,CAAC,CAAC,EACpB,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,iBAAiB,EACzB,EAAE,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAC7C,OAAO,CAAC,CAAC,CAAC;IAab,OAAO,CAAC,MAAM,CAAC,aAAa;CAU7B"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/storage-factory.ts"],
|
|
4
|
-
"mappings": "AAGA,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAO3B,MAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ1B,aAAa,QACX,MACA,QACA,IACY;AACZ,UAAM,SAAS,eAAe,cAAc,IAAI;AAEhD,UAAM,OAAO,QAAQ,MAAM;AAC3B,QAAI;AACF,aAAO,MAAM,GAAG,MAAM;AAAA,IACxB,UAAE;AACA,YAAM,OAAO,MAAM,EAAE,MAAM,MAAM;AAAA,MAEjC,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,OAAe,cAAc,
|
|
4
|
+
"mappings": "AAGA,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAO3B,MAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ1B,aAAa,QACX,MACA,QACA,IACY;AACZ,UAAM,SAAS,eAAe,cAAc,IAAI;AAEhD,UAAM,OAAO,QAAQ,MAAM;AAC3B,QAAI;AACF,aAAO,MAAM,GAAG,MAAM;AAAA,IACxB,UAAE;AACA,YAAM,OAAO,MAAM,EAAE,MAAM,MAAM;AAAA,MAEjC,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,OAAe,cAAc,MAAsC;AACjE,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,IAAI,kBAAkB;AAAA,MAC/B,KAAK;AACH,eAAO,IAAI,iBAAiB,IAAI;AAAA,MAClC,KAAK;AACH,eAAO,IAAI,iBAAiB,KAAK;AAAA,IACrC;AAAA,EACF;AACF;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-conn-config.d.ts","sourceRoot":"","sources":["..\\..\\src\\types\\storage-conn-config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,
|
|
1
|
+
{"version":3,"file":"storage-conn-config.d.ts","sourceRoot":"","sources":["..\\..\\src\\types\\storage-conn-config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type StorageProtocol = "ftp" | "ftps" | "sftp";
|
|
2
2
|
//# sourceMappingURL=storage-type.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-type.d.ts","sourceRoot":"","sources":["..\\..\\src\\types\\storage-type.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"storage-type.d.ts","sourceRoot":"","sources":["..\\..\\src\\types\\storage-type.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC"}
|
package/dist/types/storage.d.ts
CHANGED
|
@@ -4,11 +4,11 @@ export interface FileInfo {
|
|
|
4
4
|
name: string;
|
|
5
5
|
isFile: boolean;
|
|
6
6
|
}
|
|
7
|
-
export interface
|
|
7
|
+
export interface StorageClient {
|
|
8
8
|
connect(config: StorageConnConfig): Promise<void>;
|
|
9
9
|
mkdir(dirPath: string): Promise<void>;
|
|
10
10
|
rename(fromPath: string, toPath: string): Promise<void>;
|
|
11
|
-
|
|
11
|
+
list(dirPath: string): Promise<FileInfo[]>;
|
|
12
12
|
readFile(filePath: string): Promise<Bytes>;
|
|
13
13
|
exists(filePath: string): Promise<boolean>;
|
|
14
14
|
put(localPathOrBuffer: string | Bytes, storageFilePath: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["..\\..\\src\\types\\storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["..\\..\\src\\types\\storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC3C,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,GAAG,CAAC,iBAAiB,EAAE,MAAM,GAAG,KAAK,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/storage",
|
|
3
|
-
"version": "13.0.
|
|
3
|
+
"version": "13.0.80",
|
|
4
4
|
"description": "Simplysm Package - Storage Module (node)",
|
|
5
5
|
"author": "simplysm",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -14,14 +14,15 @@
|
|
|
14
14
|
"types": "./dist/index.d.ts",
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
|
+
"docs",
|
|
17
18
|
"src",
|
|
18
19
|
"tests"
|
|
19
20
|
],
|
|
20
21
|
"sideEffects": false,
|
|
21
22
|
"dependencies": {
|
|
22
23
|
"basic-ftp": "^5.2.0",
|
|
23
|
-
"ssh2-sftp-client": "^12.0
|
|
24
|
-
"@simplysm/core-common": "13.0.
|
|
24
|
+
"ssh2-sftp-client": "^12.1.0",
|
|
25
|
+
"@simplysm/core-common": "13.0.80"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"@types/ssh2-sftp-client": "^9.0.6"
|
|
@@ -2,7 +2,7 @@ import type { Bytes } from "@simplysm/core-common";
|
|
|
2
2
|
import { bytes, SdError } from "@simplysm/core-common";
|
|
3
3
|
import ftp from "basic-ftp";
|
|
4
4
|
import { PassThrough, Readable } from "stream";
|
|
5
|
-
import type {
|
|
5
|
+
import type { StorageClient, FileInfo } from "../types/storage";
|
|
6
6
|
import type { StorageConnConfig } from "../types/storage-conn-config";
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -12,7 +12,7 @@ import type { StorageConnConfig } from "../types/storage-conn-config";
|
|
|
12
12
|
* The `secure` constructor parameter configures whether to use FTPS.
|
|
13
13
|
* Using {@link StorageFactory.connect} is recommended over direct usage.
|
|
14
14
|
*/
|
|
15
|
-
export class FtpStorageClient implements
|
|
15
|
+
export class FtpStorageClient implements StorageClient {
|
|
16
16
|
private _client: ftp.Client | undefined;
|
|
17
17
|
|
|
18
18
|
constructor(private readonly _secure: boolean = false) {}
|
|
@@ -35,7 +35,7 @@ export class FtpStorageClient implements Storage {
|
|
|
35
35
|
host: config.host,
|
|
36
36
|
port: config.port,
|
|
37
37
|
user: config.user,
|
|
38
|
-
password: config.
|
|
38
|
+
password: config.password,
|
|
39
39
|
secure: this._secure,
|
|
40
40
|
});
|
|
41
41
|
this._client = client;
|
|
@@ -61,7 +61,7 @@ export class FtpStorageClient implements Storage {
|
|
|
61
61
|
await this._requireClient().rename(fromPath, toPath);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
async
|
|
64
|
+
async list(dirPath: string): Promise<FileInfo[]> {
|
|
65
65
|
const fileInfos = await this._requireClient().list(dirPath);
|
|
66
66
|
return fileInfos.map((item) => ({ name: item.name, isFile: item.isFile }));
|
|
67
67
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Bytes } from "@simplysm/core-common";
|
|
2
2
|
import { SdError } from "@simplysm/core-common";
|
|
3
3
|
import SftpClient from "ssh2-sftp-client";
|
|
4
|
-
import type {
|
|
4
|
+
import type { StorageClient, FileInfo } from "../types/storage";
|
|
5
5
|
import type { StorageConnConfig } from "../types/storage-conn-config";
|
|
6
6
|
|
|
7
7
|
// Buffer usage from ssh2-sftp-client library type definitions
|
|
@@ -13,7 +13,7 @@ type SftpGetResult = string | NodeJS.WritableStream | Bytes;
|
|
|
13
13
|
* @remarks
|
|
14
14
|
* Using {@link StorageFactory.connect} is recommended over direct usage.
|
|
15
15
|
*/
|
|
16
|
-
export class SftpStorageClient implements
|
|
16
|
+
export class SftpStorageClient implements StorageClient {
|
|
17
17
|
private _client: SftpClient | undefined;
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -31,12 +31,12 @@ export class SftpStorageClient implements Storage {
|
|
|
31
31
|
|
|
32
32
|
const client = new SftpClient();
|
|
33
33
|
try {
|
|
34
|
-
if (config.
|
|
34
|
+
if (config.password != null) {
|
|
35
35
|
await client.connect({
|
|
36
36
|
host: config.host,
|
|
37
37
|
port: config.port,
|
|
38
38
|
username: config.user,
|
|
39
|
-
password: config.
|
|
39
|
+
password: config.password,
|
|
40
40
|
});
|
|
41
41
|
} else {
|
|
42
42
|
// Authenticate with SSH agent + key file
|
|
@@ -103,7 +103,7 @@ export class SftpStorageClient implements Storage {
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
async
|
|
106
|
+
async list(dirPath: string): Promise<FileInfo[]> {
|
|
107
107
|
const list = await this._requireClient().list(dirPath);
|
|
108
108
|
return list.map((item) => ({
|
|
109
109
|
name: item.name,
|
package/src/storage-factory.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { StorageConnConfig } from "./types/storage-conn-config";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { StorageClient } from "./types/storage";
|
|
3
|
+
import type { StorageProtocol } from "./types/storage-type";
|
|
4
4
|
import { FtpStorageClient } from "./clients/ftp-storage-client";
|
|
5
5
|
import { SftpStorageClient } from "./clients/sftp-storage-client";
|
|
6
6
|
|
|
@@ -18,9 +18,9 @@ export class StorageFactory {
|
|
|
18
18
|
* The connection is automatically closed even if the callback throws an exception.
|
|
19
19
|
*/
|
|
20
20
|
static async connect<R>(
|
|
21
|
-
type:
|
|
21
|
+
type: StorageProtocol,
|
|
22
22
|
config: StorageConnConfig,
|
|
23
|
-
fn: (storage:
|
|
23
|
+
fn: (storage: StorageClient) => R | Promise<R>,
|
|
24
24
|
): Promise<R> {
|
|
25
25
|
const client = StorageFactory._createClient(type);
|
|
26
26
|
|
|
@@ -34,7 +34,7 @@ export class StorageFactory {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
private static _createClient(type:
|
|
37
|
+
private static _createClient(type: StorageProtocol): StorageClient {
|
|
38
38
|
switch (type) {
|
|
39
39
|
case "sftp":
|
|
40
40
|
return new SftpStorageClient();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type StorageProtocol = "ftp" | "ftps" | "sftp";
|
package/src/types/storage.ts
CHANGED
|
@@ -6,11 +6,11 @@ export interface FileInfo {
|
|
|
6
6
|
isFile: boolean;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export interface
|
|
9
|
+
export interface StorageClient {
|
|
10
10
|
connect(config: StorageConnConfig): Promise<void>;
|
|
11
11
|
mkdir(dirPath: string): Promise<void>;
|
|
12
12
|
rename(fromPath: string, toPath: string): Promise<void>;
|
|
13
|
-
|
|
13
|
+
list(dirPath: string): Promise<FileInfo[]>;
|
|
14
14
|
readFile(filePath: string): Promise<Bytes>;
|
|
15
15
|
exists(filePath: string): Promise<boolean>;
|
|
16
16
|
put(localPathOrBuffer: string | Bytes, storageFilePath: string): Promise<void>;
|
|
@@ -52,7 +52,7 @@ describe("FtpStorageClient", () => {
|
|
|
52
52
|
host: "ftp.example.com",
|
|
53
53
|
port: 21,
|
|
54
54
|
user: "user",
|
|
55
|
-
|
|
55
|
+
password: "pass",
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
expect(mockAccess).toHaveBeenCalledWith({
|
|
@@ -96,8 +96,8 @@ describe("FtpStorageClient", () => {
|
|
|
96
96
|
);
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
it("Should throw error when
|
|
100
|
-
await expect(client.
|
|
99
|
+
it("Should throw error when list is called before connection", async () => {
|
|
100
|
+
await expect(client.list("/")).rejects.toThrow("Not connected to FTP server.");
|
|
101
101
|
});
|
|
102
102
|
});
|
|
103
103
|
|
|
@@ -119,10 +119,10 @@ describe("FtpStorageClient", () => {
|
|
|
119
119
|
});
|
|
120
120
|
});
|
|
121
121
|
|
|
122
|
-
describe("
|
|
122
|
+
describe("list", () => {
|
|
123
123
|
it("Should return directory list as FileInfo array", async () => {
|
|
124
124
|
await client.connect({ host: "test" });
|
|
125
|
-
const result = await client.
|
|
125
|
+
const result = await client.list("/");
|
|
126
126
|
|
|
127
127
|
expect(result).toEqual([
|
|
128
128
|
{ name: "file.txt", isFile: true },
|
|
@@ -49,7 +49,7 @@ describe("SftpStorageClient", () => {
|
|
|
49
49
|
host: "sftp.example.com",
|
|
50
50
|
port: 22,
|
|
51
51
|
user: "user",
|
|
52
|
-
|
|
52
|
+
password: "pass",
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
expect(mockConnect).toHaveBeenCalledWith({
|
|
@@ -69,7 +69,7 @@ describe("SftpStorageClient", () => {
|
|
|
69
69
|
|
|
70
70
|
it("Should clean up client on connection failure", async () => {
|
|
71
71
|
mockConnect.mockRejectedValueOnce(new Error("Auth failed"));
|
|
72
|
-
await expect(client.connect({ host: "test",
|
|
72
|
+
await expect(client.connect({ host: "test", password: "wrong" })).rejects.toThrow("Auth failed");
|
|
73
73
|
expect(mockEnd).toHaveBeenCalled();
|
|
74
74
|
});
|
|
75
75
|
});
|
|
@@ -85,8 +85,8 @@ describe("SftpStorageClient", () => {
|
|
|
85
85
|
);
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
-
it("Should throw error when
|
|
89
|
-
await expect(client.
|
|
88
|
+
it("Should throw error when list is called before connection", async () => {
|
|
89
|
+
await expect(client.list("/")).rejects.toThrow("Not connected to SFTP server.");
|
|
90
90
|
});
|
|
91
91
|
});
|
|
92
92
|
|
|
@@ -149,10 +149,10 @@ describe("SftpStorageClient", () => {
|
|
|
149
149
|
});
|
|
150
150
|
});
|
|
151
151
|
|
|
152
|
-
describe("
|
|
152
|
+
describe("list", () => {
|
|
153
153
|
it("Should return directory list as FileInfo array", async () => {
|
|
154
154
|
await client.connect({ host: "test" });
|
|
155
|
-
const result = await client.
|
|
155
|
+
const result = await client.list("/");
|
|
156
156
|
|
|
157
157
|
expect(result).toEqual([
|
|
158
158
|
{ name: "file.txt", isFile: true },
|