@cocreate/file 1.17.0 → 1.17.2
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 +17 -0
- package/package.json +14 -14
- package/src/client.js +182 -49
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
## [1.17.2](https://github.com/CoCreate-app/CoCreate-file/compare/v1.17.1...v1.17.2) (2024-04-29)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* bump cocreate dependencies ([6034fc5](https://github.com/CoCreate-app/CoCreate-file/commit/6034fc570aade211662c77aaf6d66ea2c11a7340))
|
|
7
|
+
|
|
8
|
+
## [1.17.1](https://github.com/CoCreate-app/CoCreate-file/compare/v1.17.0...v1.17.1) (2024-04-26)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* condition to check input.ProcessFIle exists ([478d652](https://github.com/CoCreate-app/CoCreate-file/commit/478d65274f52ac8c0de9341ee5ca1766e0542f7f))
|
|
14
|
+
* getFiles returns files as is without conversion ([ad57ce3](https://github.com/CoCreate-app/CoCreate-file/commit/ad57ce3895c4246268b49b192d69e2bae09cf0c7))
|
|
15
|
+
* method set to static object.update ([27dbf8e](https://github.com/CoCreate-app/CoCreate-file/commit/27dbf8e717a4bc5ffd5c2f6a6bae28e081e8a7b2))
|
|
16
|
+
* replaced keyword spaces with hyphens and lowercase letters only ([77f9d89](https://github.com/CoCreate-app/CoCreate-file/commit/77f9d896ded45e1341d58faa6973d58198a4e308))
|
|
17
|
+
|
|
1
18
|
# [1.17.0](https://github.com/CoCreate-app/CoCreate-file/compare/v1.16.0...v1.17.0) (2024-03-18)
|
|
2
19
|
|
|
3
20
|
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cocreate/file",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.2",
|
|
4
4
|
"description": "A versatile, configurable headless file uploader supporting both local and server file operations. Accessible via a JavaScript API and HTML5 attributes, it offers seamless file reading, writing, and uploading capabilities with graceful fallbacks to the standard HTML5 file input API. Ideal for developers requiring robust file management in headless or UI-less environments.",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"file
|
|
6
|
+
"file-uploader",
|
|
7
7
|
"headless",
|
|
8
|
-
"
|
|
9
|
-
"server
|
|
10
|
-
"customizable
|
|
11
|
-
"file
|
|
12
|
-
"no
|
|
13
|
-
"background
|
|
14
|
-
"programmatic
|
|
15
|
-
"headless
|
|
8
|
+
"html5-attributes",
|
|
9
|
+
"server-upload",
|
|
10
|
+
"customizable-uploader",
|
|
11
|
+
"file-upload-api",
|
|
12
|
+
"no-ui-upload",
|
|
13
|
+
"background-file-upload",
|
|
14
|
+
"programmatic-file-upload",
|
|
15
|
+
"headless-file-management",
|
|
16
16
|
"cocreate",
|
|
17
17
|
"low-code-framework",
|
|
18
18
|
"cocreatejs",
|
|
@@ -63,9 +63,9 @@
|
|
|
63
63
|
"webpack-log": "^3.0.1"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@cocreate/actions": "^1.
|
|
67
|
-
"@cocreate/config": "^1.
|
|
68
|
-
"@cocreate/render": "^1.
|
|
69
|
-
"@cocreate/utils": "^1.
|
|
66
|
+
"@cocreate/actions": "^1.18.1",
|
|
67
|
+
"@cocreate/config": "^1.12.2",
|
|
68
|
+
"@cocreate/render": "^1.40.3",
|
|
69
|
+
"@cocreate/utils": "^1.33.6"
|
|
70
70
|
}
|
|
71
71
|
}
|
package/src/client.js
CHANGED
|
@@ -150,6 +150,11 @@ async function fileEvent(event) {
|
|
|
150
150
|
|
|
151
151
|
if (!files[i].src)
|
|
152
152
|
await readFile(files[i])
|
|
153
|
+
// if (!files[i].src)
|
|
154
|
+
// files[i].src = files[i]
|
|
155
|
+
|
|
156
|
+
// if (!files[i].src.name)
|
|
157
|
+
// files[i].src = files[i]
|
|
153
158
|
|
|
154
159
|
if (!files[i].size)
|
|
155
160
|
files[i].size = handle.size
|
|
@@ -173,7 +178,7 @@ async function fileEvent(event) {
|
|
|
173
178
|
console.log("Files selected:", selected);
|
|
174
179
|
|
|
175
180
|
if (input.renderValue)
|
|
176
|
-
input.renderValue(Array.from(selected.values()))
|
|
181
|
+
input.renderValue(Array.from(selected.values()));
|
|
177
182
|
|
|
178
183
|
const isImport = input.getAttribute('import')
|
|
179
184
|
const isRealtime = input.getAttribute('realtime')
|
|
@@ -226,7 +231,7 @@ async function getFileId(file) {
|
|
|
226
231
|
}
|
|
227
232
|
}
|
|
228
233
|
|
|
229
|
-
async function getFiles(fileInputs) {
|
|
234
|
+
async function getFiles(fileInputs, readAs) {
|
|
230
235
|
const files = [];
|
|
231
236
|
|
|
232
237
|
if (!Array.isArray(fileInputs))
|
|
@@ -236,8 +241,13 @@ async function getFiles(fileInputs) {
|
|
|
236
241
|
const selected = inputs.get(input)
|
|
237
242
|
if (selected) {
|
|
238
243
|
for (let file of Array.from(selected.values())) {
|
|
239
|
-
if (!file.src)
|
|
240
|
-
|
|
244
|
+
if (!file.src) {
|
|
245
|
+
// if (readAs === 'blob')
|
|
246
|
+
file.src = file
|
|
247
|
+
// else
|
|
248
|
+
// await readFile(file, readAs)
|
|
249
|
+
}
|
|
250
|
+
|
|
241
251
|
let fileObject = { ...file }
|
|
242
252
|
fileObject.size = file.size
|
|
243
253
|
await getCustomData(fileObject)
|
|
@@ -251,6 +261,7 @@ async function getFiles(fileInputs) {
|
|
|
251
261
|
}
|
|
252
262
|
|
|
253
263
|
async function getCustomData(file) {
|
|
264
|
+
// TODO: Consider potential replacment of file_id, perhaps supporting selector
|
|
254
265
|
let form = document.querySelector(`[file_id="${file.id}"]`);
|
|
255
266
|
if (form) {
|
|
256
267
|
let elements = form.querySelectorAll('[file]');
|
|
@@ -268,13 +279,15 @@ async function getCustomData(file) {
|
|
|
268
279
|
}
|
|
269
280
|
|
|
270
281
|
// This function reads the file and returns its src
|
|
271
|
-
function readFile(file) {
|
|
282
|
+
function readFile(file, readAs) {
|
|
272
283
|
return new Promise((resolve) => {
|
|
273
284
|
const fileType = file.type.split('/');
|
|
274
|
-
let readAs;
|
|
275
285
|
|
|
276
286
|
if (fileType[1] === 'directory') {
|
|
277
287
|
return resolve(file)
|
|
288
|
+
} else if (readAs) {
|
|
289
|
+
if (readAs === 'blob')
|
|
290
|
+
return resolve(file)
|
|
278
291
|
} else if (fileType[0] === 'image') {
|
|
279
292
|
readAs = 'readAsDataURL';
|
|
280
293
|
} else if (fileType[0] === 'video') {
|
|
@@ -321,6 +334,7 @@ function setFiles(element, files) {
|
|
|
321
334
|
render({ source: element, data: Array.from(selected.values()) })
|
|
322
335
|
}
|
|
323
336
|
|
|
337
|
+
// TODO: Could this benifit from media processing to save results locally
|
|
324
338
|
async function save(element, action, data) {
|
|
325
339
|
try {
|
|
326
340
|
if (!data)
|
|
@@ -410,26 +424,25 @@ async function upload(element, data) {
|
|
|
410
424
|
element = [element]
|
|
411
425
|
|
|
412
426
|
for (let i = 0; i < element.length; i++) {
|
|
413
|
-
const
|
|
427
|
+
const fileInputs = []
|
|
414
428
|
if (element[i].type === 'file')
|
|
415
|
-
|
|
429
|
+
fileInputs.push(element[i])
|
|
416
430
|
else if (element[i].tagName === 'form') {
|
|
417
|
-
|
|
418
|
-
inputs.push(...fileInputs)
|
|
431
|
+
fileInputs.push(...element[i].querySelectorAll('input[type="file"]'))
|
|
419
432
|
} else {
|
|
420
433
|
const form = element[i].closest('form')
|
|
421
434
|
if (form)
|
|
422
|
-
|
|
435
|
+
fileInputs.push(...form.querySelectorAll('input[type="file"]'))
|
|
423
436
|
}
|
|
424
437
|
|
|
425
|
-
for (let input of
|
|
438
|
+
for (let input of fileInputs) {
|
|
426
439
|
let Data = Elements.getObject(input);
|
|
427
|
-
let
|
|
428
|
-
|
|
429
|
-
Data.type = 'object'
|
|
440
|
+
let object = input.getAttribute('object') || ''
|
|
441
|
+
let key = input.getAttribute('key')
|
|
430
442
|
|
|
431
|
-
Data.
|
|
432
|
-
|
|
443
|
+
Data.broadcastBrowser = false
|
|
444
|
+
Data.method = 'object.update'
|
|
445
|
+
if (!Data.array)
|
|
433
446
|
Data.array = 'files'
|
|
434
447
|
|
|
435
448
|
let path = input.getAttribute('path')
|
|
@@ -438,11 +451,17 @@ async function upload(element, data) {
|
|
|
438
451
|
if (path) {
|
|
439
452
|
directory = path.split('/');
|
|
440
453
|
directory = directory[directory.length - 1];
|
|
441
|
-
if (!path.
|
|
454
|
+
if (!path.endsWith('/'))
|
|
442
455
|
path += '/'
|
|
443
456
|
} else
|
|
444
457
|
path = directory = '/'
|
|
445
458
|
|
|
459
|
+
if (!Data.host)
|
|
460
|
+
Data.host = ['*']
|
|
461
|
+
|
|
462
|
+
if (!Data.public)
|
|
463
|
+
Data.public = true
|
|
464
|
+
|
|
446
465
|
if (input.getFilter) {
|
|
447
466
|
Data.$filter = await input.getFilter()
|
|
448
467
|
if (!Data.$filter.query)
|
|
@@ -453,50 +472,163 @@ async function upload(element, data) {
|
|
|
453
472
|
}
|
|
454
473
|
|
|
455
474
|
|
|
456
|
-
let files = await getFiles(input)
|
|
475
|
+
// let files = await getFiles(input, 'blob')
|
|
476
|
+
let files
|
|
477
|
+
const selected = inputs.get(input)
|
|
478
|
+
if (selected) {
|
|
479
|
+
files = Array.from(selected.values())
|
|
480
|
+
}
|
|
481
|
+
|
|
457
482
|
let segmentSize = 10 * 1024 * 1024
|
|
458
483
|
for (let i = 0; i < files.length; i++) {
|
|
459
484
|
files[i].path = path
|
|
460
|
-
files[i].pathname = path +
|
|
485
|
+
files[i].pathname = path + files[i].name
|
|
461
486
|
files[i].directory = directory
|
|
462
487
|
|
|
488
|
+
// let fileObject = { ...file }
|
|
489
|
+
// fileObject.size = file.size
|
|
490
|
+
// await getCustomData(fileObject)
|
|
491
|
+
|
|
463
492
|
|
|
464
|
-
if (files[i].size > segmentSize) {
|
|
465
|
-
let
|
|
466
|
-
files[i]
|
|
467
|
-
for (let j = 0; j < segments.length; j++) {
|
|
468
|
-
segments[j].path = path
|
|
469
|
-
segments[j].pathname = path + '/' + segments[j].name
|
|
470
|
-
segments[j].directory = directory
|
|
493
|
+
if (input.processFile && files[i].size > segmentSize) {
|
|
494
|
+
// let test = await input.processFile(files[i], null, segmentSize, null, null, null, input);
|
|
495
|
+
let { playlist, segments } = await input.processFile(files[i], null, segmentSize);
|
|
471
496
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
497
|
+
// Create a video element
|
|
498
|
+
const videoElement = document.createElement('video');
|
|
499
|
+
videoElement.setAttribute('controls', ''); // Add controls so you can play/pause
|
|
500
|
+
videoElement.style.width = '100%';
|
|
501
|
+
document.body.appendChild(videoElement);
|
|
502
|
+
|
|
503
|
+
const mediaSource = new MediaSource();
|
|
504
|
+
videoElement.src = URL.createObjectURL(mediaSource);
|
|
505
|
+
|
|
506
|
+
mediaSource.addEventListener('sourceopen', () => {
|
|
507
|
+
const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E"');
|
|
508
|
+
|
|
509
|
+
sourceBuffer.addEventListener('updateend', () => {
|
|
510
|
+
console.log('Append operation completed.');
|
|
511
|
+
try {
|
|
512
|
+
console.log('Buffered ranges:', sourceBuffer.buffered);
|
|
513
|
+
// Append next segment here if applicable
|
|
514
|
+
} catch (e) {
|
|
515
|
+
console.error('Error accessing buffered property:', e);
|
|
516
|
+
}
|
|
477
517
|
});
|
|
478
|
-
}
|
|
479
518
|
|
|
480
|
-
|
|
481
|
-
|
|
519
|
+
function appendSegment(index) {
|
|
520
|
+
if (index >= segments.length) {
|
|
521
|
+
console.log('All segments have been appended.');
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
if (!sourceBuffer.updating) {
|
|
526
|
+
segments[index].src.arrayBuffer().then(arrayBuffer => {
|
|
527
|
+
console.log(`Appending segment ${index}`);
|
|
528
|
+
sourceBuffer.appendBuffer(arrayBuffer);
|
|
529
|
+
// Next segment will be appended on 'updateend' event
|
|
530
|
+
}).catch(error => {
|
|
531
|
+
console.error(`Error reading segment[${index}] as ArrayBuffer:`, error);
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Append the first segment to start
|
|
537
|
+
appendSegmfent(0);
|
|
538
|
+
});
|
|
482
539
|
|
|
483
|
-
let object = input.getAttribute('object')
|
|
484
|
-
if (key) {
|
|
485
|
-
Data[Data.type] = { _id: object, [key]: files }
|
|
486
|
-
} else {
|
|
487
|
-
Data[Data.type] = files
|
|
488
|
-
}
|
|
489
540
|
|
|
490
|
-
|
|
541
|
+
// mediaSource.addEventListener('sourceopen', () => {
|
|
542
|
+
// const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E"'); // avc1.4D401E, avc1.4D401F, avc1.4D4028, avc1.4D4020, avc1.4D4029, avc1.4D402A
|
|
543
|
+
|
|
544
|
+
// // Append the first segment to start
|
|
545
|
+
// if (!sourceBuffer.updating) {
|
|
546
|
+
|
|
547
|
+
// segments[0].src.arrayBuffer().then(arrayBuffer => {
|
|
548
|
+
// sourceBuffer.appendBuffer(arrayBuffer);
|
|
549
|
+
|
|
550
|
+
// // Wait for 3 seconds before logging the sourceBuffer state
|
|
551
|
+
// setTimeout(() => {
|
|
552
|
+
// console.log(sourceBuffer);
|
|
553
|
+
// }, 3000); // 3000 milliseconds = 3 seconds
|
|
554
|
+
|
|
555
|
+
// sourceBuffer.addEventListener('updateend', () => {
|
|
556
|
+
// console.log('Append operation completed.');
|
|
557
|
+
// try {
|
|
558
|
+
// console.log('Buffered ranges:', sourceBuffer.buffered);
|
|
559
|
+
// } catch (e) {
|
|
560
|
+
// console.error('Error accessing buffered property:', e);
|
|
561
|
+
// }
|
|
562
|
+
// // Proceed with additional operations here
|
|
563
|
+
// });
|
|
564
|
+
|
|
565
|
+
// }).catch(error => {
|
|
566
|
+
// console.error('Error reading segment[0] as ArrayBuffer:', error);
|
|
567
|
+
// });
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
// // segments[0].src.arrayBuffer().then(arrayBuffer => {
|
|
571
|
+
// // sourceBuffer.appendBuffer(arrayBuffer);
|
|
572
|
+
// // })
|
|
573
|
+
|
|
574
|
+
// // let segmentLength = 0
|
|
575
|
+
// // sourceBuffer.addEventListener('updateend', () => {
|
|
576
|
+
// // segmentLength += 1
|
|
577
|
+
// // if (segments[segmentLength])
|
|
578
|
+
// // segments[segmentLength].src.arrayBuffer().then(arrayBuffer => {
|
|
579
|
+
// // console.log(sourceBuffer)
|
|
580
|
+
// // // sourceBuffer.appendBuffer(arrayBuffer);
|
|
581
|
+
// // })
|
|
582
|
+
// // });
|
|
583
|
+
// }
|
|
584
|
+
// });
|
|
585
|
+
|
|
586
|
+
}
|
|
491
587
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
588
|
+
// files[i].src = playlist
|
|
589
|
+
// for (let j = 0; j < segments.length; j++) {
|
|
590
|
+
// segments[j].path = path
|
|
591
|
+
// segments[j].pathname = path + segments[j].name
|
|
592
|
+
// segments[j].directory = directory
|
|
593
|
+
// segments[j] = { ...segments[j], ...await readFile(segments[j].src) }
|
|
594
|
+
// segments[j].public = true
|
|
595
|
+
// segments[j].host = ['*']
|
|
596
|
+
|
|
597
|
+
// playlist.segments[j].src = segments[j].pathname
|
|
598
|
+
// Data.$filter.query.pathname = segments[j].pathname
|
|
599
|
+
// Crud.send({
|
|
600
|
+
// ...Data,
|
|
601
|
+
// object: segments[j],
|
|
602
|
+
// upsert: true
|
|
603
|
+
// });
|
|
604
|
+
// }
|
|
605
|
+
|
|
606
|
+
// } else {
|
|
607
|
+
// files[i] = { ...files[i], ...await readFile(files[i].src) }
|
|
608
|
+
// }
|
|
609
|
+
|
|
610
|
+
// if (!key) {
|
|
611
|
+
// Data.object = { ...files[i] }
|
|
612
|
+
// } else {
|
|
613
|
+
// Data.object = { [key]: { ...files[i] } }
|
|
614
|
+
// }
|
|
615
|
+
|
|
616
|
+
// if (object) {
|
|
617
|
+
// Data.object._id = object // test
|
|
618
|
+
// }
|
|
619
|
+
|
|
620
|
+
// delete Data.object.input
|
|
621
|
+
// Data.$filter.query.pathname = files[i].pathname
|
|
622
|
+
// let response = await Crud.send({
|
|
623
|
+
// ...Data,
|
|
624
|
+
// upsert: true
|
|
625
|
+
// });
|
|
626
|
+
|
|
627
|
+
// console.log(response, 'tes')
|
|
628
|
+
// if (response && (!object || object !== response.object)) {
|
|
629
|
+
// Elements.setTypeValue(element, response);
|
|
630
|
+
// }
|
|
496
631
|
|
|
497
|
-
data.push(response)
|
|
498
|
-
if (response && (!object || object !== response.object)) {
|
|
499
|
-
Elements.setTypeValue(element, response);
|
|
500
632
|
}
|
|
501
633
|
}
|
|
502
634
|
|
|
@@ -560,6 +692,7 @@ async function Import(element, data) {
|
|
|
560
692
|
|
|
561
693
|
if (data.length) {
|
|
562
694
|
for (let i = 0; i < data.length; i++) {
|
|
695
|
+
// TODO: if _id exist use update method
|
|
563
696
|
data[i].method = data[i].type + '.create'
|
|
564
697
|
data[i] = await Crud.send(data[i])
|
|
565
698
|
}
|