@capgo/capacitor-uploader 0.0.1 → 0.0.4
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 +30 -32
- package/android/src/main/java/ee/forgr/capacitor/uploader/Uploader.java +134 -99
- package/android/src/main/java/ee/forgr/capacitor/uploader/UploaderPlugin.java +108 -87
- package/dist/docs.json +74 -39
- package/dist/esm/definitions.d.ts +38 -17
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +4 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +5 -7
- package/dist/esm/web.js +84 -10
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +85 -13
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +86 -14
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/UploaderPlugin/Uploader.swift +8 -9
- package/ios/Sources/UploaderPlugin/UploaderPlugin.swift +6 -6
- package/package.json +39 -15
package/dist/plugin.cjs.js
CHANGED
|
@@ -1,27 +1,99 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var core = require('@capacitor/core');
|
|
6
4
|
|
|
7
|
-
const Uploader = core.registerPlugin(
|
|
8
|
-
web: () => Promise.resolve().then(function () { return web; }).then(m => new m.UploaderWeb()),
|
|
5
|
+
const Uploader = core.registerPlugin("Uploader", {
|
|
6
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.UploaderWeb()),
|
|
9
7
|
});
|
|
10
8
|
|
|
11
9
|
class UploaderWeb extends core.WebPlugin {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.uploads = new Map();
|
|
15
13
|
}
|
|
16
14
|
async startUpload(options) {
|
|
17
|
-
console.log(
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
console.log("startUpload", options);
|
|
16
|
+
const id = Math.random().toString(36).substring(2, 15);
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
const maxRetries = options.maxRetries || 3;
|
|
19
|
+
this.uploads.set(id, { controller, retries: maxRetries });
|
|
20
|
+
this.doUpload(id, options);
|
|
21
|
+
return { id };
|
|
20
22
|
}
|
|
21
23
|
async removeUpload(options) {
|
|
22
|
-
console.log(
|
|
23
|
-
this.
|
|
24
|
-
|
|
24
|
+
console.log("removeUpload", options);
|
|
25
|
+
const upload = this.uploads.get(options.id);
|
|
26
|
+
if (upload) {
|
|
27
|
+
upload.controller.abort();
|
|
28
|
+
this.uploads.delete(options.id);
|
|
29
|
+
this.notifyListeners("events", {
|
|
30
|
+
name: "cancelled",
|
|
31
|
+
id: options.id,
|
|
32
|
+
payload: {},
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async doUpload(id, options) {
|
|
37
|
+
const { filePath, serverUrl, headers = {}, method = "POST", parameters = {}, } = options;
|
|
38
|
+
const upload = this.uploads.get(id);
|
|
39
|
+
if (!upload)
|
|
40
|
+
return;
|
|
41
|
+
try {
|
|
42
|
+
const file = await this.getFileFromPath(filePath);
|
|
43
|
+
if (!file)
|
|
44
|
+
throw new Error("File not found");
|
|
45
|
+
const formData = new FormData();
|
|
46
|
+
formData.append("file", file);
|
|
47
|
+
for (const [key, value] of Object.entries(parameters)) {
|
|
48
|
+
formData.append(key, value);
|
|
49
|
+
}
|
|
50
|
+
const response = await fetch(serverUrl, {
|
|
51
|
+
method,
|
|
52
|
+
headers,
|
|
53
|
+
body: method === "PUT" ? file : formData,
|
|
54
|
+
signal: upload.controller.signal,
|
|
55
|
+
});
|
|
56
|
+
if (!response.ok)
|
|
57
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
58
|
+
this.notifyListeners("events", {
|
|
59
|
+
name: "completed",
|
|
60
|
+
id,
|
|
61
|
+
payload: { statusCode: response.status },
|
|
62
|
+
});
|
|
63
|
+
this.uploads.delete(id);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
if (error.name === "AbortError")
|
|
67
|
+
return;
|
|
68
|
+
if (upload.retries > 0) {
|
|
69
|
+
upload.retries--;
|
|
70
|
+
console.log(`Retrying upload (retries left: ${upload.retries})`);
|
|
71
|
+
setTimeout(() => this.doUpload(id, options), 1000);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
this.notifyListeners("events", {
|
|
75
|
+
name: "failed",
|
|
76
|
+
id,
|
|
77
|
+
payload: { error: error.message },
|
|
78
|
+
});
|
|
79
|
+
this.uploads.delete(id);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async getFileFromPath(filePath) {
|
|
84
|
+
// This is a simplified version. In a real-world scenario,
|
|
85
|
+
// you might need to handle different types of paths or use a file system API.
|
|
86
|
+
try {
|
|
87
|
+
const response = await fetch(filePath);
|
|
88
|
+
const blob = await response.blob();
|
|
89
|
+
return new File([blob], filePath.split("/").pop() || "file", {
|
|
90
|
+
type: blob.type,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.error("Error getting file:", error);
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
25
97
|
}
|
|
26
98
|
}
|
|
27
99
|
|
package/dist/plugin.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from \"@capacitor/core\";\nconst Uploader = registerPlugin(\"Uploader\", {\n web: () => import(\"./web\").then((m) => new m.UploaderWeb()),\n});\nexport * from \"./definitions\";\nexport { Uploader };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nexport class UploaderWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.uploads = new Map();\n }\n async startUpload(options) {\n console.log(\"startUpload\", options);\n const id = Math.random().toString(36).substring(2, 15);\n const controller = new AbortController();\n const maxRetries = options.maxRetries || 3;\n this.uploads.set(id, { controller, retries: maxRetries });\n this.doUpload(id, options);\n return { id };\n }\n async removeUpload(options) {\n console.log(\"removeUpload\", options);\n const upload = this.uploads.get(options.id);\n if (upload) {\n upload.controller.abort();\n this.uploads.delete(options.id);\n this.notifyListeners(\"events\", {\n name: \"cancelled\",\n id: options.id,\n payload: {},\n });\n }\n }\n async doUpload(id, options) {\n const { filePath, serverUrl, headers = {}, method = \"POST\", parameters = {}, } = options;\n const upload = this.uploads.get(id);\n if (!upload)\n return;\n try {\n const file = await this.getFileFromPath(filePath);\n if (!file)\n throw new Error(\"File not found\");\n const formData = new FormData();\n formData.append(\"file\", file);\n for (const [key, value] of Object.entries(parameters)) {\n formData.append(key, value);\n }\n const response = await fetch(serverUrl, {\n method,\n headers,\n body: method === \"PUT\" ? file : formData,\n signal: upload.controller.signal,\n });\n if (!response.ok)\n throw new Error(`HTTP error! status: ${response.status}`);\n this.notifyListeners(\"events\", {\n name: \"completed\",\n id,\n payload: { statusCode: response.status },\n });\n this.uploads.delete(id);\n }\n catch (error) {\n if (error.name === \"AbortError\")\n return;\n if (upload.retries > 0) {\n upload.retries--;\n console.log(`Retrying upload (retries left: ${upload.retries})`);\n setTimeout(() => this.doUpload(id, options), 1000);\n }\n else {\n this.notifyListeners(\"events\", {\n name: \"failed\",\n id,\n payload: { error: error.message },\n });\n this.uploads.delete(id);\n }\n }\n }\n async getFileFromPath(filePath) {\n // This is a simplified version. In a real-world scenario,\n // you might need to handle different types of paths or use a file system API.\n try {\n const response = await fetch(filePath);\n const blob = await response.blob();\n return new File([blob], filePath.split(\"/\").pop() || \"file\", {\n type: blob.type,\n });\n }\n catch (error) {\n console.error(\"Error getting file:\", error);\n return null;\n }\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
|
package/dist/plugin.js
CHANGED
|
@@ -1,24 +1,98 @@
|
|
|
1
|
-
var
|
|
1
|
+
var capacitorCapacitorUpdater = (function (exports, core) {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const Uploader = core.registerPlugin(
|
|
5
|
-
web: () => Promise.resolve().then(function () { return web; }).then(m => new m.UploaderWeb()),
|
|
4
|
+
const Uploader = core.registerPlugin("Uploader", {
|
|
5
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.UploaderWeb()),
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
class UploaderWeb extends core.WebPlugin {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
this.uploads = new Map();
|
|
12
12
|
}
|
|
13
13
|
async startUpload(options) {
|
|
14
|
-
console.log(
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
console.log("startUpload", options);
|
|
15
|
+
const id = Math.random().toString(36).substring(2, 15);
|
|
16
|
+
const controller = new AbortController();
|
|
17
|
+
const maxRetries = options.maxRetries || 3;
|
|
18
|
+
this.uploads.set(id, { controller, retries: maxRetries });
|
|
19
|
+
this.doUpload(id, options);
|
|
20
|
+
return { id };
|
|
17
21
|
}
|
|
18
22
|
async removeUpload(options) {
|
|
19
|
-
console.log(
|
|
20
|
-
this.
|
|
21
|
-
|
|
23
|
+
console.log("removeUpload", options);
|
|
24
|
+
const upload = this.uploads.get(options.id);
|
|
25
|
+
if (upload) {
|
|
26
|
+
upload.controller.abort();
|
|
27
|
+
this.uploads.delete(options.id);
|
|
28
|
+
this.notifyListeners("events", {
|
|
29
|
+
name: "cancelled",
|
|
30
|
+
id: options.id,
|
|
31
|
+
payload: {},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async doUpload(id, options) {
|
|
36
|
+
const { filePath, serverUrl, headers = {}, method = "POST", parameters = {}, } = options;
|
|
37
|
+
const upload = this.uploads.get(id);
|
|
38
|
+
if (!upload)
|
|
39
|
+
return;
|
|
40
|
+
try {
|
|
41
|
+
const file = await this.getFileFromPath(filePath);
|
|
42
|
+
if (!file)
|
|
43
|
+
throw new Error("File not found");
|
|
44
|
+
const formData = new FormData();
|
|
45
|
+
formData.append("file", file);
|
|
46
|
+
for (const [key, value] of Object.entries(parameters)) {
|
|
47
|
+
formData.append(key, value);
|
|
48
|
+
}
|
|
49
|
+
const response = await fetch(serverUrl, {
|
|
50
|
+
method,
|
|
51
|
+
headers,
|
|
52
|
+
body: method === "PUT" ? file : formData,
|
|
53
|
+
signal: upload.controller.signal,
|
|
54
|
+
});
|
|
55
|
+
if (!response.ok)
|
|
56
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
57
|
+
this.notifyListeners("events", {
|
|
58
|
+
name: "completed",
|
|
59
|
+
id,
|
|
60
|
+
payload: { statusCode: response.status },
|
|
61
|
+
});
|
|
62
|
+
this.uploads.delete(id);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (error.name === "AbortError")
|
|
66
|
+
return;
|
|
67
|
+
if (upload.retries > 0) {
|
|
68
|
+
upload.retries--;
|
|
69
|
+
console.log(`Retrying upload (retries left: ${upload.retries})`);
|
|
70
|
+
setTimeout(() => this.doUpload(id, options), 1000);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.notifyListeners("events", {
|
|
74
|
+
name: "failed",
|
|
75
|
+
id,
|
|
76
|
+
payload: { error: error.message },
|
|
77
|
+
});
|
|
78
|
+
this.uploads.delete(id);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async getFileFromPath(filePath) {
|
|
83
|
+
// This is a simplified version. In a real-world scenario,
|
|
84
|
+
// you might need to handle different types of paths or use a file system API.
|
|
85
|
+
try {
|
|
86
|
+
const response = await fetch(filePath);
|
|
87
|
+
const blob = await response.blob();
|
|
88
|
+
return new File([blob], filePath.split("/").pop() || "file", {
|
|
89
|
+
type: blob.type,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error("Error getting file:", error);
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
22
96
|
}
|
|
23
97
|
}
|
|
24
98
|
|
|
@@ -29,8 +103,6 @@ var capacitorUploader = (function (exports, core) {
|
|
|
29
103
|
|
|
30
104
|
exports.Uploader = Uploader;
|
|
31
105
|
|
|
32
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
33
|
-
|
|
34
106
|
return exports;
|
|
35
107
|
|
|
36
108
|
})({}, capacitorExports);
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from \"@capacitor/core\";\nconst Uploader = registerPlugin(\"Uploader\", {\n web: () => import(\"./web\").then((m) => new m.UploaderWeb()),\n});\nexport * from \"./definitions\";\nexport { Uploader };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from \"@capacitor/core\";\nexport class UploaderWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.uploads = new Map();\n }\n async startUpload(options) {\n console.log(\"startUpload\", options);\n const id = Math.random().toString(36).substring(2, 15);\n const controller = new AbortController();\n const maxRetries = options.maxRetries || 3;\n this.uploads.set(id, { controller, retries: maxRetries });\n this.doUpload(id, options);\n return { id };\n }\n async removeUpload(options) {\n console.log(\"removeUpload\", options);\n const upload = this.uploads.get(options.id);\n if (upload) {\n upload.controller.abort();\n this.uploads.delete(options.id);\n this.notifyListeners(\"events\", {\n name: \"cancelled\",\n id: options.id,\n payload: {},\n });\n }\n }\n async doUpload(id, options) {\n const { filePath, serverUrl, headers = {}, method = \"POST\", parameters = {}, } = options;\n const upload = this.uploads.get(id);\n if (!upload)\n return;\n try {\n const file = await this.getFileFromPath(filePath);\n if (!file)\n throw new Error(\"File not found\");\n const formData = new FormData();\n formData.append(\"file\", file);\n for (const [key, value] of Object.entries(parameters)) {\n formData.append(key, value);\n }\n const response = await fetch(serverUrl, {\n method,\n headers,\n body: method === \"PUT\" ? file : formData,\n signal: upload.controller.signal,\n });\n if (!response.ok)\n throw new Error(`HTTP error! status: ${response.status}`);\n this.notifyListeners(\"events\", {\n name: \"completed\",\n id,\n payload: { statusCode: response.status },\n });\n this.uploads.delete(id);\n }\n catch (error) {\n if (error.name === \"AbortError\")\n return;\n if (upload.retries > 0) {\n upload.retries--;\n console.log(`Retrying upload (retries left: ${upload.retries})`);\n setTimeout(() => this.doUpload(id, options), 1000);\n }\n else {\n this.notifyListeners(\"events\", {\n name: \"failed\",\n id,\n payload: { error: error.message },\n });\n this.uploads.delete(id);\n }\n }\n }\n async getFileFromPath(filePath) {\n // This is a simplified version. In a real-world scenario,\n // you might need to handle different types of paths or use a file system API.\n try {\n const response = await fetch(filePath);\n const blob = await response.blob();\n return new File([blob], filePath.split(\"/\").pop() || \"file\", {\n type: blob.type,\n });\n }\n catch (error) {\n console.error(\"Error getting file:\", error);\n return null;\n }\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
|
|
@@ -3,13 +3,12 @@ import Capacitor
|
|
|
3
3
|
import UniformTypeIdentifiers
|
|
4
4
|
import MobileCoreServices
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
@objc public class Uploader: NSObject, URLSessionTaskDelegate {
|
|
8
7
|
private var urlSession: URLSession?
|
|
9
8
|
private var responsesData: [Int: Data] = [:]
|
|
10
9
|
private var tasks: [String: URLSessionTask] = [:]
|
|
11
10
|
private var retries: [String: Int] = [:]
|
|
12
|
-
|
|
11
|
+
|
|
13
12
|
var eventHandler: (([String: Any]) -> Void)?
|
|
14
13
|
|
|
15
14
|
@objc public func startUpload(_ filePath: String, _ serverUrl: String, _ options: [String: Any], maxRetries: Int = 3) async throws -> String {
|
|
@@ -40,11 +39,11 @@ import MobileCoreServices
|
|
|
40
39
|
// For POST uploads
|
|
41
40
|
let boundary = UUID().uuidString
|
|
42
41
|
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
|
|
43
|
-
|
|
42
|
+
|
|
44
43
|
let parameters = options["parameters"] as? [String: String] ?? [:]
|
|
45
|
-
|
|
44
|
+
|
|
46
45
|
let dataBody = createDataBody(withParameters: parameters, filePath: filePath, mimeType: mimeType, boundary: boundary)
|
|
47
|
-
|
|
46
|
+
|
|
48
47
|
task = self.getUrlSession().uploadTask(with: request, from: dataBody)
|
|
49
48
|
}
|
|
50
49
|
|
|
@@ -101,7 +100,7 @@ import MobileCoreServices
|
|
|
101
100
|
task.resume()
|
|
102
101
|
return
|
|
103
102
|
}
|
|
104
|
-
|
|
103
|
+
|
|
105
104
|
payload["error"] = error.localizedDescription
|
|
106
105
|
sendEvent(name: "failed", id: id, payload: payload)
|
|
107
106
|
} else {
|
|
@@ -134,20 +133,20 @@ import MobileCoreServices
|
|
|
134
133
|
|
|
135
134
|
private func createDataBody(withParameters params: [String: String], filePath: String, mimeType: String, boundary: String) -> Data {
|
|
136
135
|
let data = NSMutableData()
|
|
137
|
-
|
|
136
|
+
|
|
138
137
|
for (key, value) in params {
|
|
139
138
|
data.append("--\(boundary)\r\n".data(using: .utf8)!)
|
|
140
139
|
data.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: .utf8)!)
|
|
141
140
|
data.append("\(value)\r\n".data(using: .utf8)!)
|
|
142
141
|
}
|
|
143
|
-
|
|
142
|
+
|
|
144
143
|
data.append("--\(boundary)\r\n".data(using: .utf8)!)
|
|
145
144
|
data.append("Content-Disposition: form-data; name=\"file\"; filename=\"\(URL(fileURLWithPath: filePath).lastPathComponent)\"\r\n".data(using: .utf8)!)
|
|
146
145
|
data.append("Content-Type: \(mimeType)\r\n\r\n".data(using: .utf8)!)
|
|
147
146
|
data.append(try! Data(contentsOf: URL(fileURLWithPath: filePath)))
|
|
148
147
|
data.append("\r\n".data(using: .utf8)!)
|
|
149
148
|
data.append("--\(boundary)--".data(using: .utf8)!)
|
|
150
|
-
|
|
149
|
+
|
|
151
150
|
return data as Data
|
|
152
151
|
}
|
|
153
152
|
|
|
@@ -13,20 +13,20 @@ public class UploaderPlugin: CAPPlugin {
|
|
|
13
13
|
|
|
14
14
|
@objc func startUpload(_ call: CAPPluginCall) {
|
|
15
15
|
guard let filePath = call.getString("filePath"),
|
|
16
|
-
|
|
16
|
+
let serverUrl = call.getString("serverUrl") else {
|
|
17
17
|
call.reject("Missing required parameters")
|
|
18
18
|
return
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
let options: [String: Any] = [
|
|
22
22
|
"headers": call.getObject("headers") as Any,
|
|
23
23
|
"method": call.getString("method") as Any,
|
|
24
24
|
"mimeType": call.getString("mimeType") as Any,
|
|
25
25
|
"parameters": call.getObject("parameters") as Any
|
|
26
26
|
]
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
let maxRetries = call.getInt("maxRetries") ?? 3
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
Task {
|
|
31
31
|
do {
|
|
32
32
|
let id = try await implementation.startUpload(filePath, serverUrl, options, maxRetries: maxRetries)
|
|
@@ -35,14 +35,14 @@ public class UploaderPlugin: CAPPlugin {
|
|
|
35
35
|
call.reject("Failed to start upload: \(error.localizedDescription)")
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
}
|
|
38
|
+
}
|
|
39
39
|
|
|
40
40
|
@objc func removeUpload(_ call: CAPPluginCall) {
|
|
41
41
|
guard let id = call.getString("id") else {
|
|
42
42
|
call.reject("Missing required parameter: id")
|
|
43
43
|
return
|
|
44
44
|
}
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
Task {
|
|
47
47
|
do {
|
|
48
48
|
try await implementation.removeUpload(id)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/capacitor-uploader",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Upload file natively",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -27,7 +27,24 @@
|
|
|
27
27
|
"keywords": [
|
|
28
28
|
"capacitor",
|
|
29
29
|
"plugin",
|
|
30
|
-
"native"
|
|
30
|
+
"native",
|
|
31
|
+
"uploader",
|
|
32
|
+
"s3",
|
|
33
|
+
"upload",
|
|
34
|
+
"file",
|
|
35
|
+
"upload",
|
|
36
|
+
"upload-file",
|
|
37
|
+
"upload-files",
|
|
38
|
+
"upload-file-to-s3",
|
|
39
|
+
"upload-files-to-s3",
|
|
40
|
+
"capgo",
|
|
41
|
+
"capacitor-uploader",
|
|
42
|
+
"background",
|
|
43
|
+
"background-upload",
|
|
44
|
+
"background-upload-file",
|
|
45
|
+
"background-upload-files",
|
|
46
|
+
"background-upload-file-to-s3",
|
|
47
|
+
"background-upload-files-to-s3"
|
|
31
48
|
],
|
|
32
49
|
"scripts": {
|
|
33
50
|
"verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
|
|
@@ -35,39 +52,46 @@
|
|
|
35
52
|
"verify:android": "cd android && ./gradlew clean build test && cd ..",
|
|
36
53
|
"verify:web": "npm run build",
|
|
37
54
|
"lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
|
|
38
|
-
"fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --
|
|
39
|
-
"eslint": "eslint . --ext ts",
|
|
40
|
-
"prettier": "prettier \"**/*.{css,html,ts,js,java}\"",
|
|
55
|
+
"fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --autocorrect --format",
|
|
56
|
+
"eslint": "eslint . --ext .ts",
|
|
57
|
+
"prettier": "prettier --config .prettierrc.js \"**/*.{css,html,ts,js,java}\"",
|
|
41
58
|
"swiftlint": "node-swiftlint",
|
|
42
59
|
"docgen": "docgen --api UploaderPlugin --output-readme README.md --output-json dist/docs.json",
|
|
43
|
-
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.
|
|
60
|
+
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
|
|
44
61
|
"clean": "rimraf ./dist",
|
|
45
62
|
"watch": "tsc --watch",
|
|
46
63
|
"prepublishOnly": "npm run build"
|
|
47
64
|
},
|
|
48
65
|
"devDependencies": {
|
|
49
66
|
"@capacitor/android": "^6.0.0",
|
|
67
|
+
"@capacitor/cli": "^6.0.0",
|
|
50
68
|
"@capacitor/core": "^6.0.0",
|
|
51
69
|
"@capacitor/docgen": "^0.2.2",
|
|
52
70
|
"@capacitor/ios": "^6.0.0",
|
|
53
71
|
"@ionic/eslint-config": "^0.4.0",
|
|
54
|
-
"@ionic/prettier-config": "^
|
|
72
|
+
"@ionic/prettier-config": "^4.0.0",
|
|
55
73
|
"@ionic/swiftlint-config": "^1.1.2",
|
|
74
|
+
"@types/node": "^20.12.12",
|
|
75
|
+
"@typescript-eslint/eslint-plugin": "^7.11.0",
|
|
76
|
+
"@typescript-eslint/parser": "^7.11.0",
|
|
56
77
|
"eslint": "^8.57.0",
|
|
57
|
-
"
|
|
58
|
-
"prettier
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
78
|
+
"eslint-plugin-import": "^2.29.1",
|
|
79
|
+
"prettier": "^3.2.5",
|
|
80
|
+
"prettier-plugin-java": "^2.6.0",
|
|
81
|
+
"rimraf": "^5.0.7",
|
|
82
|
+
"rollup": "^4.18.0",
|
|
83
|
+
"swiftlint": "^1.0.2",
|
|
84
|
+
"typescript": "^5.4.5"
|
|
63
85
|
},
|
|
64
86
|
"peerDependencies": {
|
|
65
87
|
"@capacitor/core": "^6.0.0"
|
|
66
88
|
},
|
|
67
89
|
"prettier": "@ionic/prettier-config",
|
|
68
|
-
"swiftlint": "@ionic/swiftlint-config",
|
|
69
90
|
"eslintConfig": {
|
|
70
|
-
"extends": "@ionic/eslint-config/recommended"
|
|
91
|
+
"extends": "@ionic/eslint-config/recommended",
|
|
92
|
+
"rules": {
|
|
93
|
+
"@typescript-eslint/prefer-optional-chain": "off"
|
|
94
|
+
}
|
|
71
95
|
},
|
|
72
96
|
"capacitor": {
|
|
73
97
|
"ios": {
|