@atlaskit/media-client 39.1.4 → 39.1.6
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/AGENTS.md
CHANGED
|
@@ -49,8 +49,8 @@ first, edit, then `kg.py edit <path> --message "<reason>"`.
|
|
|
49
49
|
|
|
50
50
|
- Peer dependencies: `@atlaskit/media-core`, `@atlaskit/media-state`
|
|
51
51
|
- Key internal dependencies: `@atlaskit/chunkinator`, `@atlaskit/media-common`
|
|
52
|
-
-
|
|
52
|
+
- 10 feature flags registered (see `package.json` → `platform-feature-flags`)
|
|
53
53
|
- Notable flags: `platform_media_cdn_delivery`, `platform_media_cdn_single_host`,
|
|
54
|
-
`platform_media_auth_provider_analytics`
|
|
54
|
+
`platform_media_auth_provider_analytics`, `platform_media_unique_external_upload_name`
|
|
55
55
|
- All new behaviour changes must be behind a feature gate (`fg()` from
|
|
56
56
|
`@atlaskit/platform-feature-flags`)
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @atlaskit/media-client
|
|
2
2
|
|
|
3
|
+
## 39.1.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
|
|
9
|
+
## 39.1.5
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [`0d4a7d7340b59`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0d4a7d7340b59) -
|
|
14
|
+
`uploadExternal` now derives a collision-resistant filename for external uploads, behind the
|
|
15
|
+
`platform_media_unique_external_upload_name` feature gate. Endpoint-style source URLs such as
|
|
16
|
+
`/binary` previously produced an identical filename for every image, so publishing collapsed the
|
|
17
|
+
copied page attachments into several versions of a single attachment. The generated name keeps the
|
|
18
|
+
source extension when the URL supplies one and otherwise derives it from the response MIME type.
|
|
19
|
+
Anonymised uploads are unchanged.
|
|
20
|
+
|
|
3
21
|
## 39.1.4
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
|
@@ -22,6 +22,7 @@ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/
|
|
|
22
22
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
23
23
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
24
24
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
25
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
25
26
|
var _mime = require("mime");
|
|
26
27
|
var _map = require("rxjs/operators/map");
|
|
27
28
|
var _Subscription = require("rxjs/Subscription");
|
|
@@ -32,6 +33,7 @@ var _mediaTypeUtils = require("@atlaskit/media-common/mediaTypeUtils");
|
|
|
32
33
|
var _authToOwner = require("@atlaskit/media-core/auth-to-owner");
|
|
33
34
|
var _mediaStore = require("@atlaskit/media-state/media-store");
|
|
34
35
|
var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
|
|
36
|
+
var _fg = require("@atlaskit/platform-feature-flags/fg");
|
|
35
37
|
var _constants = require("../../constants");
|
|
36
38
|
var _fileStreamsCache = require("../../file-streams-cache");
|
|
37
39
|
var _globalMediaEventEmitter = require("../../globalMediaEventEmitter");
|
|
@@ -74,6 +76,36 @@ var isCopySourceFileWithToken = function isCopySourceFileWithToken(token) {
|
|
|
74
76
|
var isCopyDestinationWithToken = function isCopyDestinationWithToken(token) {
|
|
75
77
|
return !!token.authProvider;
|
|
76
78
|
};
|
|
79
|
+
var EXTERNAL_UPLOAD_FALLBACK_STEM = 'image';
|
|
80
|
+
// Only used to resolve relative urls so their path can be read; never requested.
|
|
81
|
+
var EXTERNAL_UPLOAD_URL_BASE = 'https://media.invalid';
|
|
82
|
+
|
|
83
|
+
// A leading dot names a file rather than an extension, so `.gitignore` splits to a stem.
|
|
84
|
+
var splitExtension = function splitExtension(name) {
|
|
85
|
+
var index = name.lastIndexOf('.');
|
|
86
|
+
return index > 0 ? [name.slice(0, index), name.slice(index)] : [name, ''];
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Publishing copies media into page attachments keyed by filename, and same-named files collapse
|
|
90
|
+
// into versions of a single attachment. External URLs are frequently endpoint-style (for example
|
|
91
|
+
// `/binary`), so the stem is made unique before the upload reaches Media Services.
|
|
92
|
+
var buildExternalUploadName = function buildExternalUploadName(url, anonymizeFilename) {
|
|
93
|
+
if (anonymizeFilename) {
|
|
94
|
+
return crypto.randomUUID();
|
|
95
|
+
}
|
|
96
|
+
if (!(0, _fg.fg)('platform_media_unique_external_upload_name')) {
|
|
97
|
+
return url.split('/').pop() || '';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Reading the path drops any query string, which would otherwise be captured as part of the
|
|
101
|
+
// extension and suppress the MIME-derived fallback.
|
|
102
|
+
var urlName = new URL(url, EXTERNAL_UPLOAD_URL_BASE).pathname.split('/').pop() || '';
|
|
103
|
+
var _splitExtension = splitExtension(urlName),
|
|
104
|
+
_splitExtension2 = (0, _slicedToArray2.default)(_splitExtension, 2),
|
|
105
|
+
stem = _splitExtension2[0],
|
|
106
|
+
extension = _splitExtension2[1];
|
|
107
|
+
return "".concat(stem || EXTERNAL_UPLOAD_FALLBACK_STEM, "-").concat(crypto.randomUUID()).concat(extension);
|
|
108
|
+
};
|
|
77
109
|
var FileFetcherImpl = exports.FileFetcherImpl = /*#__PURE__*/function () {
|
|
78
110
|
function FileFetcherImpl(mediaApi) {
|
|
79
111
|
var _this = this;
|
|
@@ -613,7 +645,7 @@ var FileFetcherImpl = exports.FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
613
645
|
return _ref0.apply(this, arguments);
|
|
614
646
|
};
|
|
615
647
|
}());
|
|
616
|
-
initialName =
|
|
648
|
+
initialName = buildExternalUploadName(url, anonymizeFilename); // we create a initial fileState with the minimum info that we have at this point
|
|
617
649
|
fileState = {
|
|
618
650
|
status: 'processing',
|
|
619
651
|
name: initialName,
|
|
@@ -630,7 +662,7 @@ var FileFetcherImpl = exports.FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
630
662
|
this.setFileState(id, fileState);
|
|
631
663
|
return _context0.abrupt("return", new Promise( /*#__PURE__*/function () {
|
|
632
664
|
var _ref1 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee9(resolve, reject) {
|
|
633
|
-
var blob, type, size, extension, name, file, mediaType, dimensions, _t4;
|
|
665
|
+
var blob, type, size, extensionAllowed, _splitExtension3, _splitExtension4, existingExtension, extension, name, file, mediaType, dimensions, _t4;
|
|
634
666
|
return _regenerator.default.wrap(function (_context9) {
|
|
635
667
|
while (1) switch (_context9.prev = _context9.next) {
|
|
636
668
|
case 0:
|
|
@@ -645,7 +677,9 @@ var FileFetcherImpl = exports.FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
645
677
|
return _context9.abrupt("return", reject('Could not download remote file'));
|
|
646
678
|
case 2:
|
|
647
679
|
type = blob.type, size = blob.size;
|
|
648
|
-
|
|
680
|
+
extensionAllowed = anonymizeFilename ? (0, _isExperimentEnabled.isExperimentEnabled)('cc_maui_polish_changes_batch_8') : (0, _fg.fg)('platform_media_unique_external_upload_name');
|
|
681
|
+
_splitExtension3 = splitExtension(initialName), _splitExtension4 = (0, _slicedToArray2.default)(_splitExtension3, 2), existingExtension = _splitExtension4[1];
|
|
682
|
+
extension = extensionAllowed && !existingExtension ? (0, _mime.getExtension)(type) : undefined;
|
|
649
683
|
name = extension ? "".concat(initialName, ".").concat(extension) : initialName;
|
|
650
684
|
file = {
|
|
651
685
|
content: blob,
|
|
@@ -12,6 +12,7 @@ import { getMediaTypeFromMimeType } from '@atlaskit/media-common/mediaTypeUtils'
|
|
|
12
12
|
import { authToOwner } from '@atlaskit/media-core/auth-to-owner';
|
|
13
13
|
import { mediaStore } from '@atlaskit/media-state/media-store';
|
|
14
14
|
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
15
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
15
16
|
import { RECENTS_COLLECTION } from '../../constants';
|
|
16
17
|
import { getFileStreamsCache } from '../../file-streams-cache';
|
|
17
18
|
import { globalMediaEventEmitter } from '../../globalMediaEventEmitter';
|
|
@@ -50,6 +51,33 @@ export { FileFetcherError } from './FileFetcherError';
|
|
|
50
51
|
export { isFileFetcherError } from './isFileFetcherError';
|
|
51
52
|
const isCopySourceFileWithToken = token => !!token.authProvider;
|
|
52
53
|
const isCopyDestinationWithToken = token => !!token.authProvider;
|
|
54
|
+
const EXTERNAL_UPLOAD_FALLBACK_STEM = 'image';
|
|
55
|
+
// Only used to resolve relative urls so their path can be read; never requested.
|
|
56
|
+
const EXTERNAL_UPLOAD_URL_BASE = 'https://media.invalid';
|
|
57
|
+
|
|
58
|
+
// A leading dot names a file rather than an extension, so `.gitignore` splits to a stem.
|
|
59
|
+
const splitExtension = name => {
|
|
60
|
+
const index = name.lastIndexOf('.');
|
|
61
|
+
return index > 0 ? [name.slice(0, index), name.slice(index)] : [name, ''];
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Publishing copies media into page attachments keyed by filename, and same-named files collapse
|
|
65
|
+
// into versions of a single attachment. External URLs are frequently endpoint-style (for example
|
|
66
|
+
// `/binary`), so the stem is made unique before the upload reaches Media Services.
|
|
67
|
+
const buildExternalUploadName = (url, anonymizeFilename) => {
|
|
68
|
+
if (anonymizeFilename) {
|
|
69
|
+
return crypto.randomUUID();
|
|
70
|
+
}
|
|
71
|
+
if (!fg('platform_media_unique_external_upload_name')) {
|
|
72
|
+
return url.split('/').pop() || '';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Reading the path drops any query string, which would otherwise be captured as part of the
|
|
76
|
+
// extension and suppress the MIME-derived fallback.
|
|
77
|
+
const urlName = new URL(url, EXTERNAL_UPLOAD_URL_BASE).pathname.split('/').pop() || '';
|
|
78
|
+
const [stem, extension] = splitExtension(urlName);
|
|
79
|
+
return `${stem || EXTERNAL_UPLOAD_FALLBACK_STEM}-${crypto.randomUUID()}${extension}`;
|
|
80
|
+
};
|
|
53
81
|
export class FileFetcherImpl {
|
|
54
82
|
constructor(mediaApi, store = mediaStore) {
|
|
55
83
|
_defineProperty(this, "getErrorFileState", (error, id, occurrenceKey) => {
|
|
@@ -386,7 +414,7 @@ export class FileFetcherImpl {
|
|
|
386
414
|
origin: 'remote'
|
|
387
415
|
});
|
|
388
416
|
});
|
|
389
|
-
const initialName =
|
|
417
|
+
const initialName = buildExternalUploadName(url, anonymizeFilename);
|
|
390
418
|
// we create a initial fileState with the minimum info that we have at this point
|
|
391
419
|
const fileState = {
|
|
392
420
|
status: 'processing',
|
|
@@ -411,7 +439,9 @@ export class FileFetcherImpl {
|
|
|
411
439
|
type,
|
|
412
440
|
size
|
|
413
441
|
} = blob;
|
|
414
|
-
const
|
|
442
|
+
const extensionAllowed = anonymizeFilename ? isExperimentEnabled('cc_maui_polish_changes_batch_8') : fg('platform_media_unique_external_upload_name');
|
|
443
|
+
const [, existingExtension] = splitExtension(initialName);
|
|
444
|
+
const extension = extensionAllowed && !existingExtension ? getExtension(type) : undefined;
|
|
415
445
|
const name = extension ? `${initialName}.${extension}` : initialName;
|
|
416
446
|
const file = {
|
|
417
447
|
content: blob,
|
|
@@ -2,6 +2,7 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
|
2
2
|
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
3
3
|
import _createClass from "@babel/runtime/helpers/createClass";
|
|
4
4
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
5
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
5
6
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
6
7
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
7
8
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
@@ -18,6 +19,7 @@ import { getMediaTypeFromMimeType } from '@atlaskit/media-common/mediaTypeUtils'
|
|
|
18
19
|
import { authToOwner } from '@atlaskit/media-core/auth-to-owner';
|
|
19
20
|
import { mediaStore } from '@atlaskit/media-state/media-store';
|
|
20
21
|
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
22
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
21
23
|
import { RECENTS_COLLECTION } from '../../constants';
|
|
22
24
|
import { getFileStreamsCache } from '../../file-streams-cache';
|
|
23
25
|
import { globalMediaEventEmitter } from '../../globalMediaEventEmitter';
|
|
@@ -60,6 +62,36 @@ var isCopySourceFileWithToken = function isCopySourceFileWithToken(token) {
|
|
|
60
62
|
var isCopyDestinationWithToken = function isCopyDestinationWithToken(token) {
|
|
61
63
|
return !!token.authProvider;
|
|
62
64
|
};
|
|
65
|
+
var EXTERNAL_UPLOAD_FALLBACK_STEM = 'image';
|
|
66
|
+
// Only used to resolve relative urls so their path can be read; never requested.
|
|
67
|
+
var EXTERNAL_UPLOAD_URL_BASE = 'https://media.invalid';
|
|
68
|
+
|
|
69
|
+
// A leading dot names a file rather than an extension, so `.gitignore` splits to a stem.
|
|
70
|
+
var splitExtension = function splitExtension(name) {
|
|
71
|
+
var index = name.lastIndexOf('.');
|
|
72
|
+
return index > 0 ? [name.slice(0, index), name.slice(index)] : [name, ''];
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Publishing copies media into page attachments keyed by filename, and same-named files collapse
|
|
76
|
+
// into versions of a single attachment. External URLs are frequently endpoint-style (for example
|
|
77
|
+
// `/binary`), so the stem is made unique before the upload reaches Media Services.
|
|
78
|
+
var buildExternalUploadName = function buildExternalUploadName(url, anonymizeFilename) {
|
|
79
|
+
if (anonymizeFilename) {
|
|
80
|
+
return crypto.randomUUID();
|
|
81
|
+
}
|
|
82
|
+
if (!fg('platform_media_unique_external_upload_name')) {
|
|
83
|
+
return url.split('/').pop() || '';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Reading the path drops any query string, which would otherwise be captured as part of the
|
|
87
|
+
// extension and suppress the MIME-derived fallback.
|
|
88
|
+
var urlName = new URL(url, EXTERNAL_UPLOAD_URL_BASE).pathname.split('/').pop() || '';
|
|
89
|
+
var _splitExtension = splitExtension(urlName),
|
|
90
|
+
_splitExtension2 = _slicedToArray(_splitExtension, 2),
|
|
91
|
+
stem = _splitExtension2[0],
|
|
92
|
+
extension = _splitExtension2[1];
|
|
93
|
+
return "".concat(stem || EXTERNAL_UPLOAD_FALLBACK_STEM, "-").concat(crypto.randomUUID()).concat(extension);
|
|
94
|
+
};
|
|
63
95
|
export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
64
96
|
function FileFetcherImpl(mediaApi) {
|
|
65
97
|
var _this = this;
|
|
@@ -599,7 +631,7 @@ export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
599
631
|
return _ref0.apply(this, arguments);
|
|
600
632
|
};
|
|
601
633
|
}());
|
|
602
|
-
initialName =
|
|
634
|
+
initialName = buildExternalUploadName(url, anonymizeFilename); // we create a initial fileState with the minimum info that we have at this point
|
|
603
635
|
fileState = {
|
|
604
636
|
status: 'processing',
|
|
605
637
|
name: initialName,
|
|
@@ -616,7 +648,7 @@ export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
616
648
|
this.setFileState(id, fileState);
|
|
617
649
|
return _context0.abrupt("return", new Promise( /*#__PURE__*/function () {
|
|
618
650
|
var _ref1 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9(resolve, reject) {
|
|
619
|
-
var blob, type, size, extension, name, file, mediaType, dimensions, _t4;
|
|
651
|
+
var blob, type, size, extensionAllowed, _splitExtension3, _splitExtension4, existingExtension, extension, name, file, mediaType, dimensions, _t4;
|
|
620
652
|
return _regeneratorRuntime.wrap(function (_context9) {
|
|
621
653
|
while (1) switch (_context9.prev = _context9.next) {
|
|
622
654
|
case 0:
|
|
@@ -631,7 +663,9 @@ export var FileFetcherImpl = /*#__PURE__*/function () {
|
|
|
631
663
|
return _context9.abrupt("return", reject('Could not download remote file'));
|
|
632
664
|
case 2:
|
|
633
665
|
type = blob.type, size = blob.size;
|
|
634
|
-
|
|
666
|
+
extensionAllowed = anonymizeFilename ? isExperimentEnabled('cc_maui_polish_changes_batch_8') : fg('platform_media_unique_external_upload_name');
|
|
667
|
+
_splitExtension3 = splitExtension(initialName), _splitExtension4 = _slicedToArray(_splitExtension3, 2), existingExtension = _splitExtension4[1];
|
|
668
|
+
extension = extensionAllowed && !existingExtension ? getExtension(type) : undefined;
|
|
635
669
|
name = extension ? "".concat(initialName, ".").concat(extension) : initialName;
|
|
636
670
|
file = {
|
|
637
671
|
content: blob,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/media-client",
|
|
3
|
-
"version": "39.1.
|
|
3
|
+
"version": "39.1.6",
|
|
4
4
|
"description": "Media API Web Client Library",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@atlaskit/media-common": "^14.6.0",
|
|
27
27
|
"@atlaskit/platform-feature-experiments": "^0.3.0",
|
|
28
28
|
"@atlaskit/platform-feature-flags": "^2.2.0",
|
|
29
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
29
|
+
"@atlaskit/tmp-editor-statsig": "^226.0.0",
|
|
30
30
|
"@babel/runtime": "^7.0.0",
|
|
31
31
|
"dataloader": "^2.1.0",
|
|
32
32
|
"deep-equal": "^1.0.1",
|
|
@@ -87,6 +87,9 @@
|
|
|
87
87
|
"platform_media_filereader_error_surfacing": {
|
|
88
88
|
"type": "boolean",
|
|
89
89
|
"referenceOnly": true
|
|
90
|
+
},
|
|
91
|
+
"platform_media_unique_external_upload_name": {
|
|
92
|
+
"type": "boolean"
|
|
90
93
|
}
|
|
91
94
|
}
|
|
92
95
|
}
|