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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "comty.js",
3
- "version": "0.65.5",
3
+ "version": "0.66.0",
4
4
  "main": "./dist/index.js",
5
5
  "description": "Official Comty API for JavaScript",
6
6
  "homepage": "https://github.com/ragestudio/comty.js",