react-native-kookit 0.2.4 → 0.2.6

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.
@@ -0,0 +1,161 @@
1
+ # Android FTP Client Implementation Update
2
+
3
+ This document summarizes the updates made to the Android implementation to support the new object-oriented FTP client API.
4
+
5
+ ## Overview
6
+
7
+ The Android implementation has been updated to support multiple FTP client instances, matching the iOS implementation and providing a consistent cross-platform API.
8
+
9
+ ## Key Changes
10
+
11
+ ### 1. ReactNativeKookitModule.kt Updates
12
+
13
+ #### New Client Management
14
+
15
+ - Added `ftpClients` HashMap to manage multiple FTP client instances
16
+ - Each client is identified by a unique `clientId` string
17
+ - Clients can be created, used, and disposed independently
18
+
19
+ #### New Native Methods
20
+
21
+ **Client Lifecycle:**
22
+
23
+ - `createFtpClient(clientId: String)` - Create a new FTP client instance
24
+ - `disposeFtpClient(clientId: String)` - Dispose client and clean up resources
25
+ - `getFtpClientStatus(clientId: String)` - Get client status (exists, connected)
26
+ - `listFtpClients()` - List all active clients with their status
27
+
28
+ **Connection Management:**
29
+
30
+ - `ftpClientConnect(clientId: String, config: Map<String, Any>)` - Connect specific client
31
+ - `ftpClientDisconnect(clientId: String)` - Disconnect specific client
32
+
33
+ **File Operations (all require clientId):**
34
+
35
+ - `ftpClientList(clientId: String, path: String?)` - List files/directories
36
+ - `ftpClientDownload(clientId: String, remotePath: String, localPath: String)` - Download file
37
+ - `ftpClientUpload(clientId: String, localPath: String, remotePath: String)` - Upload file
38
+ - `ftpClientDelete(clientId: String, remotePath: String, isDirectory: Boolean?)` - Delete file/directory
39
+ - `ftpClientCreateDirectory(clientId: String, remotePath: String)` - Create directory
40
+ - `ftpClientChangeDirectory(clientId: String, remotePath: String)` - Change directory
41
+ - `ftpClientGetCurrentDirectory(clientId: String)` - Get current directory
42
+
43
+ #### Event System Updates
44
+
45
+ All FTP events now include `clientId` to identify which client triggered the event:
46
+
47
+ - `onFtpProgress` - Includes `clientId`, `transferred`, `total`, `percentage`
48
+ - `onFtpComplete` - Includes `clientId`
49
+ - `onFtpError` - Includes `clientId`, `error`
50
+
51
+ ### 2. FtpClient.kt Updates
52
+
53
+ #### New Methods
54
+
55
+ - `isConnected(): Boolean` - Public method to check connection status
56
+ - Enhanced connection state management
57
+
58
+ #### Existing Features Maintained
59
+
60
+ - UTF-8 encoding support for Chinese characters
61
+ - Passive mode FTP connections
62
+ - Progress callbacks for upload/download operations
63
+ - Comprehensive error handling
64
+ - Multi-line FTP response parsing
65
+
66
+ ## Architecture Benefits
67
+
68
+ ### Resource Management
69
+
70
+ - Each client manages its own connection independently
71
+ - Proper cleanup when clients are disposed
72
+ - No interference between multiple concurrent connections
73
+
74
+ ### Scalability
75
+
76
+ - Support for multiple FTP servers simultaneously
77
+ - Each client can connect to different servers
78
+ - Independent authentication and configuration per client
79
+
80
+ ### Error Isolation
81
+
82
+ - Errors in one client don't affect others
83
+ - Per-client event handling
84
+ - Individual client status tracking
85
+
86
+ ## Usage Pattern
87
+
88
+ ### Android Native Layer
89
+
90
+ ```kotlin
91
+ // Create client
92
+ createFtpClient("client1")
93
+
94
+ // Connect
95
+ ftpClientConnect("client1", config)
96
+
97
+ // Use client
98
+ ftpClientList("client1", "/")
99
+ ftpClientDownload("client1", "/remote/file.txt", "/local/file.txt")
100
+
101
+ // Clean up
102
+ disposeFtpClient("client1")
103
+ ```
104
+
105
+ ### Event Handling
106
+
107
+ ```kotlin
108
+ // Events now include clientId for identification
109
+ sendEvent("onFtpProgress", mapOf(
110
+ "clientId" to clientId,
111
+ "transferred" to transferred,
112
+ "total" to total,
113
+ "percentage" to percentage
114
+ ))
115
+ ```
116
+
117
+ ## Backward Compatibility
118
+
119
+ The old global FTP methods (`ftpConnect`, `ftpDisconnect`, etc.) are maintained for backward compatibility, but the new client-based API is recommended for new development.
120
+
121
+ ## Error Handling
122
+
123
+ All new methods include comprehensive error handling:
124
+
125
+ - Client not found errors when invalid `clientId` is provided
126
+ - Connection state validation before operations
127
+ - Proper exception propagation to JavaScript layer
128
+ - Resource cleanup on errors
129
+
130
+ ## Testing
131
+
132
+ The implementation has been tested with:
133
+
134
+ - ✅ TypeScript compilation (0 errors)
135
+ - ✅ Multiple concurrent clients
136
+ - ✅ Client lifecycle management
137
+ - ✅ Event system with client identification
138
+ - ✅ Error handling and resource cleanup
139
+
140
+ ## Migration from Old API
141
+
142
+ ### Old Android Pattern:
143
+
144
+ ```kotlin
145
+ ftpConnect(config)
146
+ ftpList(path)
147
+ ftpDownload(remotePath, localPath)
148
+ ftpDisconnect()
149
+ ```
150
+
151
+ ### New Android Pattern:
152
+
153
+ ```kotlin
154
+ createFtpClient(clientId)
155
+ ftpClientConnect(clientId, config)
156
+ ftpClientList(clientId, path)
157
+ ftpClientDownload(clientId, remotePath, localPath)
158
+ disposeFtpClient(clientId)
159
+ ```
160
+
161
+ The new API provides better resource management, supports multiple concurrent connections, and maintains consistency with the iOS implementation.
File without changes
@@ -0,0 +1,180 @@
1
+ # iOS与Android API接口统一更新
2
+
3
+ 本文档记录了为统一iOS和Android FTP客户端API接口命名所做的更改。
4
+
5
+ ## 问题描述
6
+
7
+ 之前iOS和Android的FTP API方法命名不一致:
8
+
9
+ ### 修改前的命名差异
10
+
11
+ | 功能 | iOS方法名 | Android方法名 |
12
+ | -------------- | --------------------------- | ------------------------------ |
13
+ | 连接 | `ftpConnect` | `ftpClientConnect` |
14
+ | 断开连接 | `ftpDisconnect` | `ftpClientDisconnect` |
15
+ | 文件列表 | `ftpList` | `ftpClientList` |
16
+ | 下载文件 | `ftpDownload` | `ftpClientDownload` |
17
+ | 上传文件 | `ftpUpload` | `ftpClientUpload` |
18
+ | 删除文件 | `ftpDelete` | `ftpClientDelete` |
19
+ | 创建目录 | `ftpCreateDirectory` | `ftpClientCreateDirectory` |
20
+ | 切换目录 | `ftpChangeDirectory` | `ftpClientChangeDirectory` |
21
+ | 获取当前目录 | `ftpGetCurrentDirectory` | `ftpClientGetCurrentDirectory` |
22
+ | 获取客户端状态 | `getFtpClientStatus` (同步) | `getFtpClientStatus` (异步) |
23
+ | 列出所有客户端 | `listFtpClients` (同步) | `listFtpClients` (异步) |
24
+
25
+ ## 解决方案
26
+
27
+ 统一使用`ftpClient*`命名模式,并确保所有方法都是异步的。
28
+
29
+ ### 修改后的统一命名
30
+
31
+ | 功能 | 统一方法名 | 参数 |
32
+ | -------------- | ------------------------------ | --------------------------------------------------------------- |
33
+ | 创建客户端 | `createFtpClient` | `(clientId: String)` |
34
+ | 释放客户端 | `disposeFtpClient` | `(clientId: String)` |
35
+ | 连接 | `ftpClientConnect` | `(clientId: String, config: Object)` |
36
+ | 断开连接 | `ftpClientDisconnect` | `(clientId: String)` |
37
+ | 文件列表 | `ftpClientList` | `(clientId: String, path?: String)` |
38
+ | 下载文件 | `ftpClientDownload` | `(clientId: String, remotePath: String, localPath: String)` |
39
+ | 上传文件 | `ftpClientUpload` | `(clientId: String, localPath: String, remotePath: String)` |
40
+ | 删除文件 | `ftpClientDelete` | `(clientId: String, remotePath: String, isDirectory?: Boolean)` |
41
+ | 创建目录 | `ftpClientCreateDirectory` | `(clientId: String, remotePath: String)` |
42
+ | 切换目录 | `ftpClientChangeDirectory` | `(clientId: String, remotePath: String)` |
43
+ | 获取当前目录 | `ftpClientGetCurrentDirectory` | `(clientId: String)` |
44
+ | 获取客户端状态 | `getFtpClientStatus` | `(clientId: String)` |
45
+ | 列出所有客户端 | `listFtpClients` | `()` |
46
+
47
+ ## iOS代码更改详情
48
+
49
+ ### 主要FTP操作方法
50
+
51
+ ```swift
52
+ // 连接
53
+ AsyncFunction("ftpClientConnect") { (clientId: String, config: [String: Any], promise: Promise) in
54
+
55
+ // 断开连接
56
+ AsyncFunction("ftpClientDisconnect") { (clientId: String, promise: Promise) in
57
+
58
+ // 文件列表
59
+ AsyncFunction("ftpClientList") { (clientId: String, path: String?, promise: Promise) in
60
+
61
+ // 下载文件
62
+ AsyncFunction("ftpClientDownload") { (clientId: String, remotePath: String, localPath: String, promise: Promise) in
63
+
64
+ // 上传文件
65
+ AsyncFunction("ftpClientUpload") { (clientId: String, localPath: String, remotePath: String, promise: Promise) in
66
+
67
+ // 删除文件
68
+ AsyncFunction("ftpClientDelete") { (clientId: String, remotePath: String, isDirectory: Bool?, promise: Promise) in
69
+
70
+ // 创建目录
71
+ AsyncFunction("ftpClientCreateDirectory") { (clientId: String, remotePath: String, promise: Promise) in
72
+
73
+ // 切换目录
74
+ AsyncFunction("ftpClientChangeDirectory") { (clientId: String, remotePath: String, promise: Promise) in
75
+
76
+ // 获取当前目录
77
+ AsyncFunction("ftpClientGetCurrentDirectory") { (clientId: String, promise: Promise) in
78
+ ```
79
+
80
+ ### 客户端管理方法
81
+
82
+ ```swift
83
+ // 获取客户端状态 - 改为异步
84
+ AsyncFunction("getFtpClientStatus") { (clientId: String, promise: Promise) in
85
+ guard let ftpClient = self.ftpClients[clientId] else {
86
+ promise.resolve([
87
+ "exists": false,
88
+ "connected": false
89
+ ])
90
+ return
91
+ }
92
+
93
+ promise.resolve([
94
+ "exists": true,
95
+ "connected": ftpClient.isConnected
96
+ ])
97
+ }
98
+
99
+ // 列出所有客户端 - 改为异步
100
+ AsyncFunction("listFtpClients") { (promise: Promise) in
101
+ let clientsInfo = self.ftpClients.mapValues { client in
102
+ [
103
+ "connected": client.isConnected
104
+ ]
105
+ }
106
+
107
+ promise.resolve([
108
+ "clients": clientsInfo,
109
+ "count": self.ftpClients.count
110
+ ])
111
+ }
112
+ ```
113
+
114
+ ## 兼容性说明
115
+
116
+ ### 完全统一
117
+
118
+ 现在iOS和Android的API接口完全统一:
119
+
120
+ - ✅ 方法名称一致
121
+ - ✅ 参数顺序一致
122
+ - ✅ 返回值格式一致
123
+ - ✅ 所有方法都是异步的
124
+ - ✅ 错误处理方式一致
125
+
126
+ ### TypeScript类型定义
127
+
128
+ TypeScript模块定义(`ReactNativeKookitModule.ts`)已经使用了统一的命名,无需修改。
129
+
130
+ ### FtpClient包装类
131
+
132
+ `FtpClient.ts`中的方法调用已经更新为使用统一的方法名。
133
+
134
+ ## 影响范围
135
+
136
+ ### 不影响的部分
137
+
138
+ - TypeScript客户端API保持不变
139
+ - 示例应用代码无需修改
140
+ - 用户使用的高级API (`FtpClient` 类) 保持不变
141
+
142
+ ### 改进的部分
143
+
144
+ - 跨平台开发时API行为完全一致
145
+ - 调试时方法名称在两个平台上相同
146
+ - 内部native方法调用逻辑统一
147
+
148
+ ## 验证结果
149
+
150
+ ### 构建测试
151
+
152
+ - ✅ TypeScript编译:0错误
153
+ - ✅ iOS Swift编译:通过
154
+ - ✅ Android Kotlin编译:通过
155
+
156
+ ### API一致性验证
157
+
158
+ ```typescript
159
+ // 现在这些调用在iOS和Android上完全一致
160
+ await ReactNativeKookitModule.createFtpClient(clientId);
161
+ await ReactNativeKookitModule.ftpClientConnect(clientId, config);
162
+ await ReactNativeKookitModule.ftpClientList(clientId, path);
163
+ await ReactNativeKookitModule.ftpClientDownload(
164
+ clientId,
165
+ remotePath,
166
+ localPath
167
+ );
168
+ // ... 所有其他方法
169
+ ```
170
+
171
+ ## 总结
172
+
173
+ 通过这次统一更新:
174
+
175
+ 1. **解决了命名不一致问题**:iOS方法名更新为与Android一致
176
+ 2. **统一了异步模式**:所有方法都使用AsyncFunction模式
177
+ 3. **简化了维护工作**:两个平台使用相同的API接口
178
+ 4. **提高了开发体验**:跨平台开发时无需记忆不同的方法名
179
+
180
+ 现在iOS和Android的FTP客户端API完全统一,为开发者提供了一致的跨平台体验。
@@ -0,0 +1,301 @@
1
+ # FTP Client API
2
+
3
+ This document describes the new FTP Client API that provides an object-oriented approach to FTP operations.
4
+
5
+ ## Overview
6
+
7
+ The new FTP API allows you to create multiple FTP client instances, each maintaining its own connection and state. This is more flexible than the previous global FTP functions.
8
+
9
+ ## Basic Usage
10
+
11
+ ### Creating an FTP Client
12
+
13
+ ```typescript
14
+ import { FtpClient } from "react-native-kookit";
15
+
16
+ // Method 1: Using static create method (recommended)
17
+ const ftpClient = await FtpClient.create("my-client-id");
18
+
19
+ // Method 2: Manual initialization
20
+ const ftpClient = new FtpClient("my-client-id");
21
+ await ftpClient.initialize();
22
+ ```
23
+
24
+ ### Setting up Event Handlers
25
+
26
+ ```typescript
27
+ ftpClient.setEventHandlers({
28
+ onProgress: (progress) => {
29
+ console.log(`Progress: ${progress.percentage}%`);
30
+ console.log(`Transferred: ${progress.transferred}/${progress.total} bytes`);
31
+ },
32
+ onComplete: () => {
33
+ console.log("Operation completed successfully!");
34
+ },
35
+ onError: (error) => {
36
+ console.error("FTP Error:", error.message);
37
+ },
38
+ });
39
+ ```
40
+
41
+ ### Connecting to FTP Server
42
+
43
+ ```typescript
44
+ await ftpClient.connect({
45
+ host: "192.168.1.100",
46
+ port: 21, // optional, defaults to 21
47
+ username: "your-username",
48
+ password: "your-password",
49
+ passive: true, // optional, defaults to true
50
+ timeout: 30, // optional, defaults to 30 seconds
51
+ });
52
+ ```
53
+
54
+ ## FTP Operations
55
+
56
+ ### Directory Operations
57
+
58
+ ```typescript
59
+ // Get current directory
60
+ const currentDir = await ftpClient.getCurrentDirectory();
61
+ console.log("Current directory:", currentDir);
62
+
63
+ // Change directory
64
+ await ftpClient.changeDirectory("/path/to/directory");
65
+
66
+ // Create directory
67
+ await ftpClient.createDirectory("/path/to/new-directory");
68
+
69
+ // List files and directories
70
+ const files = await ftpClient.list(); // List current directory
71
+ const filesInPath = await ftpClient.list("/specific/path"); // List specific path
72
+
73
+ files.forEach((file) => {
74
+ console.log(
75
+ `${file.name} - ${file.isDirectory ? "DIR" : "FILE"} - ${file.size} bytes`
76
+ );
77
+ });
78
+ ```
79
+
80
+ ### File Operations
81
+
82
+ ```typescript
83
+ // Download file
84
+ await ftpClient.download("/remote/path/file.txt", "/local/path/file.txt");
85
+
86
+ // Upload file
87
+ await ftpClient.upload("/local/path/file.txt", "/remote/path/file.txt");
88
+
89
+ // Delete file
90
+ await ftpClient.delete("/remote/path/file.txt");
91
+
92
+ // Delete directory
93
+ await ftpClient.delete("/remote/path/directory", true); // true for directory
94
+ ```
95
+
96
+ ### Client Management
97
+
98
+ ```typescript
99
+ // Check client status
100
+ const status = ftpClient.getStatus();
101
+ console.log("Client exists:", status.exists);
102
+ console.log("Client connected:", status.connected);
103
+
104
+ // Check if connected (convenience method)
105
+ if (ftpClient.isConnected()) {
106
+ console.log("Client is ready for operations");
107
+ }
108
+
109
+ // Get client ID
110
+ const clientId = ftpClient.getClientId();
111
+ console.log("Client ID:", clientId);
112
+
113
+ // Disconnect from server
114
+ await ftpClient.disconnect();
115
+
116
+ // Dispose client and clean up resources
117
+ await ftpClient.dispose();
118
+ ```
119
+
120
+ ## Advanced Usage
121
+
122
+ ### Multiple FTP Clients
123
+
124
+ ```typescript
125
+ import { FtpClient } from "react-native-kookit";
126
+
127
+ // Create multiple clients for different servers
128
+ const client1 = await FtpClient.create("server1");
129
+ const client2 = await FtpClient.create("server2");
130
+
131
+ // Connect to different servers
132
+ await client1.connect({
133
+ host: "ftp1.example.com",
134
+ username: "user1",
135
+ password: "pass1",
136
+ });
137
+
138
+ await client2.connect({
139
+ host: "ftp2.example.com",
140
+ username: "user2",
141
+ password: "pass2",
142
+ });
143
+
144
+ // Perform operations on different servers simultaneously
145
+ const [files1, files2] = await Promise.all([client1.list(), client2.list()]);
146
+
147
+ // Clean up
148
+ await Promise.all([client1.dispose(), client2.dispose()]);
149
+ ```
150
+
151
+ ### Managing All Clients
152
+
153
+ ```typescript
154
+ // List all active FTP clients
155
+ const clientsInfo = FtpClient.listClients();
156
+ console.log("Active clients:", clientsInfo.count);
157
+ console.log("Clients details:", clientsInfo.clients);
158
+
159
+ // Example output:
160
+ // {
161
+ // clients: {
162
+ // 'client-1': { connected: true },
163
+ // 'client-2': { connected: false }
164
+ // },
165
+ // count: 2
166
+ // }
167
+ ```
168
+
169
+ ### Error Handling
170
+
171
+ ```typescript
172
+ try {
173
+ const ftpClient = await FtpClient.create();
174
+
175
+ await ftpClient.connect({
176
+ host: "ftp.example.com",
177
+ username: "user",
178
+ password: "pass",
179
+ });
180
+
181
+ await ftpClient.download("/remote/file.txt", "/local/file.txt");
182
+ } catch (error) {
183
+ console.error("FTP operation failed:", error.message);
184
+ } finally {
185
+ // Always dispose to clean up resources
186
+ if (ftpClient) {
187
+ await ftpClient.dispose();
188
+ }
189
+ }
190
+ ```
191
+
192
+ ## API Reference
193
+
194
+ ### FtpClient Class
195
+
196
+ #### Constructor
197
+
198
+ - `new FtpClient(clientId?: string)` - Create a new FTP client instance
199
+
200
+ #### Static Methods
201
+
202
+ - `FtpClient.create(clientId?: string): Promise<FtpClient>` - Create and initialize a new FTP client
203
+ - `FtpClient.listClients()` - Get information about all active FTP clients
204
+
205
+ #### Instance Methods
206
+
207
+ **Lifecycle:**
208
+
209
+ - `initialize(): Promise<void>` - Initialize the client (called automatically by `create()`)
210
+ - `dispose(): Promise<void>` - Dispose client and clean up resources
211
+
212
+ **Connection:**
213
+
214
+ - `connect(config: FtpConnectionConfig): Promise<void>` - Connect to FTP server
215
+ - `disconnect(): Promise<void>` - Disconnect from FTP server
216
+ - `isConnected(): boolean` - Check if client is connected
217
+
218
+ **Directory Operations:**
219
+
220
+ - `list(path?: string): Promise<FtpFileInfo[]>` - List files and directories
221
+ - `getCurrentDirectory(): Promise<string>` - Get current working directory
222
+ - `changeDirectory(path: string): Promise<void>` - Change working directory
223
+ - `createDirectory(path: string): Promise<void>` - Create a directory
224
+
225
+ **File Operations:**
226
+
227
+ - `download(remotePath: string, localPath: string): Promise<void>` - Download a file
228
+ - `upload(localPath: string, remotePath: string): Promise<void>` - Upload a file
229
+ - `delete(remotePath: string, isDirectory?: boolean): Promise<void>` - Delete a file or directory
230
+
231
+ **Utility:**
232
+
233
+ - `getStatus()` - Get client status information
234
+ - `getClientId(): string` - Get the client ID
235
+ - `setEventHandlers(handlers: FtpClientEventHandlers): void` - Set event handlers
236
+
237
+ ### Types
238
+
239
+ ```typescript
240
+ interface FtpConnectionConfig {
241
+ host: string;
242
+ port?: number;
243
+ username: string;
244
+ password: string;
245
+ passive?: boolean;
246
+ timeout?: number;
247
+ }
248
+
249
+ interface FtpFileInfo {
250
+ name: string;
251
+ isDirectory: boolean;
252
+ size: number;
253
+ lastModified: string;
254
+ permissions?: string;
255
+ }
256
+
257
+ interface FtpClientEventHandlers {
258
+ onProgress?: (progress: {
259
+ transferred: number;
260
+ total: number;
261
+ percentage: number;
262
+ }) => void;
263
+ onComplete?: () => void;
264
+ onError?: (error: Error) => void;
265
+ }
266
+ ```
267
+
268
+ ## Migration from Old API
269
+
270
+ If you're migrating from the old global FTP functions, here's how to update your code:
271
+
272
+ ### Old API:
273
+
274
+ ```typescript
275
+ import ReactNativeKookitModule from "react-native-kookit";
276
+
277
+ await ReactNativeKookitModule.ftpConnect(config);
278
+ const files = await ReactNativeKookitModule.ftpList();
279
+ await ReactNativeKookitModule.ftpDownload(remotePath, localPath);
280
+ await ReactNativeKookitModule.ftpDisconnect();
281
+ ```
282
+
283
+ ### New API:
284
+
285
+ ```typescript
286
+ import { FtpClient } from "react-native-kookit";
287
+
288
+ const ftpClient = await FtpClient.create();
289
+ await ftpClient.connect(config);
290
+ const files = await ftpClient.list();
291
+ await ftpClient.download(remotePath, localPath);
292
+ await ftpClient.dispose(); // This disconnects and cleans up
293
+ ```
294
+
295
+ ## Best Practices
296
+
297
+ 1. **Always dispose clients**: Call `dispose()` when you're done to clean up resources
298
+ 2. **Use try-finally blocks**: Ensure disposal happens even if operations fail
299
+ 3. **Handle events**: Set up progress, completion, and error handlers for better UX
300
+ 4. **Use meaningful client IDs**: This helps with debugging and client management
301
+ 5. **Check connection status**: Use `isConnected()` before performing operations
File without changes