comty.js 0.65.5 → 0.66.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.
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _events = require('@foxify/events'); var _events2 = _interopRequireDefault(_events);
|
|
2
|
+
|
|
3
|
+
class FileUploadBrowser {
|
|
4
|
+
constructor(params) {;FileUploadBrowser.prototype.__init.call(this);FileUploadBrowser.prototype.__init2.call(this);FileUploadBrowser.prototype.__init3.call(this);
|
|
5
|
+
const {
|
|
6
|
+
endpoint,
|
|
7
|
+
file,
|
|
8
|
+
headers = {},
|
|
9
|
+
splitChunkSize = 1024 * 1024 * 10,
|
|
10
|
+
maxRetries = 3,
|
|
11
|
+
delayBeforeRetry = 5,
|
|
12
|
+
} = params
|
|
13
|
+
|
|
14
|
+
if (!endpoint) {
|
|
15
|
+
throw new Error("Missing endpoint")
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if ((!file) instanceof File) {
|
|
19
|
+
throw new Error("Invalid or missing file")
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (typeof headers !== "object") {
|
|
23
|
+
throw new Error("Invalid headers")
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (splitChunkSize <= 0) {
|
|
27
|
+
throw new Error("Invalid splitChunkSize")
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
this.chunkCount = 0
|
|
31
|
+
this.retriesCount = 0
|
|
32
|
+
|
|
33
|
+
this.splitChunkSize = splitChunkSize
|
|
34
|
+
this.totalChunks = Math.ceil(file.size / splitChunkSize)
|
|
35
|
+
|
|
36
|
+
this.maxRetries = maxRetries
|
|
37
|
+
this.delayBeforeRetry = delayBeforeRetry
|
|
38
|
+
this.offline = this.paused = false
|
|
39
|
+
|
|
40
|
+
this.endpoint = endpoint
|
|
41
|
+
this.file = file
|
|
42
|
+
this.headers = {
|
|
43
|
+
...headers,
|
|
44
|
+
"uploader-original-name": encodeURIComponent(file.name),
|
|
45
|
+
"uploader-file-id": this.getFileUID(file),
|
|
46
|
+
"uploader-chunks-total": this.totalChunks,
|
|
47
|
+
"chunk-size": splitChunkSize,
|
|
48
|
+
"cache-control": "no-cache",
|
|
49
|
+
connection: "keep-alive",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
window.addEventListener(
|
|
53
|
+
"online",
|
|
54
|
+
() =>
|
|
55
|
+
!this.offline &&
|
|
56
|
+
((this.offline = false),
|
|
57
|
+
this.events.emit("online"),
|
|
58
|
+
this.nextSend()),
|
|
59
|
+
)
|
|
60
|
+
window.addEventListener(
|
|
61
|
+
"offline",
|
|
62
|
+
() => ((this.offline = true), this.events.emit("offline")),
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
__init() {this._reader = new FileReader()}
|
|
67
|
+
__init2() {this.events = new (0, _events2.default)()}
|
|
68
|
+
|
|
69
|
+
__init3() {this.start = () => {
|
|
70
|
+
this.nextSend()
|
|
71
|
+
}}
|
|
72
|
+
|
|
73
|
+
getFileUID(file) {
|
|
74
|
+
return (
|
|
75
|
+
Math.floor(Math.random() * 100000000) +
|
|
76
|
+
Date.now() +
|
|
77
|
+
file.size +
|
|
78
|
+
"_tmp"
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
loadChunk() {
|
|
83
|
+
return new Promise((resolve) => {
|
|
84
|
+
const start = this.chunkCount * this.splitChunkSize
|
|
85
|
+
const end = Math.min(start + this.splitChunkSize, this.file.size)
|
|
86
|
+
|
|
87
|
+
// load chunk as buffer
|
|
88
|
+
this._reader.onload = () => {
|
|
89
|
+
resolve(
|
|
90
|
+
new Blob([this._reader.result], {
|
|
91
|
+
type: "application/octet-stream",
|
|
92
|
+
}),
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
this._reader.readAsArrayBuffer(this.file.slice(start, end))
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async sendChunk() {
|
|
100
|
+
console.log(`[UPLOADER] Sending chunk ${this.chunkCount}`, {
|
|
101
|
+
currentChunk: this.chunkCount,
|
|
102
|
+
totalChunks: this.totalChunks,
|
|
103
|
+
chunk: this.chunk,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
const res = await fetch(this.endpoint, {
|
|
108
|
+
method: "POST",
|
|
109
|
+
headers: {
|
|
110
|
+
...this.headers,
|
|
111
|
+
"uploader-chunk-number": this.chunkCount,
|
|
112
|
+
},
|
|
113
|
+
body: this.chunk,
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
return res
|
|
117
|
+
} catch (error) {
|
|
118
|
+
this.manageRetries()
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
manageRetries() {
|
|
123
|
+
if (++this.retriesCount < this.maxRetries) {
|
|
124
|
+
setTimeout(() => this.nextSend(), this.delayBeforeRetry * 1000)
|
|
125
|
+
|
|
126
|
+
this.events.emit("fileRetry", {
|
|
127
|
+
message: `Retrying chunk ${this.chunkCount}`,
|
|
128
|
+
chunk: this.chunkCount,
|
|
129
|
+
retriesLeft: this.retries - this.retriesCount,
|
|
130
|
+
})
|
|
131
|
+
} else {
|
|
132
|
+
this.events.emit("error", {
|
|
133
|
+
message: `No more retries for chunk ${this.chunkCount}`,
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async nextSend() {
|
|
139
|
+
if (this.paused || this.offline) {
|
|
140
|
+
return null
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
this.chunk = await this.loadChunk()
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
const res = await this.sendChunk()
|
|
147
|
+
|
|
148
|
+
if (![200, 201, 204].includes(res.status)) {
|
|
149
|
+
// failed!!
|
|
150
|
+
return this.manageRetries()
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const data = await res.json()
|
|
154
|
+
|
|
155
|
+
console.log(`[UPLOADER] Chunk ${this.chunkCount} sent`)
|
|
156
|
+
|
|
157
|
+
this.chunkCount = this.chunkCount + 1
|
|
158
|
+
|
|
159
|
+
if (this.chunkCount < this.totalChunks) {
|
|
160
|
+
this.nextSend()
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// check if is the last chunk, if so, handle sse events
|
|
164
|
+
if (this.chunkCount === this.totalChunks) {
|
|
165
|
+
if (data.sseChannelId || data.sseUrl) {
|
|
166
|
+
this.waitOnSSE(data)
|
|
167
|
+
} else {
|
|
168
|
+
this.events.emit("finish", data)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
this.events.emit("progress", {
|
|
173
|
+
percent: Math.round((100 / this.totalChunks) * this.chunkCount),
|
|
174
|
+
state: "Uploading",
|
|
175
|
+
})
|
|
176
|
+
} catch (error) {
|
|
177
|
+
this.events.emit("error", error)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
togglePause() {
|
|
182
|
+
this.paused = !this.paused
|
|
183
|
+
|
|
184
|
+
if (!this.paused) {
|
|
185
|
+
return this.nextSend()
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
waitOnSSE(data) {
|
|
190
|
+
// temporal solution until a better solution
|
|
191
|
+
const url = `${app.cores.api.client().mainOrigin}/upload/sse_events/${data.sseChannelId}`
|
|
192
|
+
|
|
193
|
+
console.log(`[UPLOADER] Connecting to SSE channel >`, url)
|
|
194
|
+
const eventSource = new EventSource(url)
|
|
195
|
+
|
|
196
|
+
eventSource.onerror = (error) => {
|
|
197
|
+
this.events.emit("error", error)
|
|
198
|
+
eventSource.close()
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
eventSource.onopen = () => {
|
|
202
|
+
console.log(`[UPLOADER] SSE channel opened`)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
eventSource.onmessage = (event) => {
|
|
206
|
+
// parse json
|
|
207
|
+
const messageData = JSON.parse(event.data)
|
|
208
|
+
|
|
209
|
+
console.log(`[UPLOADER] SSE Event >`, messageData)
|
|
210
|
+
|
|
211
|
+
if (messageData.event === "done") {
|
|
212
|
+
this.events.emit("finish", messageData.result)
|
|
213
|
+
eventSource.close()
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (messageData.event === "error") {
|
|
217
|
+
this.events.emit("error", messageData.result)
|
|
218
|
+
eventSource.close()
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (messageData.state) {
|
|
222
|
+
this.events.emit("progress", {
|
|
223
|
+
percent: messageData.percent,
|
|
224
|
+
state: messageData.state,
|
|
225
|
+
})
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
} exports.default = FileUploadBrowser;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }var _FileUploadBrowser = require('../../classes/FileUploadBrowser'); var _FileUploadBrowser2 = _interopRequireDefault(_FileUploadBrowser);
|
|
2
|
+
var _session = require('../session'); var _session2 = _interopRequireDefault(_session);
|
|
3
|
+
|
|
4
|
+
class Files {
|
|
5
|
+
static get chunkUploadEndpoint() {
|
|
6
|
+
return globalThis.__comty_shared_state.mainOrigin + "/upload/chunk"
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static __initStatic() {this.upload = async (
|
|
10
|
+
file,
|
|
11
|
+
{ service, headers, onError, onProgress, onFinish } = {},
|
|
12
|
+
) => {
|
|
13
|
+
try {
|
|
14
|
+
if (globalThis.isServerMode) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
"File Upload is only supported in the browser. Yet...",
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
await new Promise((resolve, reject) => {
|
|
21
|
+
const uploadInstance = new (0, _FileUploadBrowser2.default)({
|
|
22
|
+
endpoint: Files.chunkUploadEndpoint,
|
|
23
|
+
splitChunkSize: 5 * 1024 * 1024,
|
|
24
|
+
file: file,
|
|
25
|
+
service: _nullishCoalesce(service, () => ( "standard")),
|
|
26
|
+
headers: {
|
|
27
|
+
...(_nullishCoalesce(headers, () => ( {}))),
|
|
28
|
+
Authorization: `Bearer ${_session2.default.token}`,
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
uploadInstance.events.on("error", (data) => {
|
|
33
|
+
reject(data)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
uploadInstance.events.on("finish", (data) => {
|
|
37
|
+
if (typeof onFinish === "function") {
|
|
38
|
+
onFinish(file, data)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
resolve(data)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
uploadInstance.events.on("progress", (data) => {
|
|
45
|
+
if (typeof onProgress === "function") {
|
|
46
|
+
onProgress(file, data)
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
uploadInstance.start()
|
|
51
|
+
})
|
|
52
|
+
} catch (error) {
|
|
53
|
+
if (typeof onError === "function") {
|
|
54
|
+
onError(file, error)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}}
|
|
58
|
+
} Files.__initStatic(); exports.default = Files;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _linebridgeclient = require('linebridge-client');
|
|
2
2
|
var _request = require('../../request'); var _request2 = _interopRequireDefault(_request);
|
|
3
3
|
|
|
4
|
-
var _linebridgeclient = require('linebridge-client');
|
|
5
|
-
|
|
6
4
|
var _session = require('../session'); var _session2 = _interopRequireDefault(_session);
|
|
7
5
|
var _user = require('../user'); var _user2 = _interopRequireDefault(_user);
|
|
8
6
|
|