@js4cytoscape/ndex-client 0.5.0-alpha.9 → 0.6.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +339 -13
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.d.mts +1906 -0
- package/dist/index.d.ts +1906 -0
- package/dist/index.global.js +9 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +80 -21
- package/src/CyNDEx.js.bak +178 -0
- package/src/NDEx.js +66 -13
- package/src/NDEx.js.bak +1107 -0
- package/src/index.ts +230 -0
- package/src/models/CX2Network.ts +423 -0
- package/src/services/AdminService.ts +10 -0
- package/src/services/CyNDExService.ts +338 -0
- package/src/services/FilesService.ts +234 -0
- package/src/services/HTTPService.ts +442 -0
- package/src/services/NetworkServiceV2.ts +427 -0
- package/src/services/NetworkServiceV3.ts +288 -0
- package/src/services/UnifiedNetworkService.ts +641 -0
- package/src/services/UserService.ts +233 -0
- package/src/services/WorkspaceService.ts +159 -0
- package/src/types/cytoscape.ts +81 -0
- package/src/types/index.ts +524 -0
- package/dist/ndexClient.common.js +0 -1057
- package/dist/ndexClient.js +0 -538
- package/src/index.js +0 -2
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import axios, { AxiosInstance } from 'axios';
|
|
2
|
+
import {
|
|
3
|
+
CyNDExConfig,
|
|
4
|
+
CyNDExAuthConfig,
|
|
5
|
+
NDExImportParams,
|
|
6
|
+
NDExExportParams,
|
|
7
|
+
CytoscapeNetworkSummary,
|
|
8
|
+
CyNDExStatusResponse,
|
|
9
|
+
CX2ImportParams
|
|
10
|
+
} from '../types/cytoscape';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* CyNDEx Service - Cytoscape-NDEx Bridge
|
|
14
|
+
*
|
|
15
|
+
* Provides seamless integration between Cytoscape desktop application and NDEx,
|
|
16
|
+
* enabling import/export of networks with support for CX and CX2 formats.
|
|
17
|
+
*
|
|
18
|
+
* This service communicates with Cytoscape via its REST API and handles NDEx
|
|
19
|
+
* authentication parameters that are passed to Cytoscape for NDEx operations.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* // Basic usage
|
|
24
|
+
* const cyNDEx = new CyNDExService();
|
|
25
|
+
*
|
|
26
|
+
* // Configure NDEx server
|
|
27
|
+
* cyNDEx.setNDExBaseURL('https://www.ndexbio.org');
|
|
28
|
+
*
|
|
29
|
+
* // Set authentication
|
|
30
|
+
* cyNDEx.setBasicAuth('username', 'password');
|
|
31
|
+
* // or
|
|
32
|
+
* cyNDEx.setAuthToken('oauth-id-token');
|
|
33
|
+
*
|
|
34
|
+
* // Import network from NDEx to Cytoscape
|
|
35
|
+
* await cyNDEx.postNDExNetworkToCytoscape('network-uuid', 'access-key');
|
|
36
|
+
*
|
|
37
|
+
* // Export network from Cytoscape to NDEx
|
|
38
|
+
* await cyNDEx.postCytoscapeNetworkToNDEx('current');
|
|
39
|
+
*
|
|
40
|
+
* // Import CX2 data to Cytoscape
|
|
41
|
+
* await cyNDEx.postCX2NetworkToCytoscape(cx2String, 'My Network', 'My Collection');
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export class CyNDExService {
|
|
45
|
+
private _port: number;
|
|
46
|
+
private cyRestBaseURL: string;
|
|
47
|
+
private ndexBaseURL: string;
|
|
48
|
+
private authConfig?: CyNDExAuthConfig;
|
|
49
|
+
private axiosInstance: AxiosInstance;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Create a new CyNDEx service instance
|
|
53
|
+
*
|
|
54
|
+
* @param port - Port number for Cytoscape REST API (default: 1234)
|
|
55
|
+
* @param config - Optional configuration object
|
|
56
|
+
*/
|
|
57
|
+
constructor(port: number = 1234, config?: CyNDExConfig) {
|
|
58
|
+
this._port = port;
|
|
59
|
+
this.cyRestBaseURL = config?.cyRestBaseURL || 'http://127.0.0.1';
|
|
60
|
+
this.ndexBaseURL = config?.ndexBaseURL || 'https://www.ndexbio.org';
|
|
61
|
+
|
|
62
|
+
// Create axios instance for Cytoscape REST API calls
|
|
63
|
+
this.axiosInstance = axios.create({
|
|
64
|
+
baseURL: this.cyRestURL(),
|
|
65
|
+
timeout: 30000,
|
|
66
|
+
headers: {
|
|
67
|
+
'Content-Type': 'application/json'
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get the port number for Cytoscape REST API
|
|
74
|
+
*/
|
|
75
|
+
get port(): number {
|
|
76
|
+
return this._port;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Get the base URL for Cytoscape REST API
|
|
81
|
+
*/
|
|
82
|
+
static get cyRestBaseURL(): string {
|
|
83
|
+
return 'http://127.0.0.1';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Set NDEx server base URL
|
|
88
|
+
*
|
|
89
|
+
* @param ndexBaseURL - Complete base URL for NDEx server (e.g., 'https://www.ndexbio.org')
|
|
90
|
+
* Must include protocol (https:// or http://)
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* cyNDEx.setNDExBaseURL('https://www.ndexbio.org');
|
|
95
|
+
* cyNDEx.setNDExBaseURL('https://test.ndexbio.org');
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
setNDExBaseURL(ndexBaseURL: string): void {
|
|
99
|
+
if (ndexBaseURL?.trim()) {
|
|
100
|
+
this.ndexBaseURL = ndexBaseURL.trim();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get the current NDEx server base URL
|
|
106
|
+
*
|
|
107
|
+
* @returns Complete NDEx server base URL
|
|
108
|
+
*/
|
|
109
|
+
getNDExBaseURL(): string {
|
|
110
|
+
return this.ndexBaseURL;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Set basic authentication credentials for NDEx operations
|
|
116
|
+
*
|
|
117
|
+
* @param username - NDEx username
|
|
118
|
+
* @param password - NDEx password
|
|
119
|
+
*/
|
|
120
|
+
setBasicAuth(username: string, password: string): void {
|
|
121
|
+
if (username?.trim() && password) {
|
|
122
|
+
this.authConfig = {
|
|
123
|
+
type: 'basic',
|
|
124
|
+
username: username.trim(),
|
|
125
|
+
password: password
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Set OAuth ID token for NDEx operations
|
|
132
|
+
*
|
|
133
|
+
* @param idToken - OAuth ID token from authentication provider
|
|
134
|
+
*/
|
|
135
|
+
setAuthToken(idToken: string): void {
|
|
136
|
+
if (idToken?.trim()) {
|
|
137
|
+
this.authConfig = {
|
|
138
|
+
type: 'oauth',
|
|
139
|
+
idToken: idToken.trim()
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Clear authentication credentials
|
|
146
|
+
*/
|
|
147
|
+
clearAuth(): void {
|
|
148
|
+
this.authConfig = undefined;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Get the complete Cytoscape REST API URL
|
|
153
|
+
*
|
|
154
|
+
* @returns Complete URL for Cytoscape REST API
|
|
155
|
+
*/
|
|
156
|
+
cyRestURL(): string {
|
|
157
|
+
return `${this.cyRestBaseURL}:${this._port}`;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Get authorization fields for NDEx operations
|
|
162
|
+
* These are passed as parameters to Cytoscape for NDEx authentication
|
|
163
|
+
*
|
|
164
|
+
* @private
|
|
165
|
+
* @returns Authorization parameters object
|
|
166
|
+
*/
|
|
167
|
+
private getAuthFields(): Record<string, string> {
|
|
168
|
+
if (!this.authConfig) return {};
|
|
169
|
+
|
|
170
|
+
switch (this.authConfig.type) {
|
|
171
|
+
case 'basic':
|
|
172
|
+
return {
|
|
173
|
+
username: this.authConfig.username!,
|
|
174
|
+
password: this.authConfig.password!
|
|
175
|
+
};
|
|
176
|
+
case 'oauth':
|
|
177
|
+
return {
|
|
178
|
+
idToken: this.authConfig.idToken!
|
|
179
|
+
};
|
|
180
|
+
default:
|
|
181
|
+
return {};
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Perform HTTP GET request to Cytoscape REST API
|
|
187
|
+
*
|
|
188
|
+
* @private
|
|
189
|
+
* @param url - Endpoint URL (relative to base URL)
|
|
190
|
+
* @returns Promise resolving to response data
|
|
191
|
+
*/
|
|
192
|
+
private async _httpGet<T = any>(url: string): Promise<T> {
|
|
193
|
+
const response = await this.axiosInstance.get<T>(url);
|
|
194
|
+
return response.data;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Perform HTTP POST request to Cytoscape REST API
|
|
199
|
+
*
|
|
200
|
+
* @private
|
|
201
|
+
* @param url - Endpoint URL (relative to base URL)
|
|
202
|
+
* @param params - Optional query parameters
|
|
203
|
+
* @param data - Optional request body data
|
|
204
|
+
* @returns Promise resolving to response data
|
|
205
|
+
*/
|
|
206
|
+
private async _httpPost<T = any>(url: string, params?: any, data?: any): Promise<T> {
|
|
207
|
+
const response = await this.axiosInstance.post<T>(url, data, { params });
|
|
208
|
+
return response.data;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Perform HTTP PUT request to Cytoscape REST API
|
|
213
|
+
*
|
|
214
|
+
* @private
|
|
215
|
+
* @param url - Endpoint URL (relative to base URL)
|
|
216
|
+
* @param params - Optional query parameters
|
|
217
|
+
* @param data - Optional request body data
|
|
218
|
+
* @returns Promise resolving to response data
|
|
219
|
+
*/
|
|
220
|
+
private async _httpPut<T = any>(url: string, params?: any, data?: any): Promise<T> {
|
|
221
|
+
const response = await this.axiosInstance.put<T>(url, data, { params });
|
|
222
|
+
return response.data;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// =============================================================================
|
|
226
|
+
// Public API Methods - Maintain exact same signatures as original CyNDEx.js
|
|
227
|
+
// =============================================================================
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Get CyNDEx plugin status from Cytoscape
|
|
231
|
+
*
|
|
232
|
+
* @returns Promise resolving to CyNDEx status information
|
|
233
|
+
*/
|
|
234
|
+
async getCyNDExStatus(): Promise<CyNDExStatusResponse> {
|
|
235
|
+
return this._httpGet<CyNDExStatusResponse>('/cyndex2/v1');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Get network summary information from Cytoscape
|
|
240
|
+
*
|
|
241
|
+
* @param suid - Network SUID or 'current' for current network (default: 'current')
|
|
242
|
+
* @returns Promise resolving to network summary
|
|
243
|
+
*/
|
|
244
|
+
async getCytoscapeNetworkSummary(suid: string = 'current'): Promise<CytoscapeNetworkSummary> {
|
|
245
|
+
return this._httpGet<CytoscapeNetworkSummary>(`/cyndex2/v1/networks/${suid}`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Import network from NDEx to Cytoscape
|
|
250
|
+
*
|
|
251
|
+
* @param uuid - NDEx network UUID
|
|
252
|
+
* @param accessKey - Optional access key for private networks
|
|
253
|
+
* @param createView - Whether to create a network view (default: undefined)
|
|
254
|
+
* @returns Promise resolving to import result
|
|
255
|
+
*/
|
|
256
|
+
async postNDExNetworkToCytoscape(
|
|
257
|
+
uuid: string,
|
|
258
|
+
accessKey?: string,
|
|
259
|
+
createView?: boolean
|
|
260
|
+
): Promise<any> {
|
|
261
|
+
const importParams: NDExImportParams = {
|
|
262
|
+
serverUrl: `${this.ndexBaseURL}/v2`,
|
|
263
|
+
uuid: uuid,
|
|
264
|
+
accessKey: accessKey,
|
|
265
|
+
createView: createView,
|
|
266
|
+
...this.getAuthFields()
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
return this._httpPost('/cyndex2/v1/networks', undefined, importParams);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Import CX network data to Cytoscape
|
|
274
|
+
*
|
|
275
|
+
* @param cx - CX format network data
|
|
276
|
+
* @returns Promise resolving to import result
|
|
277
|
+
*/
|
|
278
|
+
async postCXNetworkToCytoscape(cx: any): Promise<any> {
|
|
279
|
+
return this._httpPost('/cyndex2/v1/networks/cx', undefined, cx);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Import CX2 network data to Cytoscape
|
|
284
|
+
*
|
|
285
|
+
* @param cx2_string - CX2 format network data as string
|
|
286
|
+
* @param title - Network title
|
|
287
|
+
* @param collection_name - Collection name
|
|
288
|
+
* @returns Promise resolving to import result
|
|
289
|
+
*/
|
|
290
|
+
async postCX2NetworkToCytoscape(
|
|
291
|
+
cx2_string: string,
|
|
292
|
+
title: string,
|
|
293
|
+
collection_name: string
|
|
294
|
+
): Promise<any> {
|
|
295
|
+
const params: CX2ImportParams = {
|
|
296
|
+
format: 'cx2',
|
|
297
|
+
collection: collection_name,
|
|
298
|
+
title: title
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
return this._httpPost('/v1/networks', params, cx2_string);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Export network from Cytoscape to NDEx (create new network)
|
|
306
|
+
*
|
|
307
|
+
* @param suid - Network SUID or 'current' for current network (default: 'current')
|
|
308
|
+
* @returns Promise resolving to export result
|
|
309
|
+
*/
|
|
310
|
+
async postCytoscapeNetworkToNDEx(suid: string = 'current'): Promise<any> {
|
|
311
|
+
const saveParams: NDExExportParams = {
|
|
312
|
+
serverUrl: `${this.ndexBaseURL}/v2`,
|
|
313
|
+
...this.getAuthFields()
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
return this._httpPost(`/cyndex2/v1/networks/${suid}`, undefined, saveParams);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Update existing network in NDEx with data from Cytoscape
|
|
321
|
+
*
|
|
322
|
+
* @param suid - Network SUID or 'current' for current network (default: 'current')
|
|
323
|
+
* @param uuid - Target NDEx network UUID to update
|
|
324
|
+
* @returns Promise resolving to update result
|
|
325
|
+
*/
|
|
326
|
+
async putCytoscapeNetworkInNDEx(suid: string = 'current', uuid: string): Promise<any> {
|
|
327
|
+
const saveParams: NDExExportParams = {
|
|
328
|
+
serverUrl: `${this.ndexBaseURL}/v2`,
|
|
329
|
+
uuid: uuid,
|
|
330
|
+
...this.getAuthFields()
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
return this._httpPut(`/cyndex2/v1/networks/${suid}`, undefined, saveParams);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Export both as named export and default for backward compatibility
|
|
338
|
+
export default CyNDExService;
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { HTTPService } from './HTTPService';
|
|
2
|
+
|
|
3
|
+
// Type definitions for better type safety
|
|
4
|
+
interface ShareData {
|
|
5
|
+
files: Record<string, 'NETWORK' | 'FOLDER' | 'SHORTCUT'>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface MemberData {
|
|
9
|
+
members: Record<string, 'READ' | 'WRITE'>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface UpdateMemberRequest {
|
|
13
|
+
files: ShareData['files'];
|
|
14
|
+
members: MemberData['members'];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface TransferOwnershipRequest {
|
|
18
|
+
files: ShareData['files'];
|
|
19
|
+
new_owner: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* FilesService - NDEx file operations and task management
|
|
24
|
+
* Handles file uploads, downloads, exports, and asynchronous task tracking
|
|
25
|
+
*/
|
|
26
|
+
export class FilesService {
|
|
27
|
+
constructor(private http: HTTPService) {}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Copy a file to a different location
|
|
31
|
+
* @param fromUuid - Source file UUID
|
|
32
|
+
* @param toPath - Target path
|
|
33
|
+
* @param type - File type (NETWORK, FOLDER, SHORTCUT)
|
|
34
|
+
* @param accessKey - Optional access key for protected files
|
|
35
|
+
*/
|
|
36
|
+
copyFile(fromUuid: string, toPath: string, type: string, accessKey?: string): Promise<any> {
|
|
37
|
+
let parameters: Record<string, any> = {};
|
|
38
|
+
|
|
39
|
+
if (accessKey !== undefined) {
|
|
40
|
+
parameters['accesskey'] = accessKey;
|
|
41
|
+
}
|
|
42
|
+
return this.http.post('files/copy', {from_uuid: fromUuid, type: type, to_path: toPath}, {params: parameters, version: 'v3'});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Get file count statistics for the current user */
|
|
46
|
+
getCount(): Promise<any> {
|
|
47
|
+
return this.http.get('files/count', {version: 'v3'});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Get files in the trash for the current user */
|
|
51
|
+
getTrash(): Promise<any> {
|
|
52
|
+
return this.http.get('files/trash', {version: 'v3'});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Permanently delete all files in trash */
|
|
56
|
+
emptyTrash(): Promise<any> {
|
|
57
|
+
return this.http.delete('files/trash', {version: 'v3'});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Permanently delete a file from trash
|
|
62
|
+
* @param fileId - File UUID to permanently delete
|
|
63
|
+
*/
|
|
64
|
+
permanentlyDeleteFile(fileId: string): Promise<any> {
|
|
65
|
+
return this.http.delete(`files/trash/${fileId}`, { version: 'v3' });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Restore files from trash
|
|
70
|
+
* @param networkIds - Array of network UUIDs to restore
|
|
71
|
+
* @param folderIds - Array of folder UUIDs to restore
|
|
72
|
+
* @param shortcutIds - Array of shortcut UUIDs to restore
|
|
73
|
+
*/
|
|
74
|
+
restoreFile(networkIds: string[], folderIds: string[], shortcutIds: string[]): Promise<any> {
|
|
75
|
+
return this.http.post('files/trash/restore', {networks: networkIds, folders: folderIds, shortcuts: shortcutIds}, {version: 'v3'});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private _validateShareData(data: any): void {
|
|
79
|
+
// Check if data is an object and has files property
|
|
80
|
+
if (typeof data !== 'object' || data === null || data.files === undefined) {
|
|
81
|
+
throw new Error('Data must be an object with a "files" property');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Check if files is an object
|
|
85
|
+
if (typeof data.files !== 'object' || data.files === null) {
|
|
86
|
+
throw new Error('The "files" property must be an object');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Check each key-value pair in files
|
|
90
|
+
const validValues = ['NETWORK', 'FOLDER', 'SHORTCUT'];
|
|
91
|
+
|
|
92
|
+
for (const [uuid, fileType] of Object.entries(data.files)) {
|
|
93
|
+
// Validate UUID format (basic validation)
|
|
94
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(uuid)) {
|
|
95
|
+
throw new Error(`Invalid UUID format: ${uuid}`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Validate file type
|
|
99
|
+
if (!validValues.includes(fileType as string)) {
|
|
100
|
+
throw new Error(`Invalid file type for ${uuid}: ${fileType}. Must be one of: ${validValues.join(', ')}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private _validateMemberData(data: any): void {
|
|
106
|
+
if (typeof data !== 'object' || data === null || data.members === undefined) {
|
|
107
|
+
throw new Error('Data must be an object with a "members" property');
|
|
108
|
+
}
|
|
109
|
+
const validValues = ['READ', 'WRITE'];
|
|
110
|
+
for (const [uuid, permission] of Object.entries(data.members)) {
|
|
111
|
+
if (!validValues.includes(permission as string)) {
|
|
112
|
+
throw new Error(`Invalid permission for ${uuid}: ${permission}. Must be one of: ${validValues.join(', ')}`);
|
|
113
|
+
}
|
|
114
|
+
if (typeof uuid !== 'string' || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(uuid)) {
|
|
115
|
+
throw new Error(`Invalid UUID format: ${uuid}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
updateMember(files: ShareData['files'], members: MemberData['members']): Promise<any> {
|
|
121
|
+
this._validateShareData({ files });
|
|
122
|
+
this._validateMemberData({ members });
|
|
123
|
+
return this.http.post('files/sharing/members', { files, members }, { version: 'v3' });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
listMembers(files: any): Promise<any> {
|
|
127
|
+
return this.http.get('files/sharing/members/list', {params: files, version: 'v3'});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
transferOwnership(files: ShareData['files'], newOwner: string): Promise<any> {
|
|
131
|
+
this._validateShareData({ files });
|
|
132
|
+
return this.http.post('files/sharing/transfer_ownership', { files, new_owner: newOwner }, { version: 'v3' });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
listShares(limit?: number): Promise<any> {
|
|
136
|
+
const parameters: Record<string, any> = {};
|
|
137
|
+
if (limit !== undefined) {
|
|
138
|
+
parameters['limit'] = limit;
|
|
139
|
+
}
|
|
140
|
+
return this.http.post('files/sharing/list', parameters, { version: 'v3' });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
share(files: ShareData['files']): Promise<any> {
|
|
144
|
+
this._validateShareData({ files });
|
|
145
|
+
return this.http.post('files/sharing/share', { files }, { version: 'v3' });
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
unshare(files: ShareData['files']): Promise<any> {
|
|
149
|
+
this._validateShareData({ files });
|
|
150
|
+
return this.http.post('files/sharing/unshare', { files }, { version: 'v3' });
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Folder operations
|
|
154
|
+
getFolders(limit?: number): Promise<any> {
|
|
155
|
+
let parameters: Record<string, any> = {};
|
|
156
|
+
|
|
157
|
+
if (limit !== undefined) {
|
|
158
|
+
parameters['limit'] = limit;
|
|
159
|
+
}
|
|
160
|
+
return this.http.get('files/folders', {params: parameters, version: 'v3'});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
createFolder(name: string, parentFolderId?: string): Promise<any> {
|
|
164
|
+
return this.http.post('files/folders', { name: name, parent: parentFolderId }, { version: 'v3' });
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
getFolder(folderId: string, accessKey?: string): Promise<any> {
|
|
168
|
+
const parameters: Record<string, any> = {};
|
|
169
|
+
if (accessKey !== undefined) {
|
|
170
|
+
parameters['accesskey'] = accessKey;
|
|
171
|
+
}
|
|
172
|
+
return this.http.get(`files/folders/${folderId}`, { params: parameters, version: 'v3' });
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
updateFolder(folderId: string, name: string, parentFolderId?: string): Promise<any> {
|
|
176
|
+
return this.http.put(`files/folders/${folderId}`, { name: name, parent: parentFolderId }, { version: 'v3' });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
deleteFolder(folderId: string): Promise<any> {
|
|
180
|
+
return this.http.delete(`files/folders/${folderId}`, { version: 'v3' });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
getFolderCount(folderId: string, accessKey?: string): Promise<any> {
|
|
184
|
+
const parameters: Record<string, any> = {};
|
|
185
|
+
if (accessKey !== undefined) {
|
|
186
|
+
parameters['accesskey'] = accessKey;
|
|
187
|
+
}
|
|
188
|
+
return this.http.get(`files/folders/${folderId}/count`, { params: parameters, version: 'v3' });
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
getFolderList(folderId: string, accessKey?: string, format?: string, type?: string): Promise<any> {
|
|
192
|
+
const parameters: Record<string, any> = {};
|
|
193
|
+
if (accessKey !== undefined) {
|
|
194
|
+
parameters['accesskey'] = accessKey;
|
|
195
|
+
}
|
|
196
|
+
if (format !== undefined) {
|
|
197
|
+
parameters['format'] = format;
|
|
198
|
+
}
|
|
199
|
+
if (type !== undefined) {
|
|
200
|
+
parameters['type'] = type;
|
|
201
|
+
}
|
|
202
|
+
return this.http.get(`files/folders/${folderId}/list`, { params: parameters, version: 'v3' });
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Shortcut operations
|
|
206
|
+
getShortcuts(limit?: number): Promise<any> {
|
|
207
|
+
let parameters: Record<string, any> = {};
|
|
208
|
+
|
|
209
|
+
if (limit !== undefined) {
|
|
210
|
+
parameters['limit'] = limit;
|
|
211
|
+
}
|
|
212
|
+
return this.http.get('files/shortcuts', {params: parameters, version: 'v3'});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
createShortcut(name: string, parentFolderId?: string, targetId?: string, targetType?: string): Promise<any> {
|
|
216
|
+
return this.http.post('files/shortcuts', { name: name, parent: parentFolderId, target: targetId, targetType }, { version: 'v3' });
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
getShortcut(shortcutId: string, accessKey?: string): Promise<any> {
|
|
220
|
+
const parameters: Record<string, any> = {};
|
|
221
|
+
if (accessKey !== undefined) {
|
|
222
|
+
parameters['accesskey'] = accessKey;
|
|
223
|
+
}
|
|
224
|
+
return this.http.get(`files/shortcuts/${shortcutId}`, { params: parameters, version: 'v3' });
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
updateShortcut(shortcutId: string, name: string, parentFolderId?: string, targetId?: string, targetType?: string): Promise<any> {
|
|
228
|
+
return this.http.put(`files/shortcuts/${shortcutId}`, { name: name, parent: parentFolderId, target: targetId, targetType }, { version: 'v3' });
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
deleteShortcut(shortcutId: string): Promise<any> {
|
|
232
|
+
return this.http.delete(`files/shortcuts/${shortcutId}`, { version: 'v3' });
|
|
233
|
+
}
|
|
234
|
+
}
|