@weapnl/js-junction 0.1.4 → 0.3.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.
- package/CHANGELOG.md +8 -0
- package/README.md +20 -0
- package/dist/index.js +124 -25
- package/index.d.ts +3 -2
- package/package.json +1 -1
- package/src/api.js +15 -0
- package/src/builder/model.js +75 -10
- package/src/connection.js +8 -4
- package/src/request.js +4 -1
package/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ declare class Api {
|
|
|
9
9
|
constructor();
|
|
10
10
|
|
|
11
11
|
host(host: string): this;
|
|
12
|
+
chunkUploadsBySize(bytes: number): this;
|
|
12
13
|
suffix(suffix: string): this;
|
|
13
14
|
readonly baseUrl: string;
|
|
14
15
|
|
|
@@ -80,7 +81,7 @@ declare class Request extends Mixins {
|
|
|
80
81
|
post(data?: object): Promise<this>;
|
|
81
82
|
put(data?: object): Promise<this>;
|
|
82
83
|
setKey(key: string): this;
|
|
83
|
-
delete(): Promise<this>;
|
|
84
|
+
delete(data?: object): Promise<this>;
|
|
84
85
|
storeFiles(files?: object, data?: object, url?: string|null): Promise<this>;
|
|
85
86
|
readonly bodyParameters: object;
|
|
86
87
|
onSuccess<T = any>(callback?: (result: T, data: any, response: Response) => void): this;
|
|
@@ -126,7 +127,7 @@ export class Model extends Request {
|
|
|
126
127
|
|
|
127
128
|
update(extraData?: JsonMap): Promise<Model>;
|
|
128
129
|
|
|
129
|
-
destroy(): Promise<boolean>;
|
|
130
|
+
destroy(extraData?: JsonMap): Promise<boolean>;
|
|
130
131
|
|
|
131
132
|
save(extraData?: JsonMap): Promise<Model>;
|
|
132
133
|
|
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -12,6 +12,7 @@ export default class Api {
|
|
|
12
12
|
this.setHeader('X-Requested-With', 'XMLHttpRequest');
|
|
13
13
|
|
|
14
14
|
this._requests = [];
|
|
15
|
+
this._chunkUploadSize = null;
|
|
15
16
|
|
|
16
17
|
this.host('/').suffix('');
|
|
17
18
|
|
|
@@ -29,6 +30,20 @@ export default class Api {
|
|
|
29
30
|
return this;
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Chunk file uploads into multiple requests when total size exceeds the given size.
|
|
35
|
+
* Useful when the API has a max upload limit, or to split large batches into smaller requests.
|
|
36
|
+
*
|
|
37
|
+
* @param {number} bytes Maximum total file size per request in bytes.
|
|
38
|
+
*
|
|
39
|
+
* @returns {this} The current instance.
|
|
40
|
+
*/
|
|
41
|
+
chunkUploadsBySize (bytes) {
|
|
42
|
+
this._chunkUploadSize = bytes;
|
|
43
|
+
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
|
|
32
47
|
/**
|
|
33
48
|
* @param {string} suffix
|
|
34
49
|
*
|
package/src/builder/model.js
CHANGED
|
@@ -202,7 +202,12 @@ export default class Model extends Request {
|
|
|
202
202
|
|
|
203
203
|
this._response = await this._connection.post(
|
|
204
204
|
this._queryString(),
|
|
205
|
-
{
|
|
205
|
+
{
|
|
206
|
+
...this._attributes.toJson(this),
|
|
207
|
+
...this._mediaCollections.toJson(this),
|
|
208
|
+
..._.merge(...this._customParameters),
|
|
209
|
+
...extraData,
|
|
210
|
+
},
|
|
206
211
|
);
|
|
207
212
|
|
|
208
213
|
this._connection.removeRequest(this);
|
|
@@ -234,7 +239,12 @@ export default class Model extends Request {
|
|
|
234
239
|
|
|
235
240
|
this._response = await this._connection.put(
|
|
236
241
|
this._queryString(this._identifier),
|
|
237
|
-
{
|
|
242
|
+
{
|
|
243
|
+
...this._attributes.toJson(this),
|
|
244
|
+
...this._mediaCollections.toJson(this),
|
|
245
|
+
..._.merge(...this._customParameters),
|
|
246
|
+
...extraData,
|
|
247
|
+
},
|
|
238
248
|
);
|
|
239
249
|
|
|
240
250
|
this._connection.removeRequest(this);
|
|
@@ -257,13 +267,19 @@ export default class Model extends Request {
|
|
|
257
267
|
/**
|
|
258
268
|
* Delete the current model.
|
|
259
269
|
*
|
|
270
|
+
* @param {Object} [extraData] Extra data to send to the API
|
|
271
|
+
*
|
|
260
272
|
* @returns {boolean} Whether the deletion was successful.
|
|
261
273
|
*/
|
|
262
|
-
async destroy () {
|
|
274
|
+
async destroy (extraData = {}) {
|
|
263
275
|
this._connection.cancelRunning(this);
|
|
264
276
|
|
|
265
277
|
this._response = await this._connection.delete(
|
|
266
278
|
this._queryString(this._identifier),
|
|
279
|
+
{
|
|
280
|
+
..._.merge(...this._customParameters),
|
|
281
|
+
...extraData,
|
|
282
|
+
},
|
|
267
283
|
);
|
|
268
284
|
|
|
269
285
|
this._connection.removeRequest(this);
|
|
@@ -286,20 +302,69 @@ export default class Model extends Request {
|
|
|
286
302
|
*/
|
|
287
303
|
async upload (files, collection) {
|
|
288
304
|
this._media ??= {};
|
|
289
|
-
|
|
305
|
+
files = _.flatMapDeep(Array.isArray(files) ? files : [files]).filter((value) => value instanceof File);
|
|
290
306
|
|
|
291
|
-
if (
|
|
307
|
+
if (files.length === 0) {
|
|
292
308
|
this._media[collection] = {};
|
|
293
309
|
return;
|
|
294
310
|
}
|
|
295
311
|
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
|
|
312
|
+
const chunkSize = this._connection.getChunkUploadSize();
|
|
313
|
+
|
|
314
|
+
const chunks = chunkSize ? this._chunkFilesBySize(files, chunkSize) : [files];
|
|
315
|
+
|
|
316
|
+
let allResponseData = [];
|
|
317
|
+
|
|
318
|
+
for (const chunk of chunks) {
|
|
319
|
+
const request = await this.storeFiles({
|
|
320
|
+
files: chunk,
|
|
321
|
+
}, {}, '/media/upload');
|
|
322
|
+
|
|
323
|
+
if (request._response.data) {
|
|
324
|
+
allResponseData = allResponseData.concat(
|
|
325
|
+
_.castArray(request._response.data),
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
this._media[collection] = allResponseData;
|
|
331
|
+
|
|
332
|
+
return allResponseData;
|
|
333
|
+
}
|
|
299
334
|
|
|
300
|
-
|
|
335
|
+
/**
|
|
336
|
+
* Split files into chunks that don't exceed the given max size.
|
|
337
|
+
* A single file that exceeds the limit will still be sent as its own chunk.
|
|
338
|
+
*
|
|
339
|
+
* @param {File[]} files
|
|
340
|
+
* @param {number} maxSize Maximum total file size per chunk in bytes.
|
|
341
|
+
*
|
|
342
|
+
* @returns {File[][]} Array of file arrays (chunks).
|
|
343
|
+
* @private
|
|
344
|
+
*/
|
|
345
|
+
_chunkFilesBySize (files, maxSize) {
|
|
346
|
+
const chunks = [];
|
|
347
|
+
let currentChunk = [];
|
|
348
|
+
let currentSize = 0;
|
|
349
|
+
|
|
350
|
+
for (const file of files) {
|
|
351
|
+
const fileSize = file.size || 0;
|
|
352
|
+
|
|
353
|
+
if (currentChunk.length > 0 && currentSize + fileSize > maxSize) {
|
|
354
|
+
chunks.push(currentChunk);
|
|
355
|
+
currentChunk = [];
|
|
356
|
+
currentSize = 0;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
currentChunk.push(file);
|
|
360
|
+
currentSize += fileSize;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (currentChunk.length > 0) {
|
|
364
|
+
chunks.push(currentChunk);
|
|
365
|
+
}
|
|
301
366
|
|
|
302
|
-
return
|
|
367
|
+
return chunks;
|
|
303
368
|
}
|
|
304
369
|
|
|
305
370
|
/**
|
package/src/connection.js
CHANGED
|
@@ -33,6 +33,10 @@ export default class Connection {
|
|
|
33
33
|
return this._config;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
getChunkUploadSize () {
|
|
37
|
+
return this._api?._chunkUploadSize ?? null;
|
|
38
|
+
}
|
|
39
|
+
|
|
36
40
|
setConfig (config) {
|
|
37
41
|
this._config = config;
|
|
38
42
|
}
|
|
@@ -49,12 +53,12 @@ export default class Connection {
|
|
|
49
53
|
return this._execute(query, 'post', data);
|
|
50
54
|
}
|
|
51
55
|
|
|
52
|
-
async put (query,
|
|
53
|
-
return this._execute(query, 'put',
|
|
56
|
+
async put (query, data) {
|
|
57
|
+
return this._execute(query, 'put', data);
|
|
54
58
|
}
|
|
55
59
|
|
|
56
|
-
async delete (query) {
|
|
57
|
-
return this._execute(query, 'delete');
|
|
60
|
+
async delete (query, data) {
|
|
61
|
+
return this._execute(query, 'delete', data);
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
async _execute (url, method, data) {
|
package/src/request.js
CHANGED
|
@@ -150,15 +150,18 @@ export default class Request {
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
/**
|
|
153
|
+
* @param {Object} data
|
|
154
|
+
*
|
|
153
155
|
* @returns {this} The current instance.
|
|
154
156
|
*/
|
|
155
|
-
async delete () {
|
|
157
|
+
async delete (data = {}) {
|
|
156
158
|
const url = this.url ?? this.constructor.endpoint;
|
|
157
159
|
|
|
158
160
|
this._connection.cancelRunning(this);
|
|
159
161
|
|
|
160
162
|
this._response = await this._connection.delete(
|
|
161
163
|
url,
|
|
164
|
+
{ ...data, ...this.bodyParameters },
|
|
162
165
|
);
|
|
163
166
|
|
|
164
167
|
this._connection.removeRequest(this);
|