@webiny/app-file-manager-s3 6.3.0-beta.4 → 6.4.0-beta.0

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.
@@ -1,3 +0,0 @@
1
- export {};
2
-
3
- //# sourceMappingURL=MultiPartUploadAPI.js.map
@@ -1,38 +1,32 @@
1
- import gql from "graphql-tag";
2
- export class MultiPartUploadGraphQLAPI {
3
- constructor(client) {
4
- this.client = client;
5
- }
6
- async createUpload(params) {
7
- const {
8
- data,
9
- errors
10
- } = await this.client.mutate({
11
- mutation: CREATE_UPLOAD,
12
- variables: params
13
- });
14
- if (!data) {
15
- console.error(errors);
16
- throw new Error(`Failed to initialize a multi-part file upload!`);
1
+ import graphql_tag from "graphql-tag";
2
+ class MultiPartUploadGraphQLAPI {
3
+ constructor(client){
4
+ this.client = client;
17
5
  }
18
- return data.fileManager.createMultiPartUpload.data;
19
- }
20
- async completeUpload(params) {
21
- const {
22
- data,
23
- errors
24
- } = await this.client.mutate({
25
- mutation: COMPLETE_UPLOAD,
26
- variables: params
27
- });
28
- if (!data) {
29
- console.error(errors);
30
- throw new Error(`Failed to complete a multi-part file upload!`);
6
+ async createUpload(params) {
7
+ const { data, errors } = await this.client.mutate({
8
+ mutation: CREATE_UPLOAD,
9
+ variables: params
10
+ });
11
+ if (!data) {
12
+ console.error(errors);
13
+ throw new Error("Failed to initialize a multi-part file upload!");
14
+ }
15
+ return data.fileManager.createMultiPartUpload.data;
16
+ }
17
+ async completeUpload(params) {
18
+ const { data, errors } = await this.client.mutate({
19
+ mutation: COMPLETE_UPLOAD,
20
+ variables: params
21
+ });
22
+ if (!data) {
23
+ console.error(errors);
24
+ throw new Error("Failed to complete a multi-part file upload!");
25
+ }
26
+ return data.fileManager.completeMultiPartUpload.data;
31
27
  }
32
- return data.fileManager.completeMultiPartUpload.data;
33
- }
34
28
  }
35
- const CREATE_UPLOAD = gql`
29
+ const CREATE_UPLOAD = graphql_tag`
36
30
  mutation CreateMultiPartUpload($data: PreSignedPostPayloadInput!, $numberOfParts: Number!) {
37
31
  fileManager {
38
32
  createMultiPartUpload(data: $data, numberOfParts: $numberOfParts) {
@@ -59,7 +53,7 @@ const CREATE_UPLOAD = gql`
59
53
  }
60
54
  }
61
55
  `;
62
- const COMPLETE_UPLOAD = gql`
56
+ const COMPLETE_UPLOAD = graphql_tag`
63
57
  mutation CompleteMultiPartUpload($fileKey: String!, $uploadId: String!) {
64
58
  fileManager {
65
59
  completeMultiPartUpload(fileKey: $fileKey, uploadId: $uploadId) {
@@ -73,5 +67,6 @@ const COMPLETE_UPLOAD = gql`
73
67
  }
74
68
  }
75
69
  `;
70
+ export { MultiPartUploadGraphQLAPI };
76
71
 
77
72
  //# sourceMappingURL=MultiPartUploadGraphQLAPI.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["gql","MultiPartUploadGraphQLAPI","constructor","client","createUpload","params","data","errors","mutate","mutation","CREATE_UPLOAD","variables","console","error","Error","fileManager","createMultiPartUpload","completeUpload","COMPLETE_UPLOAD","completeMultiPartUpload"],"sources":["MultiPartUploadGraphQLAPI.ts"],"sourcesContent":["import type { UploadOptions } from \"@webiny/app/types.js\";\nimport gql from \"graphql-tag\";\nimport type {\n CompleteUploadParams,\n CreateUploadParams,\n MultiPartUpload,\n MultiPartUploadAPI\n} from \"~/MultiPartUploadAPI.js\";\n\nexport class MultiPartUploadGraphQLAPI implements MultiPartUploadAPI {\n private client: UploadOptions[\"apolloClient\"];\n\n constructor(client: UploadOptions[\"apolloClient\"]) {\n this.client = client;\n }\n\n async createUpload(params: CreateUploadParams): Promise<MultiPartUpload> {\n const { data, errors } = await this.client.mutate<CreateUploadResponse>({\n mutation: CREATE_UPLOAD,\n variables: params\n });\n\n if (!data) {\n console.error(errors);\n throw new Error(`Failed to initialize a multi-part file upload!`);\n }\n\n return data.fileManager.createMultiPartUpload.data;\n }\n\n async completeUpload(params: CompleteUploadParams): Promise<boolean> {\n const { data, errors } = await this.client.mutate<CompleteUploadResponse>({\n mutation: COMPLETE_UPLOAD,\n variables: params\n });\n\n if (!data) {\n console.error(errors);\n throw new Error(`Failed to complete a multi-part file upload!`);\n }\n\n return data.fileManager.completeMultiPartUpload.data;\n }\n}\n\nconst CREATE_UPLOAD = gql`\n mutation CreateMultiPartUpload($data: PreSignedPostPayloadInput!, $numberOfParts: Number!) {\n fileManager {\n createMultiPartUpload(data: $data, numberOfParts: $numberOfParts) {\n data {\n file {\n id\n key\n name\n size\n type\n }\n uploadId\n parts {\n partNumber\n url\n }\n }\n error {\n code\n message\n data\n }\n }\n }\n }\n`;\n\ninterface CreateUploadResponse {\n fileManager: {\n createMultiPartUpload: {\n data: MultiPartUpload;\n error: {\n code: string;\n message: string;\n data: Record<string, any>;\n };\n };\n };\n}\n\nconst COMPLETE_UPLOAD = gql`\n mutation CompleteMultiPartUpload($fileKey: String!, $uploadId: String!) {\n fileManager {\n completeMultiPartUpload(fileKey: $fileKey, uploadId: $uploadId) {\n data\n error {\n code\n message\n data\n }\n }\n }\n }\n`;\n\ninterface CompleteUploadResponse {\n fileManager: {\n completeMultiPartUpload: {\n data: boolean;\n error: {\n code: string;\n message: string;\n data: Record<string, any>;\n };\n };\n };\n}\n"],"mappings":"AACA,OAAOA,GAAG,MAAM,aAAa;AAQ7B,OAAO,MAAMC,yBAAyB,CAA+B;EAGjEC,WAAWA,CAACC,MAAqC,EAAE;IAC/C,IAAI,CAACA,MAAM,GAAGA,MAAM;EACxB;EAEA,MAAMC,YAAYA,CAACC,MAA0B,EAA4B;IACrE,MAAM;MAAEC,IAAI;MAAEC;IAAO,CAAC,GAAG,MAAM,IAAI,CAACJ,MAAM,CAACK,MAAM,CAAuB;MACpEC,QAAQ,EAAEC,aAAa;MACvBC,SAAS,EAAEN;IACf,CAAC,CAAC;IAEF,IAAI,CAACC,IAAI,EAAE;MACPM,OAAO,CAACC,KAAK,CAACN,MAAM,CAAC;MACrB,MAAM,IAAIO,KAAK,CAAC,gDAAgD,CAAC;IACrE;IAEA,OAAOR,IAAI,CAACS,WAAW,CAACC,qBAAqB,CAACV,IAAI;EACtD;EAEA,MAAMW,cAAcA,CAACZ,MAA4B,EAAoB;IACjE,MAAM;MAAEC,IAAI;MAAEC;IAAO,CAAC,GAAG,MAAM,IAAI,CAACJ,MAAM,CAACK,MAAM,CAAyB;MACtEC,QAAQ,EAAES,eAAe;MACzBP,SAAS,EAAEN;IACf,CAAC,CAAC;IAEF,IAAI,CAACC,IAAI,EAAE;MACPM,OAAO,CAACC,KAAK,CAACN,MAAM,CAAC;MACrB,MAAM,IAAIO,KAAK,CAAC,8CAA8C,CAAC;IACnE;IAEA,OAAOR,IAAI,CAACS,WAAW,CAACI,uBAAuB,CAACb,IAAI;EACxD;AACJ;AAEA,MAAMI,aAAa,GAAGV,GAAG;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AAeD,MAAMkB,eAAe,GAAGlB,GAAG;AAC3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"MultiPartUploadGraphQLAPI.js","sources":["../src/MultiPartUploadGraphQLAPI.ts"],"sourcesContent":["import type { UploadOptions } from \"@webiny/app/types.js\";\nimport gql from \"graphql-tag\";\nimport type {\n CompleteUploadParams,\n CreateUploadParams,\n MultiPartUpload,\n MultiPartUploadAPI\n} from \"~/MultiPartUploadAPI.js\";\n\nexport class MultiPartUploadGraphQLAPI implements MultiPartUploadAPI {\n private client: UploadOptions[\"apolloClient\"];\n\n constructor(client: UploadOptions[\"apolloClient\"]) {\n this.client = client;\n }\n\n async createUpload(params: CreateUploadParams): Promise<MultiPartUpload> {\n const { data, errors } = await this.client.mutate<CreateUploadResponse>({\n mutation: CREATE_UPLOAD,\n variables: params\n });\n\n if (!data) {\n console.error(errors);\n throw new Error(`Failed to initialize a multi-part file upload!`);\n }\n\n return data.fileManager.createMultiPartUpload.data;\n }\n\n async completeUpload(params: CompleteUploadParams): Promise<boolean> {\n const { data, errors } = await this.client.mutate<CompleteUploadResponse>({\n mutation: COMPLETE_UPLOAD,\n variables: params\n });\n\n if (!data) {\n console.error(errors);\n throw new Error(`Failed to complete a multi-part file upload!`);\n }\n\n return data.fileManager.completeMultiPartUpload.data;\n }\n}\n\nconst CREATE_UPLOAD = gql`\n mutation CreateMultiPartUpload($data: PreSignedPostPayloadInput!, $numberOfParts: Number!) {\n fileManager {\n createMultiPartUpload(data: $data, numberOfParts: $numberOfParts) {\n data {\n file {\n id\n key\n name\n size\n type\n }\n uploadId\n parts {\n partNumber\n url\n }\n }\n error {\n code\n message\n data\n }\n }\n }\n }\n`;\n\ninterface CreateUploadResponse {\n fileManager: {\n createMultiPartUpload: {\n data: MultiPartUpload;\n error: {\n code: string;\n message: string;\n data: Record<string, any>;\n };\n };\n };\n}\n\nconst COMPLETE_UPLOAD = gql`\n mutation CompleteMultiPartUpload($fileKey: String!, $uploadId: String!) {\n fileManager {\n completeMultiPartUpload(fileKey: $fileKey, uploadId: $uploadId) {\n data\n error {\n code\n message\n data\n }\n }\n }\n }\n`;\n\ninterface CompleteUploadResponse {\n fileManager: {\n completeMultiPartUpload: {\n data: boolean;\n error: {\n code: string;\n message: string;\n data: Record<string, any>;\n };\n };\n };\n}\n"],"names":["MultiPartUploadGraphQLAPI","client","params","data","errors","CREATE_UPLOAD","console","Error","COMPLETE_UPLOAD","gql"],"mappings":";AASO,MAAMA;IAGT,YAAYC,MAAqC,CAAE;QAC/C,IAAI,CAAC,MAAM,GAAGA;IAClB;IAEA,MAAM,aAAaC,MAA0B,EAA4B;QACrE,MAAM,EAAEC,IAAI,EAAEC,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAuB;YACpE,UAAUC;YACV,WAAWH;QACf;QAEA,IAAI,CAACC,MAAM;YACPG,QAAQ,KAAK,CAACF;YACd,MAAM,IAAIG,MAAM;QACpB;QAEA,OAAOJ,KAAK,WAAW,CAAC,qBAAqB,CAAC,IAAI;IACtD;IAEA,MAAM,eAAeD,MAA4B,EAAoB;QACjE,MAAM,EAAEC,IAAI,EAAEC,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAyB;YACtE,UAAUI;YACV,WAAWN;QACf;QAEA,IAAI,CAACC,MAAM;YACPG,QAAQ,KAAK,CAACF;YACd,MAAM,IAAIG,MAAM;QACpB;QAEA,OAAOJ,KAAK,WAAW,CAAC,uBAAuB,CAAC,IAAI;IACxD;AACJ;AAEA,MAAME,gBAAgBI,WAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;AA0B1B,CAAC;AAeD,MAAMD,kBAAkBC,WAAG,CAAC;;;;;;;;;;;;;AAa5B,CAAC"}
@@ -1,47 +1,32 @@
1
1
  import { MultiPartUploader } from "./MultiPartUploader.js";
2
2
  import { MultiPartUploadGraphQLAPI } from "./MultiPartUploadGraphQLAPI.js";
3
- export class MultiPartUploadStrategy {
4
- async upload(file, options) {
5
- const api = new MultiPartUploadGraphQLAPI(options.apolloClient);
6
- const uploader = new MultiPartUploader(api, {
7
- chunkSize: this.detectChunkSize(),
8
- parallelUploads: this.detectParallelChunks()
9
- });
10
- if (options.onProgress) {
11
- uploader.onProgress(options.onProgress);
3
+ class MultiPartUploadStrategy {
4
+ async upload(file, options) {
5
+ const api = new MultiPartUploadGraphQLAPI(options.apolloClient);
6
+ const uploader = new MultiPartUploader(api, {
7
+ chunkSize: this.detectChunkSize(),
8
+ parallelUploads: this.detectParallelChunks()
9
+ });
10
+ if (options.onProgress) uploader.onProgress(options.onProgress);
11
+ return uploader.uploadFile(file);
12
12
  }
13
- return uploader.uploadFile(file);
14
- }
15
- detectChunkSize() {
16
- const envSize = parseInt(process.env.WEBINY_FILE_UPLOAD_CHUNK_SIZE || "0");
17
-
18
- // For dev purposes, we take this global var into consideration.
19
- if (process.env.NODE_ENV === "development") {
20
- // @ts-expect-error
21
- const windowSize = window["fmUploadChunkSize"];
22
- if (windowSize) {
23
- return windowSize;
24
- }
13
+ detectChunkSize() {
14
+ const envSize = parseInt(process.env.WEBINY_FILE_UPLOAD_CHUNK_SIZE || "0");
15
+ if ("development" === process.env.NODE_ENV) {
16
+ const windowSize = window["fmUploadChunkSize"];
17
+ if (windowSize) return windowSize;
18
+ }
19
+ return envSize || 50;
25
20
  }
26
-
27
- // As a last resort, we check the baked in value, or fall back to 50MB chunk size.
28
- return envSize || 50;
29
- }
30
- detectParallelChunks() {
31
- const envChunks = parseInt(process.env.WEBINY_FILE_UPLOAD_PARALLEL_CHUNKS || "0");
32
-
33
- // For dev purposes, we take this global var into consideration.
34
- if (process.env.NODE_ENV === "development") {
35
- // @ts-expect-error
36
- const windowChunks = window["fmUploadParallelChunks"];
37
- if (windowChunks) {
38
- return windowChunks;
39
- }
21
+ detectParallelChunks() {
22
+ const envChunks = parseInt(process.env.WEBINY_FILE_UPLOAD_PARALLEL_CHUNKS || "0");
23
+ if ("development" === process.env.NODE_ENV) {
24
+ const windowChunks = window["fmUploadParallelChunks"];
25
+ if (windowChunks) return windowChunks;
26
+ }
27
+ return envChunks || 5;
40
28
  }
41
-
42
- // As a last resort, we check the baked in value, or fall back to 5 parallel chunks.
43
- return envChunks || 5;
44
- }
45
29
  }
30
+ export { MultiPartUploadStrategy };
46
31
 
47
32
  //# sourceMappingURL=MultiPartUploadStrategy.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["MultiPartUploader","MultiPartUploadGraphQLAPI","MultiPartUploadStrategy","upload","file","options","api","apolloClient","uploader","chunkSize","detectChunkSize","parallelUploads","detectParallelChunks","onProgress","uploadFile","envSize","parseInt","process","env","WEBINY_FILE_UPLOAD_CHUNK_SIZE","NODE_ENV","windowSize","window","envChunks","WEBINY_FILE_UPLOAD_PARALLEL_CHUNKS","windowChunks"],"sources":["MultiPartUploadStrategy.ts"],"sourcesContent":["import type { UploadedFile, UploadOptions } from \"@webiny/app/types.js\";\nimport type { FileUploadStrategy } from \"~/index.js\";\nimport { MultiPartUploader } from \"~/MultiPartUploader.js\";\nimport { MultiPartUploadGraphQLAPI } from \"~/MultiPartUploadGraphQLAPI.js\";\n\nexport class MultiPartUploadStrategy implements FileUploadStrategy {\n async upload(file: File, options: UploadOptions): Promise<UploadedFile> {\n const api = new MultiPartUploadGraphQLAPI(options.apolloClient);\n\n const uploader = new MultiPartUploader(api, {\n chunkSize: this.detectChunkSize(),\n parallelUploads: this.detectParallelChunks()\n });\n\n if (options.onProgress) {\n uploader.onProgress(options.onProgress);\n }\n return uploader.uploadFile(file);\n }\n\n private detectChunkSize(): number {\n const envSize = parseInt(process.env.WEBINY_FILE_UPLOAD_CHUNK_SIZE || \"0\");\n\n // For dev purposes, we take this global var into consideration.\n if (process.env.NODE_ENV === \"development\") {\n // @ts-expect-error\n const windowSize = window[\"fmUploadChunkSize\"];\n if (windowSize) {\n return windowSize;\n }\n }\n\n // As a last resort, we check the baked in value, or fall back to 50MB chunk size.\n return envSize || 50;\n }\n\n private detectParallelChunks(): number {\n const envChunks = parseInt(process.env.WEBINY_FILE_UPLOAD_PARALLEL_CHUNKS || \"0\");\n\n // For dev purposes, we take this global var into consideration.\n if (process.env.NODE_ENV === \"development\") {\n // @ts-expect-error\n const windowChunks = window[\"fmUploadParallelChunks\"];\n if (windowChunks) {\n return windowChunks;\n }\n }\n\n // As a last resort, we check the baked in value, or fall back to 5 parallel chunks.\n return envChunks || 5;\n }\n}\n"],"mappings":"AAEA,SAASA,iBAAiB;AAC1B,SAASC,yBAAyB;AAElC,OAAO,MAAMC,uBAAuB,CAA+B;EAC/D,MAAMC,MAAMA,CAACC,IAAU,EAAEC,OAAsB,EAAyB;IACpE,MAAMC,GAAG,GAAG,IAAIL,yBAAyB,CAACI,OAAO,CAACE,YAAY,CAAC;IAE/D,MAAMC,QAAQ,GAAG,IAAIR,iBAAiB,CAACM,GAAG,EAAE;MACxCG,SAAS,EAAE,IAAI,CAACC,eAAe,CAAC,CAAC;MACjCC,eAAe,EAAE,IAAI,CAACC,oBAAoB,CAAC;IAC/C,CAAC,CAAC;IAEF,IAAIP,OAAO,CAACQ,UAAU,EAAE;MACpBL,QAAQ,CAACK,UAAU,CAACR,OAAO,CAACQ,UAAU,CAAC;IAC3C;IACA,OAAOL,QAAQ,CAACM,UAAU,CAACV,IAAI,CAAC;EACpC;EAEQM,eAAeA,CAAA,EAAW;IAC9B,MAAMK,OAAO,GAAGC,QAAQ,CAACC,OAAO,CAACC,GAAG,CAACC,6BAA6B,IAAI,GAAG,CAAC;;IAE1E;IACA,IAAIF,OAAO,CAACC,GAAG,CAACE,QAAQ,KAAK,aAAa,EAAE;MACxC;MACA,MAAMC,UAAU,GAAGC,MAAM,CAAC,mBAAmB,CAAC;MAC9C,IAAID,UAAU,EAAE;QACZ,OAAOA,UAAU;MACrB;IACJ;;IAEA;IACA,OAAON,OAAO,IAAI,EAAE;EACxB;EAEQH,oBAAoBA,CAAA,EAAW;IACnC,MAAMW,SAAS,GAAGP,QAAQ,CAACC,OAAO,CAACC,GAAG,CAACM,kCAAkC,IAAI,GAAG,CAAC;;IAEjF;IACA,IAAIP,OAAO,CAACC,GAAG,CAACE,QAAQ,KAAK,aAAa,EAAE;MACxC;MACA,MAAMK,YAAY,GAAGH,MAAM,CAAC,wBAAwB,CAAC;MACrD,IAAIG,YAAY,EAAE;QACd,OAAOA,YAAY;MACvB;IACJ;;IAEA;IACA,OAAOF,SAAS,IAAI,CAAC;EACzB;AACJ","ignoreList":[]}
1
+ {"version":3,"file":"MultiPartUploadStrategy.js","sources":["../src/MultiPartUploadStrategy.ts"],"sourcesContent":["import type { UploadedFile, UploadOptions } from \"@webiny/app/types.js\";\nimport type { FileUploadStrategy } from \"~/index.js\";\nimport { MultiPartUploader } from \"~/MultiPartUploader.js\";\nimport { MultiPartUploadGraphQLAPI } from \"~/MultiPartUploadGraphQLAPI.js\";\n\nexport class MultiPartUploadStrategy implements FileUploadStrategy {\n async upload(file: File, options: UploadOptions): Promise<UploadedFile> {\n const api = new MultiPartUploadGraphQLAPI(options.apolloClient);\n\n const uploader = new MultiPartUploader(api, {\n chunkSize: this.detectChunkSize(),\n parallelUploads: this.detectParallelChunks()\n });\n\n if (options.onProgress) {\n uploader.onProgress(options.onProgress);\n }\n return uploader.uploadFile(file);\n }\n\n private detectChunkSize(): number {\n const envSize = parseInt(process.env.WEBINY_FILE_UPLOAD_CHUNK_SIZE || \"0\");\n\n // For dev purposes, we take this global var into consideration.\n if (process.env.NODE_ENV === \"development\") {\n // @ts-expect-error\n const windowSize = window[\"fmUploadChunkSize\"];\n if (windowSize) {\n return windowSize;\n }\n }\n\n // As a last resort, we check the baked in value, or fall back to 50MB chunk size.\n return envSize || 50;\n }\n\n private detectParallelChunks(): number {\n const envChunks = parseInt(process.env.WEBINY_FILE_UPLOAD_PARALLEL_CHUNKS || \"0\");\n\n // For dev purposes, we take this global var into consideration.\n if (process.env.NODE_ENV === \"development\") {\n // @ts-expect-error\n const windowChunks = window[\"fmUploadParallelChunks\"];\n if (windowChunks) {\n return windowChunks;\n }\n }\n\n // As a last resort, we check the baked in value, or fall back to 5 parallel chunks.\n return envChunks || 5;\n }\n}\n"],"names":["MultiPartUploadStrategy","file","options","api","MultiPartUploadGraphQLAPI","uploader","MultiPartUploader","envSize","parseInt","process","windowSize","window","envChunks","windowChunks"],"mappings":";;AAKO,MAAMA;IACT,MAAM,OAAOC,IAAU,EAAEC,OAAsB,EAAyB;QACpE,MAAMC,MAAM,IAAIC,0BAA0BF,QAAQ,YAAY;QAE9D,MAAMG,WAAW,IAAIC,kBAAkBH,KAAK;YACxC,WAAW,IAAI,CAAC,eAAe;YAC/B,iBAAiB,IAAI,CAAC,oBAAoB;QAC9C;QAEA,IAAID,QAAQ,UAAU,EAClBG,SAAS,UAAU,CAACH,QAAQ,UAAU;QAE1C,OAAOG,SAAS,UAAU,CAACJ;IAC/B;IAEQ,kBAA0B;QAC9B,MAAMM,UAAUC,SAASC,QAAQ,GAAG,CAAC,6BAA6B,IAAI;QAGtE,IAAIA,AAAyB,kBAAzBA,QAAQ,GAAG,CAAC,QAAQ,EAAoB;YAExC,MAAMC,aAAaC,MAAM,CAAC,oBAAoB;YAC9C,IAAID,YACA,OAAOA;QAEf;QAGA,OAAOH,WAAW;IACtB;IAEQ,uBAA+B;QACnC,MAAMK,YAAYJ,SAASC,QAAQ,GAAG,CAAC,kCAAkC,IAAI;QAG7E,IAAIA,AAAyB,kBAAzBA,QAAQ,GAAG,CAAC,QAAQ,EAAoB;YAExC,MAAMI,eAAeF,MAAM,CAAC,yBAAyB;YACrD,IAAIE,cACA,OAAOA;QAEf;QAGA,OAAOD,aAAa;IACxB;AACJ"}
@@ -1,165 +1,139 @@
1
- import pRetry from "p-retry";
2
- export class MultiPartUploader {
3
- activeConnections = new Map();
4
- progressTracker = new Map();
5
- onErrorFn = error => console.error(error);
6
- constructor(api, options = {}) {
7
- this.api = api;
8
- const chunkSize = options.chunkSize || 50;
9
- const parallelUploads = options.parallelUploads || 5;
10
- this.chunkSize = Math.max(1024 * 1024 * chunkSize, 1024 * 1024 * 5);
11
- this.parallelUploads = Math.min(parallelUploads, 15);
12
- }
13
- async uploadFile(file) {
14
- this.file = file;
15
- const numberOfParts = Math.ceil(file.size / this.chunkSize);
16
- try {
17
- /**
18
- * Initialize the file upload on AWS S3.
19
- */
20
- this.upload = await this.api.createUpload({
21
- data: {
22
- name: file.name,
23
- size: file.size,
24
- type: file.type
25
- },
26
- numberOfParts
27
- });
28
-
29
- /**
30
- * Run the defined number of parallel uploads. Each thread will continue to process parts
31
- * for as long as there are parts to upload. The promise will resolve once there's no more parts to upload.
32
- */
33
- const threads = Math.min(numberOfParts, this.parallelUploads);
34
- await Promise.all(Array.from({
35
- length: threads
36
- }).map(() => this.uploadNextPart()));
37
- await this.complete();
38
- return this.upload.file;
39
- } catch (error) {
40
- await this.complete(error);
41
- throw error;
1
+ import p_retry from "p-retry";
2
+ class MultiPartUploader {
3
+ constructor(api, options = {}){
4
+ this.activeConnections = new Map();
5
+ this.progressTracker = new Map();
6
+ this.onErrorFn = (error)=>console.error(error);
7
+ this.api = api;
8
+ const chunkSize = options.chunkSize || 50;
9
+ const parallelUploads = options.parallelUploads || 5;
10
+ this.chunkSize = Math.max(1048576 * chunkSize, 5242880);
11
+ this.parallelUploads = Math.min(parallelUploads, 15);
42
12
  }
43
- }
44
- onProgress(onProgress) {
45
- this.onProgressFn = onProgress;
46
- return this;
47
- }
48
- onError(onError) {
49
- this.onErrorFn = onError;
50
- return this;
51
- }
52
- async complete(error) {
53
- if (error) {
54
- this.onErrorFn(error);
55
- return;
13
+ async uploadFile(file) {
14
+ this.file = file;
15
+ const numberOfParts = Math.ceil(file.size / this.chunkSize);
16
+ try {
17
+ this.upload = await this.api.createUpload({
18
+ data: {
19
+ name: file.name,
20
+ size: file.size,
21
+ type: file.type
22
+ },
23
+ numberOfParts
24
+ });
25
+ const threads = Math.min(numberOfParts, this.parallelUploads);
26
+ await Promise.all(Array.from({
27
+ length: threads
28
+ }).map(()=>this.uploadNextPart()));
29
+ await this.complete();
30
+ return this.upload.file;
31
+ } catch (error) {
32
+ await this.complete(error);
33
+ throw error;
34
+ }
56
35
  }
57
- try {
58
- await this.sendCompleteRequest();
59
- } catch (error) {
60
- this.onErrorFn(error);
36
+ onProgress(onProgress) {
37
+ this.onProgressFn = onProgress;
38
+ return this;
61
39
  }
62
- }
63
- async sendCompleteRequest() {
64
- this.assertIsDefined(this.upload, `Upload must be created before calling "sendCompleteRequest"!`);
65
- return this.api.completeUpload({
66
- fileKey: this.upload.file.key,
67
- uploadId: this.upload.uploadId
68
- });
69
- }
70
- progressListener(part, event) {
71
- if (!this.file) {
72
- return;
40
+ onError(onError) {
41
+ this.onErrorFn = onError;
42
+ return this;
73
43
  }
74
- this.progressTracker.set(part.partNumber, event.loaded);
75
- const uploaded = Array.from(this.progressTracker.values()).reduce((sum = 0, value) => sum + value);
76
- const uploadedSize = Math.min(uploaded, this.file.size);
77
- if (this.onProgressFn) {
78
- try {
79
- this.onProgressFn({
80
- sent: uploadedSize,
81
- total: this.file.size,
82
- percentage: Math.round(uploadedSize / this.file.size * 100)
44
+ async complete(error) {
45
+ if (error) return void this.onErrorFn(error);
46
+ try {
47
+ await this.sendCompleteRequest();
48
+ } catch (error) {
49
+ this.onErrorFn(error);
50
+ }
51
+ }
52
+ async sendCompleteRequest() {
53
+ this.assertIsDefined(this.upload, 'Upload must be created before calling "sendCompleteRequest"!');
54
+ return this.api.completeUpload({
55
+ fileKey: this.upload.file.key,
56
+ uploadId: this.upload.uploadId
83
57
  });
84
- } catch (err) {
85
- console.error(`Error executing the "onProgress" callback`, err);
86
- }
87
58
  }
88
- }
89
- async uploadNextPart() {
90
- if (!this.upload) {
91
- return;
59
+ progressListener(part, event) {
60
+ if (!this.file) return;
61
+ this.progressTracker.set(part.partNumber, event.loaded);
62
+ const uploaded = Array.from(this.progressTracker.values()).reduce((sum = 0, value)=>sum + value);
63
+ const uploadedSize = Math.min(uploaded, this.file.size);
64
+ if (this.onProgressFn) try {
65
+ this.onProgressFn({
66
+ sent: uploadedSize,
67
+ total: this.file.size,
68
+ percentage: Math.round(uploadedSize / this.file.size * 100)
69
+ });
70
+ } catch (err) {
71
+ console.error('Error executing the "onProgress" callback', err);
72
+ }
92
73
  }
93
- const part = this.upload.parts.shift();
94
- if (!part) {
95
- return;
74
+ async uploadNextPart() {
75
+ if (!this.upload) return;
76
+ const part = this.upload.parts.shift();
77
+ if (!part) return;
78
+ return executeWithRetry(()=>this.uploadPart(part)).then(()=>this.uploadNextPart());
96
79
  }
97
- return executeWithRetry(() => this.uploadPart(part)).then(() => this.uploadNextPart());
98
- }
99
- uploadPart(part) {
100
- this.assertIsDefined(this.upload, `Upload must be created before calling "sendCompleteRequest"!`);
101
- this.assertIsDefined(this.file, `File must be set before calling "uploadPart"!`);
102
- const sentSize = (part.partNumber - 1) * this.chunkSize;
103
- const nextChunkSize = Math.min(sentSize + this.chunkSize, this.file.size);
104
- const chunk = this.file.slice(sentSize, nextChunkSize, this.upload.file.type);
105
- console.log(`Chunk for part #${part.partNumber}`, chunk.size);
106
- return new Promise((resolve, reject) => {
107
- const throwXHRError = error => {
108
- this.activeConnections.delete(part.partNumber);
109
- reject(error);
110
- };
111
- if (!window.navigator.onLine) {
112
- return reject(new Error("Browser is offline!"));
113
- }
114
- const xhr = new XMLHttpRequest();
115
- this.activeConnections.set(part.partNumber, xhr);
116
- const abortXHR = () => xhr.abort();
117
- xhr.upload.addEventListener("progress", event => this.progressListener(part, event));
118
- window.addEventListener("offline", abortXHR);
119
- const removeListeners = () => {
120
- window.removeEventListener("offline", abortXHR);
121
- };
122
- xhr.open("PUT", part.url);
123
- xhr.onreadystatechange = () => {
124
- if (xhr.readyState === 4 && xhr.status === 200) {
125
- try {
126
- this.activeConnections.delete(part.partNumber);
127
- window.removeEventListener("offline", abortXHR);
128
- resolve(xhr.status);
129
- } catch (err) {
130
- console.error(`Error in "onreadystatechange"`, err);
131
- }
132
- }
133
- };
134
- xhr.onerror = () => {
135
- removeListeners();
136
- throwXHRError(new Error(`Failed to upload file part #${part.partNumber}`));
137
- };
138
- xhr.ontimeout = () => {
139
- removeListeners();
140
- throwXHRError(new Error(`Request timed out for file part #${part.partNumber}!`));
141
- };
142
- xhr.onabort = () => {
143
- removeListeners();
144
- throwXHRError(new Error(`Upload was cancelled for part #${part.partNumber}!`));
145
- };
146
- xhr.send(chunk);
147
- });
148
- }
149
- assertIsDefined(upload, message) {
150
- if (!upload) {
151
- throw new Error(message);
80
+ uploadPart(part) {
81
+ this.assertIsDefined(this.upload, 'Upload must be created before calling "sendCompleteRequest"!');
82
+ this.assertIsDefined(this.file, 'File must be set before calling "uploadPart"!');
83
+ const sentSize = (part.partNumber - 1) * this.chunkSize;
84
+ const nextChunkSize = Math.min(sentSize + this.chunkSize, this.file.size);
85
+ const chunk = this.file.slice(sentSize, nextChunkSize, this.upload.file.type);
86
+ console.log(`Chunk for part #${part.partNumber}`, chunk.size);
87
+ return new Promise((resolve, reject)=>{
88
+ const throwXHRError = (error)=>{
89
+ this.activeConnections.delete(part.partNumber);
90
+ reject(error);
91
+ };
92
+ if (!window.navigator.onLine) return reject(new Error("Browser is offline!"));
93
+ const xhr = new XMLHttpRequest();
94
+ this.activeConnections.set(part.partNumber, xhr);
95
+ const abortXHR = ()=>xhr.abort();
96
+ xhr.upload.addEventListener("progress", (event)=>this.progressListener(part, event));
97
+ window.addEventListener("offline", abortXHR);
98
+ const removeListeners = ()=>{
99
+ window.removeEventListener("offline", abortXHR);
100
+ };
101
+ xhr.open("PUT", part.url);
102
+ xhr.onreadystatechange = ()=>{
103
+ if (4 === xhr.readyState && 200 === xhr.status) try {
104
+ this.activeConnections.delete(part.partNumber);
105
+ window.removeEventListener("offline", abortXHR);
106
+ resolve(xhr.status);
107
+ } catch (err) {
108
+ console.error('Error in "onreadystatechange"', err);
109
+ }
110
+ };
111
+ xhr.onerror = ()=>{
112
+ removeListeners();
113
+ throwXHRError(new Error(`Failed to upload file part #${part.partNumber}`));
114
+ };
115
+ xhr.ontimeout = ()=>{
116
+ removeListeners();
117
+ throwXHRError(new Error(`Request timed out for file part #${part.partNumber}!`));
118
+ };
119
+ xhr.onabort = ()=>{
120
+ removeListeners();
121
+ throwXHRError(new Error(`Upload was cancelled for part #${part.partNumber}!`));
122
+ };
123
+ xhr.send(chunk);
124
+ });
125
+ }
126
+ assertIsDefined(upload, message) {
127
+ if (!upload) throw new Error(message);
152
128
  }
153
- }
154
129
  }
155
- const executeWithRetry = (execute, options) => {
156
- return pRetry(execute, {
157
- maxRetryTime: 300000,
158
- retries: 5,
159
- minTimeout: 1500,
160
- maxTimeout: 30000,
161
- ...options
162
- });
163
- };
130
+ const executeWithRetry = (execute, options)=>p_retry(execute, {
131
+ maxRetryTime: 300000,
132
+ retries: 5,
133
+ minTimeout: 1500,
134
+ maxTimeout: 30000,
135
+ ...options
136
+ });
137
+ export { MultiPartUploader };
164
138
 
165
139
  //# sourceMappingURL=MultiPartUploader.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["pRetry","MultiPartUploader","activeConnections","Map","progressTracker","onErrorFn","error","console","constructor","api","options","chunkSize","parallelUploads","Math","max","min","uploadFile","file","numberOfParts","ceil","size","upload","createUpload","data","name","type","threads","Promise","all","Array","from","length","map","uploadNextPart","complete","onProgress","onProgressFn","onError","sendCompleteRequest","assertIsDefined","completeUpload","fileKey","key","uploadId","progressListener","part","event","set","partNumber","loaded","uploaded","values","reduce","sum","value","uploadedSize","sent","total","percentage","round","err","parts","shift","executeWithRetry","uploadPart","then","sentSize","nextChunkSize","chunk","slice","log","resolve","reject","throwXHRError","delete","window","navigator","onLine","Error","xhr","XMLHttpRequest","abortXHR","abort","addEventListener","removeListeners","removeEventListener","open","url","onreadystatechange","readyState","status","onerror","ontimeout","onabort","send","message","execute","maxRetryTime","retries","minTimeout","maxTimeout"],"sources":["MultiPartUploader.ts"],"sourcesContent":["import pRetry from \"p-retry\";\nimport type { MultiPartUpload, MultiPartUploadAPI, FilePart } from \"./MultiPartUploadAPI.js\";\n\ninterface MultiPartUploaderOptions {\n /**\n * Chunk size in MB. Must be >=5MB (enforced by AWS).\n */\n chunkSize?: number;\n /**\n * Number of parallel uploads. Must be >=5 && <=15.\n */\n parallelUploads?: number;\n}\n\ninterface OnProgressCallback {\n (params: { sent: number; total: number; percentage: number }): void;\n}\n\ninterface OnErrorCallback {\n (error: Error): void;\n}\n\nexport class MultiPartUploader {\n private readonly api: MultiPartUploadAPI;\n private readonly chunkSize: number;\n private readonly parallelUploads: number;\n private readonly activeConnections: Map<number, XMLHttpRequest> = new Map();\n private readonly progressTracker: Map<number, number> = new Map();\n private upload: MultiPartUpload | undefined;\n private file: File | undefined;\n private onErrorFn: OnErrorCallback = error => console.error(error);\n private onProgressFn: OnProgressCallback | undefined;\n\n constructor(api: MultiPartUploadAPI, options: MultiPartUploaderOptions = {}) {\n this.api = api;\n const chunkSize = options.chunkSize || 50;\n const parallelUploads = options.parallelUploads || 5;\n\n this.chunkSize = Math.max(1024 * 1024 * chunkSize, 1024 * 1024 * 5);\n this.parallelUploads = Math.min(parallelUploads, 15);\n }\n\n async uploadFile(file: File) {\n this.file = file;\n const numberOfParts = Math.ceil(file.size / this.chunkSize);\n\n try {\n /**\n * Initialize the file upload on AWS S3.\n */\n this.upload = await this.api.createUpload({\n data: { name: file.name, size: file.size, type: file.type },\n numberOfParts\n });\n\n /**\n * Run the defined number of parallel uploads. Each thread will continue to process parts\n * for as long as there are parts to upload. The promise will resolve once there's no more parts to upload.\n */\n const threads = Math.min(numberOfParts, this.parallelUploads);\n await Promise.all(Array.from({ length: threads }).map(() => this.uploadNextPart()));\n\n await this.complete();\n\n return this.upload.file;\n } catch (error) {\n await this.complete(error);\n throw error;\n }\n }\n\n onProgress(onProgress: OnProgressCallback) {\n this.onProgressFn = onProgress;\n return this;\n }\n\n onError(onError: OnErrorCallback) {\n this.onErrorFn = onError;\n return this;\n }\n\n private async complete(error?: Error) {\n if (error) {\n this.onErrorFn(error);\n return;\n }\n\n try {\n await this.sendCompleteRequest();\n } catch (error) {\n this.onErrorFn(error);\n }\n }\n\n private async sendCompleteRequest() {\n this.assertIsDefined(\n this.upload,\n `Upload must be created before calling \"sendCompleteRequest\"!`\n );\n\n return this.api.completeUpload({\n fileKey: this.upload.file.key,\n uploadId: this.upload.uploadId\n });\n }\n\n private progressListener(part: FilePart, event: ProgressEvent<XMLHttpRequestEventTarget>) {\n if (!this.file) {\n return;\n }\n\n this.progressTracker.set(part.partNumber, event.loaded);\n\n const uploaded = Array.from(this.progressTracker.values()).reduce(\n (sum = 0, value) => sum + value\n );\n\n const uploadedSize = Math.min(uploaded, this.file.size);\n\n if (this.onProgressFn) {\n try {\n this.onProgressFn({\n sent: uploadedSize,\n total: this.file.size,\n percentage: Math.round((uploadedSize / this.file.size) * 100)\n });\n } catch (err) {\n console.error(`Error executing the \"onProgress\" callback`, err);\n }\n }\n }\n\n private async uploadNextPart(): Promise<void> {\n if (!this.upload) {\n return;\n }\n\n const part = this.upload.parts.shift();\n\n if (!part) {\n return;\n }\n\n return executeWithRetry(() => this.uploadPart(part)).then(() => this.uploadNextPart());\n }\n\n private uploadPart(part: FilePart) {\n this.assertIsDefined(\n this.upload,\n `Upload must be created before calling \"sendCompleteRequest\"!`\n );\n\n this.assertIsDefined(this.file, `File must be set before calling \"uploadPart\"!`);\n\n const sentSize = (part.partNumber - 1) * this.chunkSize;\n const nextChunkSize = Math.min(sentSize + this.chunkSize, this.file.size);\n const chunk = this.file.slice(sentSize, nextChunkSize, this.upload.file.type);\n console.log(`Chunk for part #${part.partNumber}`, chunk.size);\n\n return new Promise((resolve, reject) => {\n const throwXHRError = (error: Error) => {\n this.activeConnections.delete(part.partNumber);\n reject(error);\n };\n\n if (!window.navigator.onLine) {\n return reject(new Error(\"Browser is offline!\"));\n }\n\n const xhr = new XMLHttpRequest();\n this.activeConnections.set(part.partNumber, xhr);\n const abortXHR = () => xhr.abort();\n\n xhr.upload.addEventListener(\"progress\", event => this.progressListener(part, event));\n\n window.addEventListener(\"offline\", abortXHR);\n const removeListeners = () => {\n window.removeEventListener(\"offline\", abortXHR);\n };\n\n xhr.open(\"PUT\", part.url);\n\n xhr.onreadystatechange = () => {\n if (xhr.readyState === 4 && xhr.status === 200) {\n try {\n this.activeConnections.delete(part.partNumber);\n window.removeEventListener(\"offline\", abortXHR);\n resolve(xhr.status);\n } catch (err) {\n console.error(`Error in \"onreadystatechange\"`, err);\n }\n }\n };\n\n xhr.onerror = () => {\n removeListeners();\n throwXHRError(new Error(`Failed to upload file part #${part.partNumber}`));\n };\n xhr.ontimeout = () => {\n removeListeners();\n throwXHRError(new Error(`Request timed out for file part #${part.partNumber}!`));\n };\n xhr.onabort = () => {\n removeListeners();\n throwXHRError(new Error(`Upload was cancelled for part #${part.partNumber}!`));\n };\n xhr.send(chunk);\n });\n }\n\n private assertIsDefined<T>(upload: T, message: string): asserts upload is NonNullable<T> {\n if (!upload) {\n throw new Error(message);\n }\n }\n}\n\nconst executeWithRetry = (execute: () => void, options?: Parameters<typeof pRetry>[1]) => {\n return pRetry(execute, {\n maxRetryTime: 300000,\n retries: 5,\n minTimeout: 1500,\n maxTimeout: 30000,\n ...options\n });\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"MultiPartUploader.js","sources":["../src/MultiPartUploader.ts"],"sourcesContent":["import pRetry from \"p-retry\";\nimport type { MultiPartUpload, MultiPartUploadAPI, FilePart } from \"./MultiPartUploadAPI.js\";\n\ninterface MultiPartUploaderOptions {\n /**\n * Chunk size in MB. Must be >=5MB (enforced by AWS).\n */\n chunkSize?: number;\n /**\n * Number of parallel uploads. Must be >=5 && <=15.\n */\n parallelUploads?: number;\n}\n\ninterface OnProgressCallback {\n (params: { sent: number; total: number; percentage: number }): void;\n}\n\ninterface OnErrorCallback {\n (error: Error): void;\n}\n\nexport class MultiPartUploader {\n private readonly api: MultiPartUploadAPI;\n private readonly chunkSize: number;\n private readonly parallelUploads: number;\n private readonly activeConnections: Map<number, XMLHttpRequest> = new Map();\n private readonly progressTracker: Map<number, number> = new Map();\n private upload: MultiPartUpload | undefined;\n private file: File | undefined;\n private onErrorFn: OnErrorCallback = error => console.error(error);\n private onProgressFn: OnProgressCallback | undefined;\n\n constructor(api: MultiPartUploadAPI, options: MultiPartUploaderOptions = {}) {\n this.api = api;\n const chunkSize = options.chunkSize || 50;\n const parallelUploads = options.parallelUploads || 5;\n\n this.chunkSize = Math.max(1024 * 1024 * chunkSize, 1024 * 1024 * 5);\n this.parallelUploads = Math.min(parallelUploads, 15);\n }\n\n async uploadFile(file: File) {\n this.file = file;\n const numberOfParts = Math.ceil(file.size / this.chunkSize);\n\n try {\n /**\n * Initialize the file upload on AWS S3.\n */\n this.upload = await this.api.createUpload({\n data: { name: file.name, size: file.size, type: file.type },\n numberOfParts\n });\n\n /**\n * Run the defined number of parallel uploads. Each thread will continue to process parts\n * for as long as there are parts to upload. The promise will resolve once there's no more parts to upload.\n */\n const threads = Math.min(numberOfParts, this.parallelUploads);\n await Promise.all(Array.from({ length: threads }).map(() => this.uploadNextPart()));\n\n await this.complete();\n\n return this.upload.file;\n } catch (error) {\n await this.complete(error);\n throw error;\n }\n }\n\n onProgress(onProgress: OnProgressCallback) {\n this.onProgressFn = onProgress;\n return this;\n }\n\n onError(onError: OnErrorCallback) {\n this.onErrorFn = onError;\n return this;\n }\n\n private async complete(error?: Error) {\n if (error) {\n this.onErrorFn(error);\n return;\n }\n\n try {\n await this.sendCompleteRequest();\n } catch (error) {\n this.onErrorFn(error);\n }\n }\n\n private async sendCompleteRequest() {\n this.assertIsDefined(\n this.upload,\n `Upload must be created before calling \"sendCompleteRequest\"!`\n );\n\n return this.api.completeUpload({\n fileKey: this.upload.file.key,\n uploadId: this.upload.uploadId\n });\n }\n\n private progressListener(part: FilePart, event: ProgressEvent<XMLHttpRequestEventTarget>) {\n if (!this.file) {\n return;\n }\n\n this.progressTracker.set(part.partNumber, event.loaded);\n\n const uploaded = Array.from(this.progressTracker.values()).reduce(\n (sum = 0, value) => sum + value\n );\n\n const uploadedSize = Math.min(uploaded, this.file.size);\n\n if (this.onProgressFn) {\n try {\n this.onProgressFn({\n sent: uploadedSize,\n total: this.file.size,\n percentage: Math.round((uploadedSize / this.file.size) * 100)\n });\n } catch (err) {\n console.error(`Error executing the \"onProgress\" callback`, err);\n }\n }\n }\n\n private async uploadNextPart(): Promise<void> {\n if (!this.upload) {\n return;\n }\n\n const part = this.upload.parts.shift();\n\n if (!part) {\n return;\n }\n\n return executeWithRetry(() => this.uploadPart(part)).then(() => this.uploadNextPart());\n }\n\n private uploadPart(part: FilePart) {\n this.assertIsDefined(\n this.upload,\n `Upload must be created before calling \"sendCompleteRequest\"!`\n );\n\n this.assertIsDefined(this.file, `File must be set before calling \"uploadPart\"!`);\n\n const sentSize = (part.partNumber - 1) * this.chunkSize;\n const nextChunkSize = Math.min(sentSize + this.chunkSize, this.file.size);\n const chunk = this.file.slice(sentSize, nextChunkSize, this.upload.file.type);\n console.log(`Chunk for part #${part.partNumber}`, chunk.size);\n\n return new Promise((resolve, reject) => {\n const throwXHRError = (error: Error) => {\n this.activeConnections.delete(part.partNumber);\n reject(error);\n };\n\n if (!window.navigator.onLine) {\n return reject(new Error(\"Browser is offline!\"));\n }\n\n const xhr = new XMLHttpRequest();\n this.activeConnections.set(part.partNumber, xhr);\n const abortXHR = () => xhr.abort();\n\n xhr.upload.addEventListener(\"progress\", event => this.progressListener(part, event));\n\n window.addEventListener(\"offline\", abortXHR);\n const removeListeners = () => {\n window.removeEventListener(\"offline\", abortXHR);\n };\n\n xhr.open(\"PUT\", part.url);\n\n xhr.onreadystatechange = () => {\n if (xhr.readyState === 4 && xhr.status === 200) {\n try {\n this.activeConnections.delete(part.partNumber);\n window.removeEventListener(\"offline\", abortXHR);\n resolve(xhr.status);\n } catch (err) {\n console.error(`Error in \"onreadystatechange\"`, err);\n }\n }\n };\n\n xhr.onerror = () => {\n removeListeners();\n throwXHRError(new Error(`Failed to upload file part #${part.partNumber}`));\n };\n xhr.ontimeout = () => {\n removeListeners();\n throwXHRError(new Error(`Request timed out for file part #${part.partNumber}!`));\n };\n xhr.onabort = () => {\n removeListeners();\n throwXHRError(new Error(`Upload was cancelled for part #${part.partNumber}!`));\n };\n xhr.send(chunk);\n });\n }\n\n private assertIsDefined<T>(upload: T, message: string): asserts upload is NonNullable<T> {\n if (!upload) {\n throw new Error(message);\n }\n }\n}\n\nconst executeWithRetry = (execute: () => void, options?: Parameters<typeof pRetry>[1]) => {\n return pRetry(execute, {\n maxRetryTime: 300000,\n retries: 5,\n minTimeout: 1500,\n maxTimeout: 30000,\n ...options\n });\n};\n"],"names":["MultiPartUploader","api","options","Map","error","console","chunkSize","parallelUploads","Math","file","numberOfParts","threads","Promise","Array","onProgress","onError","part","event","uploaded","sum","value","uploadedSize","err","executeWithRetry","sentSize","nextChunkSize","chunk","resolve","reject","throwXHRError","window","Error","xhr","XMLHttpRequest","abortXHR","removeListeners","upload","message","execute","pRetry"],"mappings":"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"}
@@ -1,59 +1,47 @@
1
1
  import { GET_PRE_SIGNED_POST_PAYLOAD } from "./graphql.js";
2
- export class SimpleUploadStrategy {
3
- async upload(file, {
4
- apolloClient,
5
- onProgress
6
- }) {
7
- // 1. GET PreSignedPostPayload
8
- const response = await apolloClient.query({
9
- query: GET_PRE_SIGNED_POST_PAYLOAD,
10
- fetchPolicy: "no-cache",
11
- variables: {
12
- data: {
13
- size: file.size,
14
- name: file.name,
15
- type: file.type,
16
- key: file.key,
17
- keyPrefix: file.keyPrefix
2
+ class SimpleUploadStrategy {
3
+ async upload(file, { apolloClient, onProgress }) {
4
+ const response = await apolloClient.query({
5
+ query: GET_PRE_SIGNED_POST_PAYLOAD,
6
+ fetchPolicy: "no-cache",
7
+ variables: {
8
+ data: {
9
+ size: file.size,
10
+ name: file.name,
11
+ type: file.type,
12
+ key: file.key,
13
+ keyPrefix: file.keyPrefix
14
+ }
15
+ }
16
+ });
17
+ const { getPreSignedPostPayload } = response.data.fileManager;
18
+ if (getPreSignedPostPayload.error) {
19
+ console.error(getPreSignedPostPayload);
20
+ throw Error(getPreSignedPostPayload.error);
18
21
  }
19
- }
20
- });
21
- const {
22
- getPreSignedPostPayload
23
- } = response.data.fileManager;
24
- if (getPreSignedPostPayload.error) {
25
- console.error(getPreSignedPostPayload);
26
- throw Error(getPreSignedPostPayload.error);
22
+ return new Promise((resolve, reject)=>{
23
+ const formData = new window.FormData();
24
+ Object.keys(getPreSignedPostPayload.data.data.fields).forEach((key)=>{
25
+ formData.append(key, getPreSignedPostPayload.data.data.fields[key]);
26
+ });
27
+ formData.append("file", file);
28
+ const xhr = new window.XMLHttpRequest();
29
+ xhr.upload.addEventListener("progress", (event)=>{
30
+ if (onProgress) onProgress({
31
+ sent: event.loaded,
32
+ total: file.size,
33
+ percentage: event.loaded / file.size * 100
34
+ });
35
+ }, false);
36
+ xhr.open("POST", getPreSignedPostPayload.data.data.url, true);
37
+ xhr.send(formData);
38
+ xhr.onload = function() {
39
+ if (204 === this.status) return void resolve(getPreSignedPostPayload.data.file);
40
+ reject(this.responseText);
41
+ };
42
+ });
27
43
  }
28
-
29
- // 2. upload file to S3
30
- return new Promise((resolve, reject) => {
31
- const formData = new window.FormData();
32
- Object.keys(getPreSignedPostPayload.data.data.fields).forEach(key => {
33
- formData.append(key, getPreSignedPostPayload.data.data.fields[key]);
34
- });
35
- formData.append("file", file);
36
- const xhr = new window.XMLHttpRequest();
37
- xhr.upload.addEventListener("progress", event => {
38
- if (onProgress) {
39
- onProgress({
40
- sent: event.loaded,
41
- total: file.size,
42
- percentage: event.loaded / file.size * 100
43
- });
44
- }
45
- }, false);
46
- xhr.open("POST", getPreSignedPostPayload.data.data.url, true);
47
- xhr.send(formData);
48
- xhr.onload = function () {
49
- if (this.status === 204) {
50
- resolve(getPreSignedPostPayload.data.file);
51
- return;
52
- }
53
- reject(this.responseText);
54
- };
55
- });
56
- }
57
44
  }
45
+ export { SimpleUploadStrategy };
58
46
 
59
47
  //# sourceMappingURL=SimpleUploadStrategy.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["GET_PRE_SIGNED_POST_PAYLOAD","SimpleUploadStrategy","upload","file","apolloClient","onProgress","response","query","fetchPolicy","variables","data","size","name","type","key","keyPrefix","getPreSignedPostPayload","fileManager","error","console","Error","Promise","resolve","reject","formData","window","FormData","Object","keys","fields","forEach","append","xhr","XMLHttpRequest","addEventListener","event","sent","loaded","total","percentage","open","url","send","onload","status","responseText"],"sources":["SimpleUploadStrategy.ts"],"sourcesContent":["import type { UploadedFile, UploadOptions } from \"@webiny/app/types.js\";\nimport { GET_PRE_SIGNED_POST_PAYLOAD } from \"./graphql.js\";\nimport type { FileUploadStrategy } from \"~/index.js\";\n\ndeclare global {\n interface File {\n key?: string;\n keyPrefix?: string;\n }\n}\n\nexport class SimpleUploadStrategy implements FileUploadStrategy {\n async upload(file: File, { apolloClient, onProgress }: UploadOptions): Promise<UploadedFile> {\n // 1. GET PreSignedPostPayload\n const response = await apolloClient.query({\n query: GET_PRE_SIGNED_POST_PAYLOAD,\n fetchPolicy: \"no-cache\",\n variables: {\n data: {\n size: file.size,\n name: file.name,\n type: file.type,\n key: file.key,\n keyPrefix: file.keyPrefix\n }\n }\n });\n\n const { getPreSignedPostPayload } = response.data.fileManager;\n if (getPreSignedPostPayload.error) {\n console.error(getPreSignedPostPayload);\n throw Error(getPreSignedPostPayload.error);\n }\n\n // 2. upload file to S3\n return new Promise((resolve, reject) => {\n const formData = new window.FormData();\n Object.keys(getPreSignedPostPayload.data.data.fields).forEach(key => {\n formData.append(key, getPreSignedPostPayload.data.data.fields[key]);\n });\n\n formData.append(\"file\", file);\n\n const xhr = new window.XMLHttpRequest();\n xhr.upload.addEventListener(\n \"progress\",\n event => {\n if (onProgress) {\n onProgress({\n sent: event.loaded,\n total: file.size,\n percentage: (event.loaded / file.size) * 100\n });\n }\n },\n false\n );\n xhr.open(\"POST\", getPreSignedPostPayload.data.data.url, true);\n xhr.send(formData);\n xhr.onload = function () {\n if (this.status === 204) {\n resolve(getPreSignedPostPayload.data.file);\n return;\n }\n\n reject(this.responseText);\n };\n });\n }\n}\n"],"mappings":"AACA,SAASA,2BAA2B;AAUpC,OAAO,MAAMC,oBAAoB,CAA+B;EAC5D,MAAMC,MAAMA,CAACC,IAAU,EAAE;IAAEC,YAAY;IAAEC;EAA0B,CAAC,EAAyB;IACzF;IACA,MAAMC,QAAQ,GAAG,MAAMF,YAAY,CAACG,KAAK,CAAC;MACtCA,KAAK,EAAEP,2BAA2B;MAClCQ,WAAW,EAAE,UAAU;MACvBC,SAAS,EAAE;QACPC,IAAI,EAAE;UACFC,IAAI,EAAER,IAAI,CAACQ,IAAI;UACfC,IAAI,EAAET,IAAI,CAACS,IAAI;UACfC,IAAI,EAAEV,IAAI,CAACU,IAAI;UACfC,GAAG,EAAEX,IAAI,CAACW,GAAG;UACbC,SAAS,EAAEZ,IAAI,CAACY;QACpB;MACJ;IACJ,CAAC,CAAC;IAEF,MAAM;MAAEC;IAAwB,CAAC,GAAGV,QAAQ,CAACI,IAAI,CAACO,WAAW;IAC7D,IAAID,uBAAuB,CAACE,KAAK,EAAE;MAC/BC,OAAO,CAACD,KAAK,CAACF,uBAAuB,CAAC;MACtC,MAAMI,KAAK,CAACJ,uBAAuB,CAACE,KAAK,CAAC;IAC9C;;IAEA;IACA,OAAO,IAAIG,OAAO,CAAC,CAACC,OAAO,EAAEC,MAAM,KAAK;MACpC,MAAMC,QAAQ,GAAG,IAAIC,MAAM,CAACC,QAAQ,CAAC,CAAC;MACtCC,MAAM,CAACC,IAAI,CAACZ,uBAAuB,CAACN,IAAI,CAACA,IAAI,CAACmB,MAAM,CAAC,CAACC,OAAO,CAAChB,GAAG,IAAI;QACjEU,QAAQ,CAACO,MAAM,CAACjB,GAAG,EAAEE,uBAAuB,CAACN,IAAI,CAACA,IAAI,CAACmB,MAAM,CAACf,GAAG,CAAC,CAAC;MACvE,CAAC,CAAC;MAEFU,QAAQ,CAACO,MAAM,CAAC,MAAM,EAAE5B,IAAI,CAAC;MAE7B,MAAM6B,GAAG,GAAG,IAAIP,MAAM,CAACQ,cAAc,CAAC,CAAC;MACvCD,GAAG,CAAC9B,MAAM,CAACgC,gBAAgB,CACvB,UAAU,EACVC,KAAK,IAAI;QACL,IAAI9B,UAAU,EAAE;UACZA,UAAU,CAAC;YACP+B,IAAI,EAAED,KAAK,CAACE,MAAM;YAClBC,KAAK,EAAEnC,IAAI,CAACQ,IAAI;YAChB4B,UAAU,EAAGJ,KAAK,CAACE,MAAM,GAAGlC,IAAI,CAACQ,IAAI,GAAI;UAC7C,CAAC,CAAC;QACN;MACJ,CAAC,EACD,KACJ,CAAC;MACDqB,GAAG,CAACQ,IAAI,CAAC,MAAM,EAAExB,uBAAuB,CAACN,IAAI,CAACA,IAAI,CAAC+B,GAAG,EAAE,IAAI,CAAC;MAC7DT,GAAG,CAACU,IAAI,CAAClB,QAAQ,CAAC;MAClBQ,GAAG,CAACW,MAAM,GAAG,YAAY;QACrB,IAAI,IAAI,CAACC,MAAM,KAAK,GAAG,EAAE;UACrBtB,OAAO,CAACN,uBAAuB,CAACN,IAAI,CAACP,IAAI,CAAC;UAC1C;QACJ;QAEAoB,MAAM,CAAC,IAAI,CAACsB,YAAY,CAAC;MAC7B,CAAC;IACL,CAAC,CAAC;EACN;AACJ","ignoreList":[]}
1
+ {"version":3,"file":"SimpleUploadStrategy.js","sources":["../src/SimpleUploadStrategy.ts"],"sourcesContent":["import type { UploadedFile, UploadOptions } from \"@webiny/app/types.js\";\nimport { GET_PRE_SIGNED_POST_PAYLOAD } from \"./graphql.js\";\nimport type { FileUploadStrategy } from \"~/index.js\";\n\ndeclare global {\n interface File {\n key?: string;\n keyPrefix?: string;\n }\n}\n\nexport class SimpleUploadStrategy implements FileUploadStrategy {\n async upload(file: File, { apolloClient, onProgress }: UploadOptions): Promise<UploadedFile> {\n // 1. GET PreSignedPostPayload\n const response = await apolloClient.query({\n query: GET_PRE_SIGNED_POST_PAYLOAD,\n fetchPolicy: \"no-cache\",\n variables: {\n data: {\n size: file.size,\n name: file.name,\n type: file.type,\n key: file.key,\n keyPrefix: file.keyPrefix\n }\n }\n });\n\n const { getPreSignedPostPayload } = response.data.fileManager;\n if (getPreSignedPostPayload.error) {\n console.error(getPreSignedPostPayload);\n throw Error(getPreSignedPostPayload.error);\n }\n\n // 2. upload file to S3\n return new Promise((resolve, reject) => {\n const formData = new window.FormData();\n Object.keys(getPreSignedPostPayload.data.data.fields).forEach(key => {\n formData.append(key, getPreSignedPostPayload.data.data.fields[key]);\n });\n\n formData.append(\"file\", file);\n\n const xhr = new window.XMLHttpRequest();\n xhr.upload.addEventListener(\n \"progress\",\n event => {\n if (onProgress) {\n onProgress({\n sent: event.loaded,\n total: file.size,\n percentage: (event.loaded / file.size) * 100\n });\n }\n },\n false\n );\n xhr.open(\"POST\", getPreSignedPostPayload.data.data.url, true);\n xhr.send(formData);\n xhr.onload = function () {\n if (this.status === 204) {\n resolve(getPreSignedPostPayload.data.file);\n return;\n }\n\n reject(this.responseText);\n };\n });\n }\n}\n"],"names":["SimpleUploadStrategy","file","apolloClient","onProgress","response","GET_PRE_SIGNED_POST_PAYLOAD","getPreSignedPostPayload","console","Error","Promise","resolve","reject","formData","window","Object","key","xhr","event"],"mappings":";AAWO,MAAMA;IACT,MAAM,OAAOC,IAAU,EAAE,EAAEC,YAAY,EAAEC,UAAU,EAAiB,EAAyB;QAEzF,MAAMC,WAAW,MAAMF,aAAa,KAAK,CAAC;YACtC,OAAOG;YACP,aAAa;YACb,WAAW;gBACP,MAAM;oBACF,MAAMJ,KAAK,IAAI;oBACf,MAAMA,KAAK,IAAI;oBACf,MAAMA,KAAK,IAAI;oBACf,KAAKA,KAAK,GAAG;oBACb,WAAWA,KAAK,SAAS;gBAC7B;YACJ;QACJ;QAEA,MAAM,EAAEK,uBAAuB,EAAE,GAAGF,SAAS,IAAI,CAAC,WAAW;QAC7D,IAAIE,wBAAwB,KAAK,EAAE;YAC/BC,QAAQ,KAAK,CAACD;YACd,MAAME,MAAMF,wBAAwB,KAAK;QAC7C;QAGA,OAAO,IAAIG,QAAQ,CAACC,SAASC;YACzB,MAAMC,WAAW,IAAIC,OAAO,QAAQ;YACpCC,OAAO,IAAI,CAACR,wBAAwB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAACS,CAAAA;gBAC1DH,SAAS,MAAM,CAACG,KAAKT,wBAAwB,IAAI,CAAC,IAAI,CAAC,MAAM,CAACS,IAAI;YACtE;YAEAH,SAAS,MAAM,CAAC,QAAQX;YAExB,MAAMe,MAAM,IAAIH,OAAO,cAAc;YACrCG,IAAI,MAAM,CAAC,gBAAgB,CACvB,YACAC,CAAAA;gBACI,IAAId,YACAA,WAAW;oBACP,MAAMc,MAAM,MAAM;oBAClB,OAAOhB,KAAK,IAAI;oBAChB,YAAagB,MAAM,MAAM,GAAGhB,KAAK,IAAI,GAAI;gBAC7C;YAER,GACA;YAEJe,IAAI,IAAI,CAAC,QAAQV,wBAAwB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACxDU,IAAI,IAAI,CAACJ;YACTI,IAAI,MAAM,GAAG;gBACT,IAAI,AAAgB,QAAhB,IAAI,CAAC,MAAM,EAAU,YACrBN,QAAQJ,wBAAwB,IAAI,CAAC,IAAI;gBAI7CK,OAAO,IAAI,CAAC,YAAY;YAC5B;QACJ;IACJ;AACJ"}
package/graphql.js CHANGED
@@ -1,5 +1,5 @@
1
- import gql from "graphql-tag";
2
- export const GET_PRE_SIGNED_POST_PAYLOAD = gql`
1
+ import graphql_tag from "graphql-tag";
2
+ const GET_PRE_SIGNED_POST_PAYLOAD = graphql_tag`
3
3
  query getPreSignedPostPayload($data: PreSignedPostPayloadInput!) {
4
4
  fileManager {
5
5
  getPreSignedPostPayload(data: $data) {
@@ -20,5 +20,6 @@ export const GET_PRE_SIGNED_POST_PAYLOAD = gql`
20
20
  }
21
21
  }
22
22
  `;
23
+ export { GET_PRE_SIGNED_POST_PAYLOAD };
23
24
 
24
25
  //# sourceMappingURL=graphql.js.map
package/graphql.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["gql","GET_PRE_SIGNED_POST_PAYLOAD"],"sources":["graphql.ts"],"sourcesContent":["import gql from \"graphql-tag\";\n\nexport const GET_PRE_SIGNED_POST_PAYLOAD = gql`\n query getPreSignedPostPayload($data: PreSignedPostPayloadInput!) {\n fileManager {\n getPreSignedPostPayload(data: $data) {\n data {\n data\n file {\n id\n type\n name\n size\n key\n }\n }\n error {\n message\n }\n }\n }\n }\n`;\n"],"mappings":"AAAA,OAAOA,GAAG,MAAM,aAAa;AAE7B,OAAO,MAAMC,2BAA2B,GAAGD,GAAG;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"graphql.js","sources":["../src/graphql.ts"],"sourcesContent":["import gql from \"graphql-tag\";\n\nexport const GET_PRE_SIGNED_POST_PAYLOAD = gql`\n query getPreSignedPostPayload($data: PreSignedPostPayloadInput!) {\n fileManager {\n getPreSignedPostPayload(data: $data) {\n data {\n data\n file {\n id\n type\n name\n size\n key\n }\n }\n error {\n message\n }\n }\n }\n }\n`;\n"],"names":["GET_PRE_SIGNED_POST_PAYLOAD","gql"],"mappings":";AAEO,MAAMA,8BAA8BC,WAAG,CAAC;;;;;;;;;;;;;;;;;;;;AAoB/C,CAAC"}
package/index.js CHANGED
@@ -1,19 +1,20 @@
1
1
  import { SimpleUploadStrategy } from "./SimpleUploadStrategy.js";
2
2
  import { MultiPartUploadStrategy } from "./MultiPartUploadStrategy.js";
3
- export default () => {
4
- class S3FileUploader {
5
- type = "file-uploader";
6
- name = "file-uploader";
7
- upload(file, options) {
8
- // Use "simple" strategy for files smaller than ~100MB
9
- // @ts-expect-error
10
- const multiPartThreshold = window["fmUploadMultiPartThreshold"] ?? 100;
11
- const simple = file.size < multiPartThreshold * 1024 * 1024;
12
- const strategy = simple ? new SimpleUploadStrategy() : new MultiPartUploadStrategy();
13
- return strategy.upload(file, options);
3
+ const src = ()=>{
4
+ class S3FileUploader {
5
+ upload(file, options) {
6
+ const multiPartThreshold = window["fmUploadMultiPartThreshold"] ?? 100;
7
+ const simple = file.size < 1024 * multiPartThreshold * 1024;
8
+ const strategy = simple ? new SimpleUploadStrategy() : new MultiPartUploadStrategy();
9
+ return strategy.upload(file, options);
10
+ }
11
+ constructor(){
12
+ this.type = "file-uploader";
13
+ this.name = "file-uploader";
14
+ }
14
15
  }
15
- }
16
- return new S3FileUploader();
16
+ return new S3FileUploader();
17
17
  };
18
+ export default src;
18
19
 
19
20
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["SimpleUploadStrategy","MultiPartUploadStrategy","S3FileUploader","type","name","upload","file","options","multiPartThreshold","window","simple","size","strategy"],"sources":["index.ts"],"sourcesContent":["import type { FileUploaderPlugin, UploadOptions } from \"@webiny/app/types.js\";\nimport { SimpleUploadStrategy } from \"~/SimpleUploadStrategy.js\";\nimport { MultiPartUploadStrategy } from \"~/MultiPartUploadStrategy.js\";\n\nexport interface FileUploadStrategy {\n upload: FileUploaderPlugin[\"upload\"];\n}\n\nexport default (): FileUploaderPlugin => {\n class S3FileUploader implements FileUploaderPlugin {\n public readonly type = \"file-uploader\";\n public readonly name = \"file-uploader\";\n\n upload(file: File, options: UploadOptions) {\n // Use \"simple\" strategy for files smaller than ~100MB\n // @ts-expect-error\n const multiPartThreshold = window[\"fmUploadMultiPartThreshold\"] ?? 100;\n const simple = file.size < multiPartThreshold * 1024 * 1024;\n\n const strategy: FileUploadStrategy = simple\n ? new SimpleUploadStrategy()\n : new MultiPartUploadStrategy();\n\n return strategy.upload(file, options);\n }\n }\n\n return new S3FileUploader();\n};\n"],"mappings":"AACA,SAASA,oBAAoB;AAC7B,SAASC,uBAAuB;AAMhC,eAAe,MAA0B;EACrC,MAAMC,cAAc,CAA+B;IAC/BC,IAAI,GAAG,eAAe;IACtBC,IAAI,GAAG,eAAe;IAEtCC,MAAMA,CAACC,IAAU,EAAEC,OAAsB,EAAE;MACvC;MACA;MACA,MAAMC,kBAAkB,GAAGC,MAAM,CAAC,4BAA4B,CAAC,IAAI,GAAG;MACtE,MAAMC,MAAM,GAAGJ,IAAI,CAACK,IAAI,GAAGH,kBAAkB,GAAG,IAAI,GAAG,IAAI;MAE3D,MAAMI,QAA4B,GAAGF,MAAM,GACrC,IAAIV,oBAAoB,CAAC,CAAC,GAC1B,IAAIC,uBAAuB,CAAC,CAAC;MAEnC,OAAOW,QAAQ,CAACP,MAAM,CAACC,IAAI,EAAEC,OAAO,CAAC;IACzC;EACJ;EAEA,OAAO,IAAIL,cAAc,CAAC,CAAC;AAC/B,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import type { FileUploaderPlugin, UploadOptions } from \"@webiny/app/types.js\";\nimport { SimpleUploadStrategy } from \"~/SimpleUploadStrategy.js\";\nimport { MultiPartUploadStrategy } from \"~/MultiPartUploadStrategy.js\";\n\nexport interface FileUploadStrategy {\n upload: FileUploaderPlugin[\"upload\"];\n}\n\nexport default (): FileUploaderPlugin => {\n class S3FileUploader implements FileUploaderPlugin {\n public readonly type = \"file-uploader\";\n public readonly name = \"file-uploader\";\n\n upload(file: File, options: UploadOptions) {\n // Use \"simple\" strategy for files smaller than ~100MB\n // @ts-expect-error\n const multiPartThreshold = window[\"fmUploadMultiPartThreshold\"] ?? 100;\n const simple = file.size < multiPartThreshold * 1024 * 1024;\n\n const strategy: FileUploadStrategy = simple\n ? new SimpleUploadStrategy()\n : new MultiPartUploadStrategy();\n\n return strategy.upload(file, options);\n }\n }\n\n return new S3FileUploader();\n};\n"],"names":["S3FileUploader","file","options","multiPartThreshold","window","simple","strategy","SimpleUploadStrategy","MultiPartUploadStrategy"],"mappings":";;AAQA,YAAgB;IACZ,MAAMA;QAIF,OAAOC,IAAU,EAAEC,OAAsB,EAAE;YAGvC,MAAMC,qBAAqBC,MAAM,CAAC,6BAA6B,IAAI;YACnE,MAAMC,SAASJ,KAAK,IAAI,GAAGE,AAAqB,OAArBA,qBAA4B;YAEvD,MAAMG,WAA+BD,SAC/B,IAAIE,yBACJ,IAAIC;YAEV,OAAOF,SAAS,MAAM,CAACL,MAAMC;QACjC;;iBAdgB,IAAI,GAAG;iBACP,IAAI,GAAG;;IAc3B;IAEA,OAAO,IAAIF;AACf"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/app-file-manager-s3",
3
- "version": "6.3.0-beta.4",
3
+ "version": "6.4.0-beta.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -14,12 +14,12 @@
14
14
  "author": "Webiny Ltd",
15
15
  "license": "MIT",
16
16
  "dependencies": {
17
- "@webiny/app": "6.3.0-beta.4",
17
+ "@webiny/app": "6.4.0-beta.0",
18
18
  "graphql-tag": "2.12.6",
19
19
  "p-retry": "8.0.0"
20
20
  },
21
21
  "devDependencies": {
22
- "@webiny/build-tools": "6.3.0-beta.4",
22
+ "@webiny/build-tools": "6.4.0-beta.0",
23
23
  "rimraf": "6.1.3",
24
24
  "typescript": "6.0.3"
25
25
  },
@@ -27,5 +27,5 @@
27
27
  "access": "public",
28
28
  "directory": "dist"
29
29
  },
30
- "gitHead": "7cefe15431dbd65504e1f58147dc9e55bcbfa693"
30
+ "gitHead": "a545d7529828af07d08d49c3da1bcb967483b9ce"
31
31
  }
@@ -1 +0,0 @@
1
- {"version":3,"names":[],"sources":["MultiPartUploadAPI.ts"],"sourcesContent":["import type { UploadedFile } from \"@webiny/app/types.js\";\n\nexport interface CreateUploadParams {\n data: {\n size: number;\n name: string;\n type: string;\n };\n numberOfParts: number;\n}\n\nexport interface CompleteUploadParams {\n fileKey: string;\n uploadId: string;\n}\n\nexport interface FilePart {\n partNumber: number;\n url: string;\n}\n\nexport interface MultiPartUpload {\n file: UploadedFile;\n uploadId: string;\n parts: FilePart[];\n}\n\nexport interface MultiPartUploadAPI {\n createUpload(params: CreateUploadParams): Promise<MultiPartUpload>;\n completeUpload(params: CompleteUploadParams): Promise<boolean>;\n}\n"],"mappings":"","ignoreList":[]}