@atlaskit/media-client 28.6.0 → 29.0.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 +9 -0
- package/dist/cjs/client/file-fetcher/index.js +99 -53
- package/dist/cjs/client/media-store/MediaStore.js +24 -21
- package/dist/cjs/utils/createCopyIntentRegisterationBatcher.js +123 -0
- package/dist/es2019/client/file-fetcher/index.js +22 -0
- package/dist/es2019/client/media-store/MediaStore.js +6 -11
- package/dist/es2019/utils/createCopyIntentRegisterationBatcher.js +75 -0
- package/dist/esm/client/file-fetcher/index.js +99 -53
- package/dist/esm/client/media-store/MediaStore.js +24 -21
- package/dist/esm/utils/createCopyIntentRegisterationBatcher.js +115 -0
- package/dist/types/client/file-fetcher/index.d.ts +3 -0
- package/dist/types/client/media-store/MediaStore.d.ts +4 -1
- package/dist/types/client/media-store/types.d.ts +5 -1
- package/dist/types/utils/createCopyIntentRegisterationBatcher.d.ts +20 -0
- package/dist/types-ts4.5/client/file-fetcher/index.d.ts +3 -0
- package/dist/types-ts4.5/client/media-store/MediaStore.d.ts +4 -1
- package/dist/types-ts4.5/client/media-store/types.d.ts +5 -1
- package/dist/types-ts4.5/utils/createCopyIntentRegisterationBatcher.d.ts +20 -0
- package/package.json +4 -4
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import Dataloader from 'dataloader';
|
|
2
|
+
import { getRandomHex } from '@atlaskit/media-common';
|
|
3
|
+
export const MAX_BATCH_SIZE = 100;
|
|
4
|
+
/**
|
|
5
|
+
* Returns a function that, given Array<DataloaderKey>, resolves to an array of same length containing either DataloaderResult or Error.
|
|
6
|
+
* Such contract is formalised by Dataloader 1.0, @see https://github.com/graphql/dataloader
|
|
7
|
+
*
|
|
8
|
+
* If an Error is resolved in the results, it must be at same position then their corresponding key:
|
|
9
|
+
* - Dataloader will re-throw that Error when accessing/loading that particular key
|
|
10
|
+
*
|
|
11
|
+
* @param mediaStore instance of MediaStore
|
|
12
|
+
*/
|
|
13
|
+
function createBatchCopyIntentRegisterationFunc(mediaStore) {
|
|
14
|
+
return async keys => {
|
|
15
|
+
const keysByToken = keys.reduce((acc, key) => {
|
|
16
|
+
const token = key.resolvedAuth.token;
|
|
17
|
+
acc[token] = acc[token] || [];
|
|
18
|
+
|
|
19
|
+
// de-duplicate ids in collection
|
|
20
|
+
const hasDuplicates = acc[token].some(({
|
|
21
|
+
id,
|
|
22
|
+
collectionName
|
|
23
|
+
}) => key.id === id && collectionName === key.collectionName);
|
|
24
|
+
if (!hasDuplicates) {
|
|
25
|
+
acc[token].push(key);
|
|
26
|
+
}
|
|
27
|
+
return acc;
|
|
28
|
+
}, {});
|
|
29
|
+
const items = [];
|
|
30
|
+
await Promise.all(Object.keys(keysByToken).map(async batchKey => {
|
|
31
|
+
const metadataTraceContext = {
|
|
32
|
+
traceId: getRandomHex(8),
|
|
33
|
+
spanId: getRandomHex(8)
|
|
34
|
+
};
|
|
35
|
+
const files = keysByToken[batchKey].map(key => ({
|
|
36
|
+
id: key.id,
|
|
37
|
+
collection: key.collectionName
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
// given these are batched by the token the assumption is that they have the same details.
|
|
41
|
+
const resolvedAuth = keysByToken[batchKey][0].resolvedAuth;
|
|
42
|
+
try {
|
|
43
|
+
await mediaStore.registerCopyIntents(files, metadataTraceContext, resolvedAuth);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
files.forEach(({
|
|
46
|
+
id,
|
|
47
|
+
collection
|
|
48
|
+
}) => {
|
|
49
|
+
items.push({
|
|
50
|
+
id,
|
|
51
|
+
collection,
|
|
52
|
+
error: error
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}));
|
|
57
|
+
return keys.map(({
|
|
58
|
+
id,
|
|
59
|
+
collectionName
|
|
60
|
+
}) => {
|
|
61
|
+
var _items$find;
|
|
62
|
+
return (_items$find = items.find(item => item.id === id && item.collection === collectionName)) === null || _items$find === void 0 ? void 0 : _items$find.error;
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function createCopyIntentRegisterationBatcher(mediaStore) {
|
|
67
|
+
return new Dataloader(createBatchCopyIntentRegisterationFunc(mediaStore), {
|
|
68
|
+
maxBatchSize: MAX_BATCH_SIZE,
|
|
69
|
+
cacheKeyFn: ({
|
|
70
|
+
id,
|
|
71
|
+
collectionName = 'default',
|
|
72
|
+
resolvedAuth
|
|
73
|
+
}) => `${id}-${collectionName}-${resolvedAuth.token}`
|
|
74
|
+
});
|
|
75
|
+
}
|
|
@@ -34,6 +34,8 @@ import { shouldFetchRemoteFileStates } from '../../utils/shouldFetchRemoteFileSt
|
|
|
34
34
|
import { PollingFunction } from '../../utils/polling';
|
|
35
35
|
import { isEmptyFile } from '../../utils/detectEmptyFile';
|
|
36
36
|
import { mediaStore } from '@atlaskit/media-state';
|
|
37
|
+
import { createCopyIntentRegisterationBatcher } from '../../utils/createCopyIntentRegisterationBatcher';
|
|
38
|
+
import { defaultShouldRetryError } from '../../utils/request/helpers';
|
|
37
39
|
export { isFileFetcherError, FileFetcherError } from './error';
|
|
38
40
|
var isCopySourceFileWithToken = function isCopySourceFileWithToken(token) {
|
|
39
41
|
return !!token.authProvider;
|
|
@@ -171,6 +173,7 @@ export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
171
173
|
this.mediaApi = mediaApi;
|
|
172
174
|
this.store = store;
|
|
173
175
|
this.dataloader = createFileDataloader(mediaApi);
|
|
176
|
+
this.copyIntentRegisterationBatcher = createCopyIntentRegisterationBatcher(mediaApi);
|
|
174
177
|
}
|
|
175
178
|
return _createClass(FileFetcherImpl, [{
|
|
176
179
|
key: "getFileState",
|
|
@@ -502,26 +505,69 @@ export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
502
505
|
return downloadBinary;
|
|
503
506
|
}()
|
|
504
507
|
}, {
|
|
505
|
-
key: "
|
|
508
|
+
key: "registerCopyIntent",
|
|
506
509
|
value: function () {
|
|
507
|
-
var
|
|
508
|
-
var
|
|
510
|
+
var _registerCopyIntent = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(id, collectionName) {
|
|
511
|
+
var auth, key, error;
|
|
509
512
|
return _regeneratorRuntime.wrap(function _callee6$(_context6) {
|
|
510
513
|
while (1) switch (_context6.prev = _context6.next) {
|
|
514
|
+
case 0:
|
|
515
|
+
_context6.next = 2;
|
|
516
|
+
return this.mediaApi.resolveAuth({
|
|
517
|
+
collectionName: collectionName
|
|
518
|
+
});
|
|
519
|
+
case 2:
|
|
520
|
+
auth = _context6.sent;
|
|
521
|
+
key = {
|
|
522
|
+
id: id,
|
|
523
|
+
collectionName: collectionName,
|
|
524
|
+
resolvedAuth: auth
|
|
525
|
+
};
|
|
526
|
+
_context6.next = 6;
|
|
527
|
+
return this.copyIntentRegisterationBatcher.load(key);
|
|
528
|
+
case 6:
|
|
529
|
+
error = _context6.sent;
|
|
530
|
+
if (!error) {
|
|
531
|
+
_context6.next = 10;
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
// if the error is retryable then it should not be cached
|
|
535
|
+
if (defaultShouldRetryError(error)) {
|
|
536
|
+
this.copyIntentRegisterationBatcher.clear(key);
|
|
537
|
+
}
|
|
538
|
+
throw error;
|
|
539
|
+
case 10:
|
|
540
|
+
case "end":
|
|
541
|
+
return _context6.stop();
|
|
542
|
+
}
|
|
543
|
+
}, _callee6, this);
|
|
544
|
+
}));
|
|
545
|
+
function registerCopyIntent(_x9, _x10) {
|
|
546
|
+
return _registerCopyIntent.apply(this, arguments);
|
|
547
|
+
}
|
|
548
|
+
return registerCopyIntent;
|
|
549
|
+
}()
|
|
550
|
+
}, {
|
|
551
|
+
key: "copyFileWithToken",
|
|
552
|
+
value: function () {
|
|
553
|
+
var _copyFileWithToken = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee7(source, destination, traceContext) {
|
|
554
|
+
var authProvider, sourceCollection, id, destinationAuthProvider, destinationCollectionName, replaceFileId, occurrenceKey, mediaStore, owner, body, params, _yield$mediaStore$cop, data;
|
|
555
|
+
return _regeneratorRuntime.wrap(function _callee7$(_context7) {
|
|
556
|
+
while (1) switch (_context7.prev = _context7.next) {
|
|
511
557
|
case 0:
|
|
512
558
|
authProvider = source.authProvider, sourceCollection = source.collection, id = source.id;
|
|
513
559
|
destinationAuthProvider = destination.authProvider, destinationCollectionName = destination.collection, replaceFileId = destination.replaceFileId, occurrenceKey = destination.occurrenceKey;
|
|
514
560
|
mediaStore = destination.mediaStore || new MediaApi({
|
|
515
561
|
authProvider: destinationAuthProvider
|
|
516
562
|
});
|
|
517
|
-
|
|
518
|
-
|
|
563
|
+
_context7.t0 = authToOwner;
|
|
564
|
+
_context7.next = 6;
|
|
519
565
|
return authProvider({
|
|
520
566
|
collectionName: sourceCollection
|
|
521
567
|
});
|
|
522
568
|
case 6:
|
|
523
|
-
|
|
524
|
-
owner = (0,
|
|
569
|
+
_context7.t1 = _context7.sent;
|
|
570
|
+
owner = (0, _context7.t0)(_context7.t1);
|
|
525
571
|
body = {
|
|
526
572
|
sourceFile: {
|
|
527
573
|
id: id,
|
|
@@ -534,19 +580,19 @@ export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
534
580
|
replaceFileId: replaceFileId,
|
|
535
581
|
occurrenceKey: occurrenceKey
|
|
536
582
|
};
|
|
537
|
-
|
|
583
|
+
_context7.next = 12;
|
|
538
584
|
return mediaStore.copyFileWithToken(body, params, traceContext);
|
|
539
585
|
case 12:
|
|
540
|
-
_yield$mediaStore$cop =
|
|
586
|
+
_yield$mediaStore$cop = _context7.sent;
|
|
541
587
|
data = _yield$mediaStore$cop.data;
|
|
542
|
-
return
|
|
588
|
+
return _context7.abrupt("return", data);
|
|
543
589
|
case 15:
|
|
544
590
|
case "end":
|
|
545
|
-
return
|
|
591
|
+
return _context7.stop();
|
|
546
592
|
}
|
|
547
|
-
},
|
|
593
|
+
}, _callee7);
|
|
548
594
|
}));
|
|
549
|
-
function copyFileWithToken(
|
|
595
|
+
function copyFileWithToken(_x11, _x12, _x13) {
|
|
550
596
|
return _copyFileWithToken.apply(this, arguments);
|
|
551
597
|
}
|
|
552
598
|
return copyFileWithToken;
|
|
@@ -554,28 +600,28 @@ export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
554
600
|
}, {
|
|
555
601
|
key: "copyFileWithIntent",
|
|
556
602
|
value: function () {
|
|
557
|
-
var _copyFileWithIntent = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
603
|
+
var _copyFileWithIntent = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee8(source, destination, traceContext) {
|
|
558
604
|
var res, data;
|
|
559
|
-
return _regeneratorRuntime.wrap(function
|
|
560
|
-
while (1) switch (
|
|
605
|
+
return _regeneratorRuntime.wrap(function _callee8$(_context8) {
|
|
606
|
+
while (1) switch (_context8.prev = _context8.next) {
|
|
561
607
|
case 0:
|
|
562
|
-
|
|
608
|
+
_context8.next = 2;
|
|
563
609
|
return this.mediaApi.copyFile(source.id, {
|
|
564
610
|
sourceCollection: source.collection,
|
|
565
611
|
collection: destination.collection,
|
|
566
612
|
replaceFileId: destination.replaceFileId
|
|
567
613
|
}, traceContext);
|
|
568
614
|
case 2:
|
|
569
|
-
res =
|
|
615
|
+
res = _context8.sent;
|
|
570
616
|
data = res.data;
|
|
571
|
-
return
|
|
617
|
+
return _context8.abrupt("return", data);
|
|
572
618
|
case 5:
|
|
573
619
|
case "end":
|
|
574
|
-
return
|
|
620
|
+
return _context8.stop();
|
|
575
621
|
}
|
|
576
|
-
},
|
|
622
|
+
}, _callee8, this);
|
|
577
623
|
}));
|
|
578
|
-
function copyFileWithIntent(
|
|
624
|
+
function copyFileWithIntent(_x14, _x15, _x16) {
|
|
579
625
|
return _copyFileWithIntent.apply(this, arguments);
|
|
580
626
|
}
|
|
581
627
|
return copyFileWithIntent;
|
|
@@ -583,7 +629,7 @@ export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
583
629
|
}, {
|
|
584
630
|
key: "copyFile",
|
|
585
631
|
value: function () {
|
|
586
|
-
var _copyFile = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
632
|
+
var _copyFile = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9(source, destination) {
|
|
587
633
|
var _this5 = this;
|
|
588
634
|
var options,
|
|
589
635
|
traceContext,
|
|
@@ -610,32 +656,32 @@ export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
610
656
|
replaceFileState,
|
|
611
657
|
key,
|
|
612
658
|
errorFileState,
|
|
613
|
-
|
|
614
|
-
return _regeneratorRuntime.wrap(function
|
|
615
|
-
while (1) switch (
|
|
659
|
+
_args9 = arguments;
|
|
660
|
+
return _regeneratorRuntime.wrap(function _callee9$(_context9) {
|
|
661
|
+
while (1) switch (_context9.prev = _context9.next) {
|
|
616
662
|
case 0:
|
|
617
|
-
options =
|
|
618
|
-
traceContext =
|
|
663
|
+
options = _args9.length > 2 && _args9[2] !== undefined ? _args9[2] : {};
|
|
664
|
+
traceContext = _args9.length > 3 ? _args9[3] : undefined;
|
|
619
665
|
id = source.id;
|
|
620
666
|
destinationCollectionName = destination.collection, replaceFileId = destination.replaceFileId, occurrenceKey = destination.occurrenceKey;
|
|
621
667
|
preview = options.preview, mimeType = options.mimeType;
|
|
622
668
|
cache = getFileStreamsCache();
|
|
623
|
-
|
|
669
|
+
_context9.prev = 6;
|
|
624
670
|
if (!(isCopySourceFileWithToken(source) && isCopyDestinationWithToken(destination))) {
|
|
625
|
-
|
|
671
|
+
_context9.next = 13;
|
|
626
672
|
break;
|
|
627
673
|
}
|
|
628
|
-
|
|
674
|
+
_context9.next = 10;
|
|
629
675
|
return this.copyFileWithToken(source, destination, traceContext);
|
|
630
676
|
case 10:
|
|
631
|
-
copiedFile =
|
|
632
|
-
|
|
677
|
+
copiedFile = _context9.sent;
|
|
678
|
+
_context9.next = 16;
|
|
633
679
|
break;
|
|
634
680
|
case 13:
|
|
635
|
-
|
|
681
|
+
_context9.next = 15;
|
|
636
682
|
return this.copyFileWithIntent(source, destination, traceContext);
|
|
637
683
|
case 15:
|
|
638
|
-
copiedFile =
|
|
684
|
+
copiedFile = _context9.sent;
|
|
639
685
|
case 16:
|
|
640
686
|
// if we were passed a "mimeType", we propagate it into copiedFileWithMimeType
|
|
641
687
|
copiedFileWithMimeType = _objectSpread(_objectSpread({}, copiedFile), mimeType ? {
|
|
@@ -652,21 +698,21 @@ export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
652
698
|
previewOverride = !isErrorFileState(copiedFileState) && !!preview ? {
|
|
653
699
|
preview: preview
|
|
654
700
|
} : {};
|
|
655
|
-
|
|
701
|
+
_context9.t0 = !isFinalFileState(copiedFileState) &&
|
|
656
702
|
// mimeType should always be returned by "copyFileWithToken"
|
|
657
703
|
// but in case it's not, we don't want to penalize "copyFile"
|
|
658
704
|
copiedMimeType;
|
|
659
|
-
if (!
|
|
660
|
-
|
|
705
|
+
if (!_context9.t0) {
|
|
706
|
+
_context9.next = 28;
|
|
661
707
|
break;
|
|
662
708
|
}
|
|
663
|
-
|
|
709
|
+
_context9.next = 27;
|
|
664
710
|
return shouldFetchRemoteFileStates(mediaType, copiedMimeType, preview);
|
|
665
711
|
case 27:
|
|
666
|
-
|
|
712
|
+
_context9.t0 = _context9.sent;
|
|
667
713
|
case 28:
|
|
668
|
-
if (!
|
|
669
|
-
|
|
714
|
+
if (!_context9.t0) {
|
|
715
|
+
_context9.next = 35;
|
|
670
716
|
break;
|
|
671
717
|
}
|
|
672
718
|
fileState = _objectSpread(_objectSpread(_objectSpread({}, copiedFileState), overrideMediaTypeIfUnknown(copiedFileState, mediaType)), previewOverride);
|
|
@@ -687,7 +733,7 @@ export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
687
733
|
return subject.complete();
|
|
688
734
|
}
|
|
689
735
|
});
|
|
690
|
-
|
|
736
|
+
_context9.next = 36;
|
|
691
737
|
break;
|
|
692
738
|
case 35:
|
|
693
739
|
if (!isProcessingFileState(copiedFileState)) {
|
|
@@ -699,10 +745,10 @@ export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
699
745
|
if (!cache.has(copiedId)) {
|
|
700
746
|
getFileStreamsCache().set(copiedId, subject);
|
|
701
747
|
}
|
|
702
|
-
return
|
|
748
|
+
return _context9.abrupt("return", copiedFile);
|
|
703
749
|
case 40:
|
|
704
|
-
|
|
705
|
-
|
|
750
|
+
_context9.prev = 40;
|
|
751
|
+
_context9.t1 = _context9["catch"](6);
|
|
706
752
|
if (processingSubscription) {
|
|
707
753
|
processingSubscription.unsubscribe();
|
|
708
754
|
}
|
|
@@ -710,23 +756,23 @@ export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
710
756
|
_fileCache = cache.get(replaceFileId);
|
|
711
757
|
replaceFileState = this.store.getState().files[replaceFileId];
|
|
712
758
|
if (_fileCache) {
|
|
713
|
-
_fileCache.error(
|
|
759
|
+
_fileCache.error(_context9.t1);
|
|
714
760
|
} else {
|
|
715
761
|
// Create a new subject with the error state for new subscriptions
|
|
716
|
-
cache.set(id, createMediaSubject(
|
|
762
|
+
cache.set(id, createMediaSubject(_context9.t1));
|
|
717
763
|
}
|
|
718
764
|
key = replaceFileState ? replaceFileId : id;
|
|
719
|
-
errorFileState = this.getErrorFileState(
|
|
765
|
+
errorFileState = this.getErrorFileState(_context9.t1, id, occurrenceKey);
|
|
720
766
|
this.setFileState(key, errorFileState);
|
|
721
767
|
}
|
|
722
|
-
throw
|
|
768
|
+
throw _context9.t1;
|
|
723
769
|
case 45:
|
|
724
770
|
case "end":
|
|
725
|
-
return
|
|
771
|
+
return _context9.stop();
|
|
726
772
|
}
|
|
727
|
-
},
|
|
773
|
+
}, _callee9, this, [[6, 40]]);
|
|
728
774
|
}));
|
|
729
|
-
function copyFile(
|
|
775
|
+
function copyFile(_x17, _x18) {
|
|
730
776
|
return _copyFile.apply(this, arguments);
|
|
731
777
|
}
|
|
732
778
|
return copyFile;
|
|
@@ -618,34 +618,26 @@ export var MediaStore = /*#__PURE__*/function () {
|
|
|
618
618
|
}, {
|
|
619
619
|
key: "registerCopyIntents",
|
|
620
620
|
value: function () {
|
|
621
|
-
var _registerCopyIntents = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee12(
|
|
622
|
-
var
|
|
621
|
+
var _registerCopyIntents = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee12(files, traceContext, resolvedAuth) {
|
|
622
|
+
var metadata, options;
|
|
623
623
|
return _regeneratorRuntime.wrap(function _callee12$(_context12) {
|
|
624
624
|
while (1) switch (_context12.prev = _context12.next) {
|
|
625
625
|
case 0:
|
|
626
|
-
files = ids.map(function (id) {
|
|
627
|
-
return {
|
|
628
|
-
id: id,
|
|
629
|
-
collection: collectionName
|
|
630
|
-
};
|
|
631
|
-
});
|
|
632
626
|
metadata = {
|
|
633
627
|
method: 'POST',
|
|
634
628
|
endpoint: '/file/copy/intents'
|
|
635
629
|
};
|
|
636
630
|
options = _objectSpread(_objectSpread({}, metadata), {}, {
|
|
637
|
-
authContext: {
|
|
638
|
-
collectionName: collectionName
|
|
639
|
-
},
|
|
640
631
|
headers: jsonHeaders,
|
|
641
632
|
body: JSON.stringify({
|
|
642
633
|
files: files
|
|
643
634
|
}),
|
|
644
|
-
traceContext: traceContext
|
|
635
|
+
traceContext: traceContext,
|
|
636
|
+
resolvedAuth: resolvedAuth
|
|
645
637
|
});
|
|
646
|
-
_context12.next =
|
|
638
|
+
_context12.next = 4;
|
|
647
639
|
return this.request('/file/copy/intents', options);
|
|
648
|
-
case
|
|
640
|
+
case 4:
|
|
649
641
|
case "end":
|
|
650
642
|
return _context12.stop();
|
|
651
643
|
}
|
|
@@ -672,6 +664,7 @@ export var MediaStore = /*#__PURE__*/function () {
|
|
|
672
664
|
clientOptions,
|
|
673
665
|
traceContext,
|
|
674
666
|
addMediaClientParam,
|
|
667
|
+
resolvedAuth,
|
|
675
668
|
auth,
|
|
676
669
|
clientId,
|
|
677
670
|
extendedTraceContext,
|
|
@@ -689,11 +682,21 @@ export var MediaStore = /*#__PURE__*/function () {
|
|
|
689
682
|
};
|
|
690
683
|
controller = _args13.length > 2 ? _args13[2] : undefined;
|
|
691
684
|
useMediaCdn = _args13.length > 3 ? _args13[3] : undefined;
|
|
692
|
-
method = options.method, endpoint = options.endpoint, authContext = options.authContext, params = options.params, headers = options.headers, body = options.body, clientOptions = options.clientOptions, traceContext = options.traceContext, addMediaClientParam = options.addMediaClientParam;
|
|
693
|
-
|
|
685
|
+
method = options.method, endpoint = options.endpoint, authContext = options.authContext, params = options.params, headers = options.headers, body = options.body, clientOptions = options.clientOptions, traceContext = options.traceContext, addMediaClientParam = options.addMediaClientParam, resolvedAuth = options.resolvedAuth;
|
|
686
|
+
if (!(resolvedAuth !== null && resolvedAuth !== void 0)) {
|
|
687
|
+
_context13.next = 8;
|
|
688
|
+
break;
|
|
689
|
+
}
|
|
690
|
+
_context13.t0 = resolvedAuth;
|
|
691
|
+
_context13.next = 11;
|
|
692
|
+
break;
|
|
693
|
+
case 8:
|
|
694
|
+
_context13.next = 10;
|
|
694
695
|
return this.resolveAuth(authContext);
|
|
695
|
-
case
|
|
696
|
-
|
|
696
|
+
case 10:
|
|
697
|
+
_context13.t0 = _context13.sent;
|
|
698
|
+
case 11:
|
|
699
|
+
auth = _context13.t0;
|
|
697
700
|
clientId = isClientBasedAuth(auth) ? auth.clientId : undefined;
|
|
698
701
|
extendedTraceContext = extendTraceContext(traceContext);
|
|
699
702
|
extendedParams = addMediaClientParam ? _objectSpread(_objectSpread({}, params), {}, {
|
|
@@ -703,7 +706,7 @@ export var MediaStore = /*#__PURE__*/function () {
|
|
|
703
706
|
if (useMediaCdn) {
|
|
704
707
|
url = mapToMediaCdnUrl(url, auth.token);
|
|
705
708
|
}
|
|
706
|
-
_context13.next =
|
|
709
|
+
_context13.next = 19;
|
|
707
710
|
return _request(url, {
|
|
708
711
|
method: method,
|
|
709
712
|
endpoint: endpoint,
|
|
@@ -714,12 +717,12 @@ export var MediaStore = /*#__PURE__*/function () {
|
|
|
714
717
|
clientOptions: clientOptions,
|
|
715
718
|
traceContext: extendedTraceContext
|
|
716
719
|
}, controller);
|
|
717
|
-
case
|
|
720
|
+
case 19:
|
|
718
721
|
response = _context13.sent;
|
|
719
722
|
setKeyValueInSessionStorage(MEDIA_API_REGION, response.headers.get('x-media-region'));
|
|
720
723
|
setKeyValueInSessionStorage(MEDIA_API_ENVIRONMENT, response.headers.get('x-media-env'));
|
|
721
724
|
return _context13.abrupt("return", response);
|
|
722
|
-
case
|
|
725
|
+
case 23:
|
|
723
726
|
case "end":
|
|
724
727
|
return _context13.stop();
|
|
725
728
|
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
3
|
+
import Dataloader from 'dataloader';
|
|
4
|
+
import { getRandomHex } from '@atlaskit/media-common';
|
|
5
|
+
export var MAX_BATCH_SIZE = 100;
|
|
6
|
+
/**
|
|
7
|
+
* Returns a function that, given Array<DataloaderKey>, resolves to an array of same length containing either DataloaderResult or Error.
|
|
8
|
+
* Such contract is formalised by Dataloader 1.0, @see https://github.com/graphql/dataloader
|
|
9
|
+
*
|
|
10
|
+
* If an Error is resolved in the results, it must be at same position then their corresponding key:
|
|
11
|
+
* - Dataloader will re-throw that Error when accessing/loading that particular key
|
|
12
|
+
*
|
|
13
|
+
* @param mediaStore instance of MediaStore
|
|
14
|
+
*/
|
|
15
|
+
function createBatchCopyIntentRegisterationFunc(mediaStore) {
|
|
16
|
+
return /*#__PURE__*/function () {
|
|
17
|
+
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(keys) {
|
|
18
|
+
var keysByToken, items;
|
|
19
|
+
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
20
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
21
|
+
case 0:
|
|
22
|
+
keysByToken = keys.reduce(function (acc, key) {
|
|
23
|
+
var token = key.resolvedAuth.token;
|
|
24
|
+
acc[token] = acc[token] || [];
|
|
25
|
+
|
|
26
|
+
// de-duplicate ids in collection
|
|
27
|
+
var hasDuplicates = acc[token].some(function (_ref2) {
|
|
28
|
+
var id = _ref2.id,
|
|
29
|
+
collectionName = _ref2.collectionName;
|
|
30
|
+
return key.id === id && collectionName === key.collectionName;
|
|
31
|
+
});
|
|
32
|
+
if (!hasDuplicates) {
|
|
33
|
+
acc[token].push(key);
|
|
34
|
+
}
|
|
35
|
+
return acc;
|
|
36
|
+
}, {});
|
|
37
|
+
items = [];
|
|
38
|
+
_context2.next = 4;
|
|
39
|
+
return Promise.all(Object.keys(keysByToken).map( /*#__PURE__*/function () {
|
|
40
|
+
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(batchKey) {
|
|
41
|
+
var metadataTraceContext, files, resolvedAuth;
|
|
42
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
43
|
+
while (1) switch (_context.prev = _context.next) {
|
|
44
|
+
case 0:
|
|
45
|
+
metadataTraceContext = {
|
|
46
|
+
traceId: getRandomHex(8),
|
|
47
|
+
spanId: getRandomHex(8)
|
|
48
|
+
};
|
|
49
|
+
files = keysByToken[batchKey].map(function (key) {
|
|
50
|
+
return {
|
|
51
|
+
id: key.id,
|
|
52
|
+
collection: key.collectionName
|
|
53
|
+
};
|
|
54
|
+
}); // given these are batched by the token the assumption is that they have the same details.
|
|
55
|
+
resolvedAuth = keysByToken[batchKey][0].resolvedAuth;
|
|
56
|
+
_context.prev = 3;
|
|
57
|
+
_context.next = 6;
|
|
58
|
+
return mediaStore.registerCopyIntents(files, metadataTraceContext, resolvedAuth);
|
|
59
|
+
case 6:
|
|
60
|
+
_context.next = 11;
|
|
61
|
+
break;
|
|
62
|
+
case 8:
|
|
63
|
+
_context.prev = 8;
|
|
64
|
+
_context.t0 = _context["catch"](3);
|
|
65
|
+
files.forEach(function (_ref4) {
|
|
66
|
+
var id = _ref4.id,
|
|
67
|
+
collection = _ref4.collection;
|
|
68
|
+
items.push({
|
|
69
|
+
id: id,
|
|
70
|
+
collection: collection,
|
|
71
|
+
error: _context.t0
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
case 11:
|
|
75
|
+
case "end":
|
|
76
|
+
return _context.stop();
|
|
77
|
+
}
|
|
78
|
+
}, _callee, null, [[3, 8]]);
|
|
79
|
+
}));
|
|
80
|
+
return function (_x2) {
|
|
81
|
+
return _ref3.apply(this, arguments);
|
|
82
|
+
};
|
|
83
|
+
}()));
|
|
84
|
+
case 4:
|
|
85
|
+
return _context2.abrupt("return", keys.map(function (_ref5) {
|
|
86
|
+
var _items$find;
|
|
87
|
+
var id = _ref5.id,
|
|
88
|
+
collectionName = _ref5.collectionName;
|
|
89
|
+
return (_items$find = items.find(function (item) {
|
|
90
|
+
return item.id === id && item.collection === collectionName;
|
|
91
|
+
})) === null || _items$find === void 0 ? void 0 : _items$find.error;
|
|
92
|
+
}));
|
|
93
|
+
case 5:
|
|
94
|
+
case "end":
|
|
95
|
+
return _context2.stop();
|
|
96
|
+
}
|
|
97
|
+
}, _callee2);
|
|
98
|
+
}));
|
|
99
|
+
return function (_x) {
|
|
100
|
+
return _ref.apply(this, arguments);
|
|
101
|
+
};
|
|
102
|
+
}();
|
|
103
|
+
}
|
|
104
|
+
export function createCopyIntentRegisterationBatcher(mediaStore) {
|
|
105
|
+
return new Dataloader(createBatchCopyIntentRegisterationFunc(mediaStore), {
|
|
106
|
+
maxBatchSize: MAX_BATCH_SIZE,
|
|
107
|
+
cacheKeyFn: function cacheKeyFn(_ref6) {
|
|
108
|
+
var id = _ref6.id,
|
|
109
|
+
_ref6$collectionName = _ref6.collectionName,
|
|
110
|
+
collectionName = _ref6$collectionName === void 0 ? 'default' : _ref6$collectionName,
|
|
111
|
+
resolvedAuth = _ref6.resolvedAuth;
|
|
112
|
+
return "".concat(id, "-").concat(collectionName, "-").concat(resolvedAuth.token);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
@@ -39,11 +39,13 @@ export interface FileFetcher {
|
|
|
39
39
|
getCurrentState(id: string, options?: GetFileOptions): Promise<FileState>;
|
|
40
40
|
copyFile(source: CopySourceFile, destination: CopyDestination, options?: CopyFileOptions, traceContext?: MediaTraceContext): Promise<MediaFile>;
|
|
41
41
|
getFileBinaryURL(id: string, collectionName?: string, maxAge?: number): Promise<string>;
|
|
42
|
+
registerCopyIntent(id: string, collectionName?: string): Promise<void>;
|
|
42
43
|
}
|
|
43
44
|
export declare class FileFetcherImpl implements FileFetcher {
|
|
44
45
|
private readonly mediaApi;
|
|
45
46
|
private readonly store;
|
|
46
47
|
private readonly dataloader;
|
|
48
|
+
private readonly copyIntentRegisterationBatcher;
|
|
47
49
|
constructor(mediaApi: MediaApi, store?: MediaStore);
|
|
48
50
|
private getErrorFileState;
|
|
49
51
|
private setFileState;
|
|
@@ -58,6 +60,7 @@ export declare class FileFetcherImpl implements FileFetcher {
|
|
|
58
60
|
private getUploadingFileStateBase;
|
|
59
61
|
upload(file: UploadableFile, controller?: UploadController, uploadableFileUpfrontIds?: UploadableFileUpfrontIds, traceContext?: MediaTraceContext): MediaSubscribable;
|
|
60
62
|
downloadBinary(id: string, name?: string, collectionName?: string, traceContext?: MediaTraceContext): Promise<void>;
|
|
63
|
+
registerCopyIntent(id: string, collectionName?: string): Promise<void>;
|
|
61
64
|
private copyFileWithToken;
|
|
62
65
|
private copyFileWithIntent;
|
|
63
66
|
copyFile(source: CopySourceFile, destination: CopyDestination, options?: CopyFileOptions, traceContext?: MediaTraceContext): Promise<MediaFile>;
|
|
@@ -29,7 +29,10 @@ export declare class MediaStore implements MediaApi {
|
|
|
29
29
|
appendChunksToUpload(uploadId: string, body: AppendChunksToUploadRequestBody, collectionName?: string, traceContext?: MediaTraceContext): Promise<void>;
|
|
30
30
|
copyFileWithToken(body: MediaStoreCopyFileWithTokenBody, params: MediaStoreCopyFileWithTokenParams, traceContext?: MediaTraceContext): Promise<MediaStoreResponse<MediaFile>>;
|
|
31
31
|
copyFile(id: string, params: CopyFileParams, traceContext?: MediaTraceContext): Promise<MediaStoreResponse<MediaFile>>;
|
|
32
|
-
registerCopyIntents(
|
|
32
|
+
registerCopyIntents(files: Array<{
|
|
33
|
+
id: string;
|
|
34
|
+
collection?: string;
|
|
35
|
+
}>, traceContext?: MediaTraceContext, resolvedAuth?: Auth): Promise<void>;
|
|
33
36
|
request(path: string, options?: MediaStoreRequestOptions, controller?: AbortController, useMediaCdn?: boolean): Promise<Response>;
|
|
34
37
|
testUrl(url: string, options?: {
|
|
35
38
|
traceContext?: MediaTraceContext;
|
|
@@ -37,6 +37,7 @@ export interface MediaStoreResponse<Data> {
|
|
|
37
37
|
export type MediaStoreRequestOptions = RequestMetadata & {
|
|
38
38
|
readonly method?: RequestMethod;
|
|
39
39
|
readonly authContext?: AuthContext;
|
|
40
|
+
readonly resolvedAuth?: Auth;
|
|
40
41
|
readonly params?: RequestParams;
|
|
41
42
|
readonly headers?: RequestHeaders;
|
|
42
43
|
readonly body?: any;
|
|
@@ -172,7 +173,10 @@ export interface MediaApi {
|
|
|
172
173
|
appendChunksToUpload: (uploadId: string, body: AppendChunksToUploadRequestBody, collectionName?: string, traceContext?: MediaTraceContext) => Promise<void>;
|
|
173
174
|
copyFileWithToken: (body: MediaStoreCopyFileWithTokenBody, params: MediaStoreCopyFileWithTokenParams, traceContext?: MediaTraceContext) => Promise<MediaStoreResponse<MediaFile>>;
|
|
174
175
|
copyFile: (id: string, params: CopyFileParams) => Promise<MediaStoreResponse<MediaFile>>;
|
|
175
|
-
registerCopyIntents: (
|
|
176
|
+
registerCopyIntents: (files: Array<{
|
|
177
|
+
id: string;
|
|
178
|
+
collection: string;
|
|
179
|
+
}>, traceContext?: MediaTraceContext, resolvedAuth?: Auth) => Promise<void>;
|
|
176
180
|
request: (path: string, options: MediaStoreRequestOptions, controller?: AbortController) => Promise<Response>;
|
|
177
181
|
testUrl: (url: string, options?: {
|
|
178
182
|
traceContext?: MediaTraceContext;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import Dataloader from 'dataloader';
|
|
2
|
+
import { type MediaStore } from '../client/media-store';
|
|
3
|
+
import { type NotFoundMediaItemDetails, type MediaItemDetails } from '../models/media';
|
|
4
|
+
import { type Auth } from '@atlaskit/media-core';
|
|
5
|
+
export declare const MAX_BATCH_SIZE = 100;
|
|
6
|
+
export type CopyIntentKey = {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly resolvedAuth: Auth;
|
|
9
|
+
readonly collectionName?: string;
|
|
10
|
+
};
|
|
11
|
+
export type DataloaderResult = MediaItemDetails | NotFoundMediaItemDetails;
|
|
12
|
+
export type BatchLoadingErrorResult = {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly collection?: string;
|
|
15
|
+
readonly error: Error;
|
|
16
|
+
};
|
|
17
|
+
export type FilesByToken = {
|
|
18
|
+
[token: string]: CopyIntentKey[];
|
|
19
|
+
};
|
|
20
|
+
export declare function createCopyIntentRegisterationBatcher(mediaStore: MediaStore): Dataloader<CopyIntentKey, Error | undefined, string>;
|