curtain-web-api 1.0.62 → 1.0.64

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.
@@ -30,6 +30,60 @@ export const reviver = (key: any, value: any) => {
30
30
  return value;
31
31
  }
32
32
 
33
+ export interface SiteProperties {
34
+ non_user_post: boolean;
35
+ allow_user_set_permanent: boolean;
36
+ expiry_duration_options: number[];
37
+ default_expiry_duration_months: number;
38
+ }
39
+
40
+ export interface CurtainChunkedUploadStatus {
41
+ id: string;
42
+ filename?: string;
43
+ offset: number;
44
+ created_at: string;
45
+ status: number;
46
+ completed_at?: string;
47
+ original_filename?: string;
48
+ mime_type?: string;
49
+ file_size?: number;
50
+ upload_session_id?: string;
51
+ }
52
+
53
+ export interface CurtainChunkedUploadRequest {
54
+ file: File | Blob;
55
+ filename?: string;
56
+ upload_session_id?: string;
57
+ description?: string;
58
+ curtain_type?: string;
59
+ permanent?: boolean;
60
+ encrypted?: boolean;
61
+ expiry_duration?: number;
62
+ enable?: boolean;
63
+ }
64
+
65
+ export interface CurtainChunkedUploadResponse {
66
+ id: string;
67
+ filename: string;
68
+ offset: number;
69
+ }
70
+
71
+ export interface CurtainChunkedUploadCompletionRequest {
72
+ md5?: string;
73
+ description?: string;
74
+ curtain_type?: string;
75
+ permanent?: boolean;
76
+ encrypted?: boolean;
77
+ expiry_duration?: number;
78
+ enable?: boolean;
79
+ }
80
+
81
+ export interface CurtainChunkedUploadCompletionResponse {
82
+ curtain?: any;
83
+ message?: string;
84
+ error?: string;
85
+ }
86
+
33
87
  export class CurtainWebAPI {
34
88
  loginURL: string = "";
35
89
  logoutURL: string = "";
@@ -211,7 +265,7 @@ export class CurtainWebAPI {
211
265
  async putSettings(settings: any, enable: boolean = true, description: string = "", sessionType: string = "TP", encryption: CurtainEncryption = {
212
266
  encrypted: false,
213
267
  e2e: false,
214
- }, permanent: boolean = false, onUploadProgress: any = undefined) {
268
+ }, permanent: boolean = false, expiry_duration?: number, onUploadProgress: any = undefined) {
215
269
  let form: FormData = new FormData();
216
270
  let data = JSON.stringify(settings, replacer)
217
271
  if (enable) {
@@ -234,6 +288,9 @@ export class CurtainWebAPI {
234
288
  } else {
235
289
  form.append("permanent", "False")
236
290
  }
291
+ if (expiry_duration !== undefined) {
292
+ form.append("expiry_duration", expiry_duration.toString())
293
+ }
237
294
  if (encryption.encrypted && encryption.e2e && encryption.publicKey !== undefined) {
238
295
  const aesKey = await generateAESKey()
239
296
  console.log("Encrypting data")
@@ -350,6 +407,10 @@ export class CurtainWebAPI {
350
407
  }
351
408
  }
352
409
 
410
+ if ("expiry_duration" in sessionData) {
411
+ form.append("expiry_duration", sessionData["expiry_duration"].toString())
412
+ }
413
+
353
414
  if (encryption.encrypted) {
354
415
  form.append("encrypted", "True")
355
416
  } else {
@@ -422,9 +483,7 @@ export class CurtainWebAPI {
422
483
  getSiteProperties() {
423
484
  let headers = new AxiosHeaders();
424
485
  headers["Accept"] = "application/json";
425
- return this.axiosInstance.get(this.baseURL + "site-properties/", {headers: headers, responseType:"json"}).then((response) => {
426
- return response;
427
- });
486
+ return this.axiosInstance.get<SiteProperties>(this.baseURL + "site-properties/", {headers: headers, responseType:"json"});
428
487
  }
429
488
 
430
489
  saveDataFilterList(name: string, data: string, category: string = "") {
@@ -694,5 +753,206 @@ export class CurtainWebAPI {
694
753
  headers["Accept"] = "application/json";
695
754
  return this.axiosInstance.get(this.baseURL + "datacite/file/" + datacite_id + "/", {headers: headers, responseType: "blob"});
696
755
  }
756
+
757
+ uploadCurtainChunk(
758
+ request: CurtainChunkedUploadRequest,
759
+ uploadId?: string,
760
+ offset?: number,
761
+ totalSize?: number
762
+ ) {
763
+ const formData = new FormData();
764
+ formData.append('file', request.file);
765
+
766
+ if (request.filename) {
767
+ formData.append('filename', request.filename);
768
+ }
769
+ if (request.upload_session_id) {
770
+ formData.append('upload_session_id', request.upload_session_id);
771
+ }
772
+ if (request.description) {
773
+ formData.append('description', request.description);
774
+ }
775
+ if (request.curtain_type) {
776
+ formData.append('curtain_type', request.curtain_type);
777
+ }
778
+ if (request.permanent !== undefined) {
779
+ formData.append('permanent', request.permanent.toString());
780
+ }
781
+ if (request.encrypted !== undefined) {
782
+ formData.append('encrypted', request.encrypted.toString());
783
+ }
784
+ if (request.expiry_duration !== undefined) {
785
+ formData.append('expiry_duration', request.expiry_duration.toString());
786
+ }
787
+ if (request.enable !== undefined) {
788
+ formData.append('enable', request.enable.toString());
789
+ }
790
+
791
+ const url = uploadId
792
+ ? `${this.baseURL}curtain-chunked-upload/${uploadId}/`
793
+ : `${this.baseURL}curtain-chunked-upload/`;
794
+
795
+ const headers = new AxiosHeaders();
796
+ headers["Accept"] = "application/json";
797
+
798
+ const isChunkedUpload = offset !== undefined && totalSize !== undefined;
799
+
800
+ if (isChunkedUpload && offset !== undefined && totalSize !== undefined) {
801
+ const chunkEnd = offset + (request.file as Blob).size - 1;
802
+ headers["Content-Range"] = `bytes ${offset}-${chunkEnd}/${totalSize}`;
803
+ }
804
+
805
+ if (isChunkedUpload || uploadId) {
806
+ return this.axiosInstance.put<CurtainChunkedUploadResponse>(url, formData, {headers: headers});
807
+ } else {
808
+ return this.axiosInstance.post<CurtainChunkedUploadResponse>(url, formData, {headers: headers});
809
+ }
810
+ }
811
+
812
+ getCurtainUploadStatus(uploadId: string) {
813
+ let headers = new AxiosHeaders();
814
+ headers["Accept"] = "application/json";
815
+ return this.axiosInstance.get<CurtainChunkedUploadStatus>(`${this.baseURL}curtain-chunked-upload/${uploadId}/`, {headers: headers});
816
+ }
817
+
818
+ completeCurtainUpload(uploadId: string, request?: CurtainChunkedUploadCompletionRequest) {
819
+ const formData = new FormData();
820
+
821
+ if (request?.md5) {
822
+ formData.append('md5', request.md5);
823
+ }
824
+ if (request?.description) {
825
+ formData.append('description', request.description);
826
+ }
827
+ if (request?.curtain_type) {
828
+ formData.append('curtain_type', request.curtain_type);
829
+ }
830
+ if (request?.permanent !== undefined) {
831
+ formData.append('permanent', request.permanent.toString());
832
+ }
833
+ if (request?.encrypted !== undefined) {
834
+ formData.append('encrypted', request.encrypted.toString());
835
+ }
836
+ if (request?.expiry_duration !== undefined) {
837
+ formData.append('expiry_duration', request.expiry_duration.toString());
838
+ }
839
+ if (request?.enable !== undefined) {
840
+ formData.append('enable', request.enable.toString());
841
+ }
842
+
843
+ let headers = new AxiosHeaders();
844
+ headers["Accept"] = "application/json";
845
+ return this.axiosInstance.put<CurtainChunkedUploadCompletionResponse>(`${this.baseURL}curtain-chunked-upload/${uploadId}/`, formData, {headers: headers});
846
+ }
847
+
848
+ cancelCurtainUpload(uploadId: string) {
849
+ let headers = new AxiosHeaders();
850
+ headers["Accept"] = "application/json";
851
+ return this.axiosInstance.delete<void>(`${this.baseURL}curtain-chunked-upload/${uploadId}/`, {headers: headers});
852
+ }
853
+
854
+ async uploadCurtainFileInChunks(
855
+ file: File,
856
+ chunkSize: number = 1024 * 1024,
857
+ options?: {
858
+ description?: string;
859
+ curtain_type?: string;
860
+ permanent?: boolean;
861
+ encrypted?: boolean;
862
+ expiry_duration?: number;
863
+ enable?: boolean;
864
+ upload_session_id?: string;
865
+ onProgress?: (progress: number) => void;
866
+ }
867
+ ): Promise<CurtainChunkedUploadCompletionResponse> {
868
+ return new Promise(async (resolve, reject) => {
869
+ let uploadId: string | undefined;
870
+ let offset = 0;
871
+ const totalSize = file.size;
872
+
873
+ if (totalSize <= chunkSize) {
874
+ try {
875
+ const response = await this.uploadCurtainChunk({
876
+ file: file,
877
+ filename: file.name,
878
+ upload_session_id: options?.upload_session_id,
879
+ description: options?.description,
880
+ curtain_type: options?.curtain_type,
881
+ permanent: options?.permanent,
882
+ encrypted: options?.encrypted,
883
+ expiry_duration: options?.expiry_duration,
884
+ enable: options?.enable
885
+ });
886
+
887
+ const completionResponse = await this.completeCurtainUpload(response.data.id, {
888
+ description: options?.description,
889
+ curtain_type: options?.curtain_type,
890
+ permanent: options?.permanent,
891
+ encrypted: options?.encrypted,
892
+ expiry_duration: options?.expiry_duration,
893
+ enable: options?.enable
894
+ });
895
+ resolve(completionResponse.data);
896
+ } catch (error) {
897
+ reject(error);
898
+ }
899
+ return;
900
+ }
901
+
902
+ const uploadNextChunk = async () => {
903
+ if (offset >= totalSize) {
904
+ if (uploadId) {
905
+ try {
906
+ const completionResponse = await this.completeCurtainUpload(uploadId, {
907
+ description: options?.description,
908
+ curtain_type: options?.curtain_type,
909
+ permanent: options?.permanent,
910
+ encrypted: options?.encrypted,
911
+ expiry_duration: options?.expiry_duration,
912
+ enable: options?.enable
913
+ });
914
+ resolve(completionResponse.data);
915
+ } catch (error) {
916
+ reject(error);
917
+ }
918
+ } else {
919
+ reject(new Error('Upload failed: No upload ID'));
920
+ }
921
+ return;
922
+ }
923
+
924
+ const end = Math.min(offset + chunkSize, totalSize);
925
+ const chunk = file.slice(offset, end);
926
+
927
+ try {
928
+ const response = await this.uploadCurtainChunk({
929
+ file: chunk,
930
+ filename: file.name,
931
+ upload_session_id: options?.upload_session_id,
932
+ description: options?.description,
933
+ curtain_type: options?.curtain_type,
934
+ permanent: options?.permanent,
935
+ encrypted: options?.encrypted,
936
+ expiry_duration: options?.expiry_duration,
937
+ enable: options?.enable
938
+ }, uploadId, offset, totalSize);
939
+
940
+ uploadId = response.data.id;
941
+ offset = response.data.offset;
942
+
943
+ const progress = (offset / totalSize) * 100;
944
+ if (options?.onProgress) {
945
+ options.onProgress(progress);
946
+ }
947
+
948
+ uploadNextChunk();
949
+ } catch (error) {
950
+ reject(error);
951
+ }
952
+ };
953
+
954
+ uploadNextChunk();
955
+ });
956
+ }
697
957
  }
698
958
 
package/src/index.ts CHANGED
@@ -1,4 +1,14 @@
1
- import {CurtainWebAPI, replacer, reviver} from "./classes/curtain-api";
1
+ import {
2
+ CurtainWebAPI,
3
+ replacer,
4
+ reviver,
5
+ SiteProperties,
6
+ CurtainChunkedUploadStatus,
7
+ CurtainChunkedUploadRequest,
8
+ CurtainChunkedUploadResponse,
9
+ CurtainChunkedUploadCompletionRequest,
10
+ CurtainChunkedUploadCompletionResponse
11
+ } from "./classes/curtain-api";
2
12
  import {User} from "./classes/curtain-user";
3
13
  import {getProteomicsData, getPrideData, getEBIAlpha, getInteractomeAtlas, getStringDBInteractions} from "./utilities";
4
14
  import {importKey, importPrivateKey, exportPrivateKey, exportKeyString, exportPublicKey, importPublicKey, CurtainEncryption, generateKeyPair, encryptDataRSA, decryptDataRSA, loadFromLocalStorage, saveToLocalStorage, pemToArrayBuffer, base64ToArrayBuffer, arrayBufferToBase64String, removeLines} from "./classes/curtain-encryption";
@@ -13,6 +23,12 @@ export {
13
23
  getStringDBInteractions,
14
24
  replacer,
15
25
  reviver,
26
+ SiteProperties,
27
+ CurtainChunkedUploadStatus,
28
+ CurtainChunkedUploadRequest,
29
+ CurtainChunkedUploadResponse,
30
+ CurtainChunkedUploadCompletionRequest,
31
+ CurtainChunkedUploadCompletionResponse,
16
32
  importKey,
17
33
  importPrivateKey,
18
34
  exportPrivateKey,
package/tsconfig.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "es2015", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
4
- "lib": ["es6"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
5
- "module": "commonjs", /* Specify what module code is generated. */
3
+ "target": "ES2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
4
+ "lib": ["ES2020", "DOM"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
5
+ "module": "ES2020", /* Specify what module code is generated. */
6
+ "moduleResolution": "bundler", /* Specify how TypeScript looks up a file from a given module specifier. */
6
7
  "rootDir": "src", /* Specify the root folder within your source files. */
7
8
  "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
8
9
  "outDir": "build", /* Specify an output folder for all emitted files. */