@windwalker-io/unicorn-next 0.1.19 → 0.1.21
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/dist/chunks/_arrayPush.js +325 -108
- package/dist/chunks/_arrayPush.js.map +1 -1
- package/dist/chunks/_baseRest.js +155 -60
- package/dist/chunks/_baseRest.js.map +1 -1
- package/dist/chunks/_baseUnary.js +463 -0
- package/dist/chunks/_baseUnary.js.map +1 -0
- package/dist/chunks/_getPrototype.js +292 -100
- package/dist/chunks/_getPrototype.js.map +1 -1
- package/dist/chunks/alert-adapter.js +29 -0
- package/dist/chunks/alert-adapter.js.map +1 -0
- package/dist/chunks/alert.js +21 -0
- package/dist/chunks/alert.js.map +1 -0
- package/dist/chunks/arr.js +24 -0
- package/dist/chunks/arr.js.map +1 -0
- package/dist/chunks/button-radio.js +127 -145
- package/dist/chunks/button-radio.js.map +1 -1
- package/dist/chunks/checkboxes-multi-select.js +44 -43
- package/dist/chunks/checkboxes-multi-select.js.map +1 -1
- package/dist/chunks/chunk.js +24 -0
- package/dist/chunks/cloneDeep.js +679 -212
- package/dist/chunks/cloneDeep.js.map +1 -1
- package/dist/chunks/cropper.min.js +6 -5
- package/dist/chunks/cropper.min.js.map +1 -1
- package/dist/chunks/crypto.js +26 -0
- package/dist/chunks/crypto.js.map +1 -0
- package/dist/chunks/data.js +49 -0
- package/dist/chunks/data.js.map +1 -0
- package/dist/chunks/dom.js +128 -0
- package/dist/chunks/dom.js.map +1 -0
- package/dist/chunks/events.js +270 -0
- package/dist/chunks/events.js.map +1 -0
- package/dist/chunks/field-cascade-select.js +207 -250
- package/dist/chunks/field-cascade-select.js.map +1 -1
- package/dist/chunks/field-file-drag.js +175 -209
- package/dist/chunks/field-file-drag.js.map +1 -1
- package/dist/chunks/field-flatpickr.js +94 -898
- package/dist/chunks/field-flatpickr.js.map +1 -1
- package/dist/chunks/field-modal-select.js +728 -467
- package/dist/chunks/field-modal-select.js.map +1 -1
- package/dist/chunks/field-modal-tree.js +771 -766
- package/dist/chunks/field-modal-tree.js.map +1 -1
- package/dist/chunks/field-multi-uploader.js +249 -256
- package/dist/chunks/field-multi-uploader.js.map +1 -1
- package/dist/chunks/field-repeatable.js +111 -127
- package/dist/chunks/field-repeatable.js.map +1 -1
- package/dist/chunks/field-single-image-drag.js +286 -338
- package/dist/chunks/field-single-image-drag.js.map +1 -1
- package/dist/chunks/form.js +146 -159
- package/dist/chunks/form.js.map +1 -1
- package/dist/chunks/grid.js +349 -418
- package/dist/chunks/grid.js.map +1 -1
- package/dist/chunks/helper.js +39 -0
- package/dist/chunks/helper.js.map +1 -0
- package/dist/chunks/http-client.js +221 -211
- package/dist/chunks/http-client.js.map +1 -1
- package/dist/chunks/iframe-modal.js +95 -115
- package/dist/chunks/iframe-modal.js.map +1 -1
- package/dist/chunks/keep-tab.js +92 -101
- package/dist/chunks/keep-tab.js.map +1 -1
- package/dist/chunks/lang.js +250 -0
- package/dist/chunks/lang.js.map +1 -0
- package/dist/chunks/legacy.js +197 -201
- package/dist/chunks/legacy.js.map +1 -1
- package/dist/chunks/list-dependent.js +195 -228
- package/dist/chunks/list-dependent.js.map +1 -1
- package/dist/chunks/loader.js +106 -0
- package/dist/chunks/loader.js.map +1 -0
- package/dist/chunks/monthSelect.js +251 -0
- package/dist/chunks/monthSelect.js.map +1 -0
- package/dist/chunks/router.js +111 -0
- package/dist/chunks/router.js.map +1 -0
- package/dist/chunks/s3-multipart-uploader.js +183 -210
- package/dist/chunks/s3-multipart-uploader.js.map +1 -1
- package/dist/chunks/s3-uploader.js +106 -128
- package/dist/chunks/s3-uploader.js.map +1 -1
- package/dist/chunks/show-on.js +358 -205
- package/dist/chunks/show-on.js.map +1 -1
- package/dist/chunks/timing.js +10 -0
- package/dist/chunks/timing.js.map +1 -0
- package/dist/chunks/tinymce.js +153 -203
- package/dist/chunks/tinymce.js.map +1 -1
- package/dist/chunks/ui-bootstrap5.js +58 -72
- package/dist/chunks/ui-bootstrap5.js.map +1 -1
- package/dist/chunks/ui.js +320 -0
- package/dist/chunks/ui.js.map +1 -0
- package/dist/chunks/unicorn.js.map +1 -1
- package/dist/chunks/useQueue.js +111 -0
- package/dist/chunks/useQueue.js.map +1 -0
- package/dist/chunks/useStack.js +76 -0
- package/dist/chunks/useStack.js.map +1 -0
- package/dist/chunks/validation.js +761 -853
- package/dist/chunks/validation.js.map +1 -1
- package/dist/editor.css +1 -1
- package/dist/index.d.ts +10 -8
- package/dist/multi-level-menu.css +1 -1
- package/dist/switcher.css +1 -1
- package/dist/unicorn.js +805 -130
- package/dist/unicorn.js.map +1 -1
- package/package.json +3 -3
- package/src/composable/useBsModalAlert.ts +29 -0
- package/src/composable/useHttp.ts +13 -1
- package/src/module/s3-uploader.ts +1 -1
- package/vite.config.ts +5 -1
- package/dist/chunks/_commonjsHelpers.js +0 -7
- package/dist/chunks/index.js +0 -314
- package/dist/chunks/isArguments.js +0 -146
- package/dist/chunks/unicorn.js +0 -2621
|
@@ -1,137 +1,115 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { n as Mixin, t as EventMixin } from "./events.js";
|
|
2
|
+
import { t as mergeDeep } from "./arr.js";
|
|
3
|
+
import { t as data } from "./data.js";
|
|
4
|
+
import { useHttpClient } from "../unicorn.js";
|
|
5
|
+
//#region src/module/s3-uploader.ts
|
|
6
|
+
var instances = {};
|
|
3
7
|
function get(name, options = {}) {
|
|
4
|
-
|
|
8
|
+
return instances[name] ??= create(name, options);
|
|
5
9
|
}
|
|
6
10
|
function create(name, options = {}) {
|
|
7
|
-
|
|
11
|
+
return new S3Uploader(name, options);
|
|
8
12
|
}
|
|
9
13
|
function destroy(name) {
|
|
10
|
-
|
|
14
|
+
delete instances[name];
|
|
11
15
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
var defaultOptions = {
|
|
17
|
+
endpoint: "",
|
|
18
|
+
subfolder: "",
|
|
19
|
+
viewerHost: "",
|
|
20
|
+
starts_with: [],
|
|
21
|
+
formInputs: {
|
|
22
|
+
acl: "",
|
|
23
|
+
bucket: "",
|
|
24
|
+
key: "",
|
|
25
|
+
Policy: "",
|
|
26
|
+
"X-Amz-Algorithm": "",
|
|
27
|
+
"X-Amz-Credential": "",
|
|
28
|
+
"X-Amz-Date": "",
|
|
29
|
+
"X-Amz-Signature": ""
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
var S3Uploader = class extends Mixin(EventMixin) {
|
|
33
|
+
options;
|
|
34
|
+
http;
|
|
35
|
+
constructor(name, options = {}) {
|
|
36
|
+
super();
|
|
37
|
+
this.name = name;
|
|
38
|
+
this.options = mergeDeep({}, defaultOptions, data("@s3.uploader." + name) || {}, options);
|
|
39
|
+
}
|
|
40
|
+
async getHttpClient() {
|
|
41
|
+
return this.http ??= await useHttpClient();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Do upload.
|
|
45
|
+
*/
|
|
46
|
+
async upload(file, path, options = {}) {
|
|
47
|
+
const httpClient = await this.getHttpClient();
|
|
48
|
+
const fileData = new FormData();
|
|
49
|
+
const inputs = mergeDeep({}, this.options.formInputs, options.formInputs || {});
|
|
50
|
+
if (typeof file === "string") file = new Blob([file], { type: options["Content-Type"] || "text/plain" });
|
|
51
|
+
if (file instanceof Blob && !(file instanceof File) && path.endsWith(".{ext}")) throw new Error("If using Blob or file data string, you must provide a valid file extension in the path.");
|
|
52
|
+
if (file instanceof Blob || file instanceof File) options["Content-Type"] = options["Content-Type"] || file.type;
|
|
53
|
+
if (options["filename"]) {
|
|
54
|
+
const filename = this.replaceExt(options["filename"], file);
|
|
55
|
+
options["Content-Disposition"] = "attachment; filename*=UTF-8''" + encodeURIComponent(filename);
|
|
56
|
+
}
|
|
57
|
+
path = this.replaceExt(path, file);
|
|
58
|
+
options["key"] = trimSlashes(this.options.subfolder || "") + "/" + trimSlashes(path);
|
|
59
|
+
options["key"] = trimSlashes(options["key"]);
|
|
60
|
+
options["Content-Type"] = options["Content-Type"] || void 0;
|
|
61
|
+
options["Content-Disposition"] = options["Content-Disposition"] || void 0;
|
|
62
|
+
for (let key in inputs) fileData.set(key, inputs[key]);
|
|
63
|
+
for (let key of Object.keys(this.options.starts_with)) if (options[key]) fileData.set(key, options[key]);
|
|
64
|
+
fileData.append("file", file);
|
|
65
|
+
this.trigger("start", fileData);
|
|
66
|
+
try {
|
|
67
|
+
let res = await httpClient.post(this.options.endpoint || "", fileData, {
|
|
68
|
+
signal: options.signal,
|
|
69
|
+
onUploadProgress: (e) => {
|
|
70
|
+
if (options.onUploadProgress) options.onUploadProgress(e);
|
|
71
|
+
this.trigger("upload-progress", e);
|
|
72
|
+
if (e.total != null) this.trigger("progress", e.loaded / e.total, e);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
const url = this.options.viewerHost + "/" + trimSlashes(path);
|
|
76
|
+
this.trigger("success", url, res);
|
|
77
|
+
res.url = url;
|
|
78
|
+
return res;
|
|
79
|
+
} finally {
|
|
80
|
+
this.trigger("end");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
replaceExt(path, file) {
|
|
84
|
+
if (file instanceof File) {
|
|
85
|
+
const fileExt = file.name.split(".").pop();
|
|
86
|
+
if (path.endsWith(".{ext}")) return path.replace(/\.{ext}$/, fileExt ? "." + fileExt : "");
|
|
87
|
+
}
|
|
88
|
+
return path;
|
|
89
|
+
}
|
|
90
|
+
on(event, handler) {
|
|
91
|
+
return super.on(event, handler);
|
|
92
|
+
}
|
|
93
|
+
onStart(handler) {
|
|
94
|
+
return this.on("start", handler);
|
|
95
|
+
}
|
|
96
|
+
onSuccess(handler) {
|
|
97
|
+
return this.on("success", handler);
|
|
98
|
+
}
|
|
99
|
+
onEnd(handler) {
|
|
100
|
+
return this.on("end", handler);
|
|
101
|
+
}
|
|
102
|
+
onProgress(handler) {
|
|
103
|
+
return this.on("upload-progress", handler);
|
|
104
|
+
}
|
|
105
|
+
onProgressWithTotal(handler) {
|
|
106
|
+
return this.on("progress", handler);
|
|
107
|
+
}
|
|
27
108
|
};
|
|
28
|
-
class S3Uploader extends (/* @__PURE__ */ Mixin(EventMixin)) {
|
|
29
|
-
constructor(name, options = {}) {
|
|
30
|
-
super();
|
|
31
|
-
this.name = name;
|
|
32
|
-
const awsOptions = data("@s3.uploader." + name) || {};
|
|
33
|
-
this.options = mergeDeep({}, defaultOptions, awsOptions, options);
|
|
34
|
-
}
|
|
35
|
-
options;
|
|
36
|
-
http;
|
|
37
|
-
async getHttpClient() {
|
|
38
|
-
return this.http ??= await useHttpClient();
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Do upload.
|
|
42
|
-
*/
|
|
43
|
-
async upload(file, path, options = {}) {
|
|
44
|
-
const httpClient = await this.getHttpClient();
|
|
45
|
-
const fileData = new FormData();
|
|
46
|
-
const inputs = mergeDeep({}, this.options.formInputs, options.formInputs || {});
|
|
47
|
-
if (typeof file === "string") {
|
|
48
|
-
file = new Blob([file], { type: options["Content-Type"] || "text/plain" });
|
|
49
|
-
}
|
|
50
|
-
if (file instanceof Blob && path.endsWith(".{ext}")) {
|
|
51
|
-
throw new Error("If using Blob or file data string, you must provide a valid file extension in the path.");
|
|
52
|
-
}
|
|
53
|
-
if (file instanceof Blob || file instanceof File) {
|
|
54
|
-
options["Content-Type"] = options["Content-Type"] || file.type;
|
|
55
|
-
}
|
|
56
|
-
if (options["filename"]) {
|
|
57
|
-
const filename = this.replaceExt(options["filename"], file);
|
|
58
|
-
options["Content-Disposition"] = "attachment; filename*=UTF-8''" + encodeURIComponent(filename);
|
|
59
|
-
}
|
|
60
|
-
path = this.replaceExt(path, file);
|
|
61
|
-
options["key"] = trimSlashes(this.options.subfolder || "") + "/" + trimSlashes(path);
|
|
62
|
-
options["key"] = trimSlashes(options["key"]);
|
|
63
|
-
options["Content-Type"] = options["Content-Type"] || void 0;
|
|
64
|
-
options["Content-Disposition"] = options["Content-Disposition"] || void 0;
|
|
65
|
-
for (let key in inputs) {
|
|
66
|
-
fileData.set(key, inputs[key]);
|
|
67
|
-
}
|
|
68
|
-
for (let key of Object.keys(this.options.starts_with)) {
|
|
69
|
-
if (options[key]) {
|
|
70
|
-
fileData.set(key, options[key]);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
fileData.append("file", file);
|
|
74
|
-
this.trigger("start", fileData);
|
|
75
|
-
try {
|
|
76
|
-
let res = await httpClient.post(
|
|
77
|
-
this.options.endpoint || "",
|
|
78
|
-
fileData,
|
|
79
|
-
{
|
|
80
|
-
signal: options.signal,
|
|
81
|
-
onUploadProgress: (e) => {
|
|
82
|
-
if (options.onUploadProgress) {
|
|
83
|
-
options.onUploadProgress(e);
|
|
84
|
-
}
|
|
85
|
-
this.trigger("upload-progress", e);
|
|
86
|
-
if (e.total != null) {
|
|
87
|
-
this.trigger("progress", e.loaded / e.total, e);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
);
|
|
92
|
-
const url = this.options.viewerHost + "/" + trimSlashes(path);
|
|
93
|
-
this.trigger("success", url, res);
|
|
94
|
-
res.url = url;
|
|
95
|
-
return res;
|
|
96
|
-
} finally {
|
|
97
|
-
this.trigger("end");
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
replaceExt(path, file) {
|
|
101
|
-
if (file instanceof File) {
|
|
102
|
-
const fileExt = file.name.split(".").pop();
|
|
103
|
-
if (path.endsWith(".{ext}")) {
|
|
104
|
-
return path.replace(/\.{ext}$/, fileExt ? "." + fileExt : "");
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return path;
|
|
108
|
-
}
|
|
109
|
-
on(event, handler) {
|
|
110
|
-
return super.on(event, handler);
|
|
111
|
-
}
|
|
112
|
-
onStart(handler) {
|
|
113
|
-
return this.on("start", handler);
|
|
114
|
-
}
|
|
115
|
-
onSuccess(handler) {
|
|
116
|
-
return this.on("success", handler);
|
|
117
|
-
}
|
|
118
|
-
onEnd(handler) {
|
|
119
|
-
return this.on("end", handler);
|
|
120
|
-
}
|
|
121
|
-
onProgress(handler) {
|
|
122
|
-
return this.on("upload-progress", handler);
|
|
123
|
-
}
|
|
124
|
-
onProgressWithTotal(handler) {
|
|
125
|
-
return this.on("progress", handler);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
109
|
function trimSlashes(str) {
|
|
129
|
-
|
|
110
|
+
return str.replace(/^\/+|\/+$/g, "");
|
|
130
111
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
get
|
|
136
|
-
};
|
|
137
|
-
//# sourceMappingURL=s3-uploader.js.map
|
|
112
|
+
//#endregion
|
|
113
|
+
export { S3Uploader, create, destroy, get };
|
|
114
|
+
|
|
115
|
+
//# sourceMappingURL=s3-uploader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"s3-uploader.js","sources":["../../src/module/s3-uploader.ts"],"sourcesContent":["import { useHttpClient } from '../composable';\nimport { data } from '../data';\nimport { EventAwareInterface, EventHandler, EventMixin } from '../events';\nimport type { UnicornHttpClient } from './http-client';\nimport { mergeDeep } from '../utilities';\nimport { AxiosProgressEvent, AxiosResponse } from 'axios';\nimport { Mixin } from 'ts-mixer';\n\nconst instances: Record<string, S3Uploader> = {};\nexport function get(name: string, options?: Partial<S3UploaderGlobalOptions>): S3Uploader;\nexport function get(\n name: string,\n options: Partial<S3UploaderGlobalOptions> = {}\n): S3Uploader | void {\n return instances[name] ??= create(name, options);\n}\n\nexport function create(name: string, options: Partial<S3UploaderGlobalOptions> = {}): S3Uploader {\n return new S3Uploader(name, options);\n}\n\nexport function destroy(name: string) {\n delete instances[name];\n}\n\nconst defaultOptions: S3UploaderGlobalOptions = {\n endpoint: '',\n subfolder: '',\n viewerHost: '',\n starts_with: [],\n formInputs: {\n acl: '',\n bucket: '',\n key: '',\n Policy: '',\n 'X-Amz-Algorithm': '',\n 'X-Amz-Credential': '',\n 'X-Amz-Date': '',\n 'X-Amz-Signature': '',\n }\n};\n\nexport class S3Uploader extends Mixin(EventMixin) implements EventAwareInterface {\n options: S3UploaderGlobalOptions;\n http?: UnicornHttpClient;\n\n constructor(protected name: string, options: Partial<S3UploaderGlobalOptions> = {}) {\n super();\n\n const awsOptions = data('@s3.uploader.' + name) || {};\n\n this.options = mergeDeep<S3UploaderGlobalOptions>({}, defaultOptions, awsOptions, options);\n }\n\n async getHttpClient() {\n return this.http ??= await useHttpClient();\n }\n\n /**\n * Do upload.\n */\n async upload(\n file: string | File | Blob,\n path: string,\n options: Partial<S3UploaderRequestOptions> = {}\n ): Promise<S3UploaderResponse> {\n const httpClient = await this.getHttpClient();\n\n const fileData = new FormData();\n const inputs = mergeDeep({}, this.options.formInputs, options.formInputs || {});\n\n if (typeof file === 'string') {\n file = new Blob([file], { type: options['Content-Type'] || 'text/plain' });\n }\n\n if (file instanceof Blob && path.endsWith('.{ext}')) {\n throw new Error('If using Blob or file data string, you must provide a valid file extension in the path.');\n }\n\n if ((file instanceof Blob) || (file as any) instanceof File) {\n options['Content-Type'] = options['Content-Type'] || file.type;\n }\n\n if (options['filename']) {\n const filename = this.replaceExt(options['filename'], file);\n options['Content-Disposition'] = 'attachment; filename*=UTF-8\\'\\'' + encodeURIComponent(filename);\n }\n\n path = this.replaceExt(path, file);\n\n options['key'] = trimSlashes(this.options.subfolder || '') + '/'\n + trimSlashes(path);\n options['key'] = trimSlashes(options['key']);\n options['Content-Type'] = options['Content-Type'] || undefined;\n options['Content-Disposition'] = options['Content-Disposition'] || undefined;\n\n // Prepare pre-signed data\n for (let key in inputs) {\n fileData.set(key, inputs[key]);\n }\n\n // Prepare custom data\n for (let key of Object.keys(this.options.starts_with)) {\n if (options[key]) {\n fileData.set(key, options[key]);\n }\n }\n\n fileData.append('file', file);\n\n this.trigger('start', fileData);\n\n try {\n let res = await httpClient.post(\n this.options.endpoint || '',\n fileData,\n {\n signal: options.signal,\n onUploadProgress: (e) => {\n if (options.onUploadProgress) {\n options.onUploadProgress(e);\n }\n\n this.trigger('upload-progress', e);\n\n if (e.total != null) {\n this.trigger('progress', e.loaded / e.total, e);\n }\n }\n }\n ) as S3UploaderResponse;\n\n const url = this.options.viewerHost + '/'\n + trimSlashes(path);\n\n this.trigger('success', url, res);\n\n res.url = url;\n\n return res;\n } finally {\n this.trigger('end');\n }\n }\n\n replaceExt(path: string, file: File | Blob): string {\n if (file instanceof File) {\n const fileExt = file.name.split('.').pop();\n\n if (path.endsWith('.{ext}')) {\n return path.replace(/\\.{ext}$/, fileExt ? '.' + fileExt : '');\n }\n }\n\n return path;\n }\n\n on(event: 'start', handler: StartEventHandler): this;\n on(event: 'success', handler: SuccessEventHandler): this;\n on(event: 'end', handler: EndEventHandler): this;\n on(event: 'upload-progress', handler: UploadProgressEventHandler): this;\n on(event: 'progress', handler: ProgressEventHandler): this;\n on(event: string | string[], handler: EventHandler): this {\n return super.on(event, handler);\n }\n\n onStart(handler: StartEventHandler): this {\n return this.on('start', handler);\n }\n\n onSuccess(handler: SuccessEventHandler): this {\n return this.on('success', handler);\n }\n\n onEnd(handler: EndEventHandler): this {\n return this.on('end', handler);\n }\n\n onProgress(handler: UploadProgressEventHandler): this {\n return this.on('upload-progress', handler);\n }\n\n onProgressWithTotal(handler: ProgressEventHandler): this {\n return this.on('progress', handler);\n }\n}\n\ntype EndEventHandler = () => void;\ntype SuccessEventHandler = (url: string, res: S3UploaderResponse) => void;\ntype StartEventHandler = (fileData: FormData) => void;\ntype UploadProgressEventHandler = (e: AxiosProgressEvent) => void;\ntype ProgressEventHandler = (total: number, e: AxiosProgressEvent) => void;\n\nfunction trimSlashes(str: string) {\n return str.replace(/^\\/+|\\/+$/g, '');\n}\n\nexport interface S3UploaderResponse extends AxiosResponse {\n url: string;\n}\n\nexport interface S3UploaderGlobalOptions {\n endpoint?: string;\n subfolder?: string;\n viewerHost?: string;\n starts_with: any[];\n formInputs?: {\n acl: string;\n bucket: string;\n key: string;\n Policy: string;\n 'X-Amz-Algorithm': string;\n 'X-Amz-Credential': string;\n 'X-Amz-Date': string;\n 'X-Amz-Signature': string;\n [name: string]: any\n },\n}\n\nexport interface S3UploaderRequestOptions {\n formInputs?: { [name: string]: any };\n onUploadProgress?: (e: AxiosProgressEvent) => void;\n 'Content-Type'?: string;\n 'Content-Disposition'?: string;\n key?: string;\n signal?: AbortSignal;\n\n [name: string]: any;\n}\n\nexport interface S3UploaderModule {\n get(name: string, options?: Partial<S3UploaderGlobalOptions>): S3Uploader;\n create(name: string, options?: Partial<S3UploaderGlobalOptions>): S3Uploader;\n destroy(name: string): void;\n S3Uploader: typeof S3Uploader;\n}\n"],"
|
|
1
|
+
{"version":3,"file":"s3-uploader.js","names":[],"sources":["../../src/module/s3-uploader.ts"],"sourcesContent":["import { useHttpClient } from '../composable';\nimport { data } from '../data';\nimport { EventAwareInterface, EventHandler, EventMixin } from '../events';\nimport type { UnicornHttpClient } from './http-client';\nimport { mergeDeep } from '../utilities';\nimport { AxiosProgressEvent, AxiosResponse } from 'axios';\nimport { Mixin } from 'ts-mixer';\n\nconst instances: Record<string, S3Uploader> = {};\nexport function get(name: string, options?: Partial<S3UploaderGlobalOptions>): S3Uploader;\nexport function get(\n name: string,\n options: Partial<S3UploaderGlobalOptions> = {}\n): S3Uploader | void {\n return instances[name] ??= create(name, options);\n}\n\nexport function create(name: string, options: Partial<S3UploaderGlobalOptions> = {}): S3Uploader {\n return new S3Uploader(name, options);\n}\n\nexport function destroy(name: string) {\n delete instances[name];\n}\n\nconst defaultOptions: S3UploaderGlobalOptions = {\n endpoint: '',\n subfolder: '',\n viewerHost: '',\n starts_with: [],\n formInputs: {\n acl: '',\n bucket: '',\n key: '',\n Policy: '',\n 'X-Amz-Algorithm': '',\n 'X-Amz-Credential': '',\n 'X-Amz-Date': '',\n 'X-Amz-Signature': '',\n }\n};\n\nexport class S3Uploader extends Mixin(EventMixin) implements EventAwareInterface {\n options: S3UploaderGlobalOptions;\n http?: UnicornHttpClient;\n\n constructor(protected name: string, options: Partial<S3UploaderGlobalOptions> = {}) {\n super();\n\n const awsOptions = data('@s3.uploader.' + name) || {};\n\n this.options = mergeDeep<S3UploaderGlobalOptions>({}, defaultOptions, awsOptions, options);\n }\n\n async getHttpClient() {\n return this.http ??= await useHttpClient();\n }\n\n /**\n * Do upload.\n */\n async upload(\n file: string | File | Blob,\n path: string,\n options: Partial<S3UploaderRequestOptions> = {}\n ): Promise<S3UploaderResponse> {\n const httpClient = await this.getHttpClient();\n\n const fileData = new FormData();\n const inputs = mergeDeep({}, this.options.formInputs, options.formInputs || {});\n\n if (typeof file === 'string') {\n file = new Blob([file], { type: options['Content-Type'] || 'text/plain' });\n }\n\n if (file instanceof Blob && !(file instanceof File) && path.endsWith('.{ext}')) {\n throw new Error('If using Blob or file data string, you must provide a valid file extension in the path.');\n }\n\n if ((file instanceof Blob) || (file as any) instanceof File) {\n options['Content-Type'] = options['Content-Type'] || file.type;\n }\n\n if (options['filename']) {\n const filename = this.replaceExt(options['filename'], file);\n options['Content-Disposition'] = 'attachment; filename*=UTF-8\\'\\'' + encodeURIComponent(filename);\n }\n\n path = this.replaceExt(path, file);\n\n options['key'] = trimSlashes(this.options.subfolder || '') + '/'\n + trimSlashes(path);\n options['key'] = trimSlashes(options['key']);\n options['Content-Type'] = options['Content-Type'] || undefined;\n options['Content-Disposition'] = options['Content-Disposition'] || undefined;\n\n // Prepare pre-signed data\n for (let key in inputs) {\n fileData.set(key, inputs[key]);\n }\n\n // Prepare custom data\n for (let key of Object.keys(this.options.starts_with)) {\n if (options[key]) {\n fileData.set(key, options[key]);\n }\n }\n\n fileData.append('file', file);\n\n this.trigger('start', fileData);\n\n try {\n let res = await httpClient.post(\n this.options.endpoint || '',\n fileData,\n {\n signal: options.signal,\n onUploadProgress: (e) => {\n if (options.onUploadProgress) {\n options.onUploadProgress(e);\n }\n\n this.trigger('upload-progress', e);\n\n if (e.total != null) {\n this.trigger('progress', e.loaded / e.total, e);\n }\n }\n }\n ) as S3UploaderResponse;\n\n const url = this.options.viewerHost + '/'\n + trimSlashes(path);\n\n this.trigger('success', url, res);\n\n res.url = url;\n\n return res;\n } finally {\n this.trigger('end');\n }\n }\n\n replaceExt(path: string, file: File | Blob): string {\n if (file instanceof File) {\n const fileExt = file.name.split('.').pop();\n\n if (path.endsWith('.{ext}')) {\n return path.replace(/\\.{ext}$/, fileExt ? '.' + fileExt : '');\n }\n }\n\n return path;\n }\n\n on(event: 'start', handler: StartEventHandler): this;\n on(event: 'success', handler: SuccessEventHandler): this;\n on(event: 'end', handler: EndEventHandler): this;\n on(event: 'upload-progress', handler: UploadProgressEventHandler): this;\n on(event: 'progress', handler: ProgressEventHandler): this;\n on(event: string | string[], handler: EventHandler): this {\n return super.on(event, handler);\n }\n\n onStart(handler: StartEventHandler): this {\n return this.on('start', handler);\n }\n\n onSuccess(handler: SuccessEventHandler): this {\n return this.on('success', handler);\n }\n\n onEnd(handler: EndEventHandler): this {\n return this.on('end', handler);\n }\n\n onProgress(handler: UploadProgressEventHandler): this {\n return this.on('upload-progress', handler);\n }\n\n onProgressWithTotal(handler: ProgressEventHandler): this {\n return this.on('progress', handler);\n }\n}\n\ntype EndEventHandler = () => void;\ntype SuccessEventHandler = (url: string, res: S3UploaderResponse) => void;\ntype StartEventHandler = (fileData: FormData) => void;\ntype UploadProgressEventHandler = (e: AxiosProgressEvent) => void;\ntype ProgressEventHandler = (total: number, e: AxiosProgressEvent) => void;\n\nfunction trimSlashes(str: string) {\n return str.replace(/^\\/+|\\/+$/g, '');\n}\n\nexport interface S3UploaderResponse extends AxiosResponse {\n url: string;\n}\n\nexport interface S3UploaderGlobalOptions {\n endpoint?: string;\n subfolder?: string;\n viewerHost?: string;\n starts_with: any[];\n formInputs?: {\n acl: string;\n bucket: string;\n key: string;\n Policy: string;\n 'X-Amz-Algorithm': string;\n 'X-Amz-Credential': string;\n 'X-Amz-Date': string;\n 'X-Amz-Signature': string;\n [name: string]: any\n },\n}\n\nexport interface S3UploaderRequestOptions {\n formInputs?: { [name: string]: any };\n onUploadProgress?: (e: AxiosProgressEvent) => void;\n 'Content-Type'?: string;\n 'Content-Disposition'?: string;\n key?: string;\n signal?: AbortSignal;\n\n [name: string]: any;\n}\n\nexport interface S3UploaderModule {\n get(name: string, options?: Partial<S3UploaderGlobalOptions>): S3Uploader;\n create(name: string, options?: Partial<S3UploaderGlobalOptions>): S3Uploader;\n destroy(name: string): void;\n S3Uploader: typeof S3Uploader;\n}\n"],"mappings":"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"}
|