@atlaskit/media-client 37.6.5 → 37.7.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 CHANGED
@@ -1,5 +1,44 @@
1
1
  # @atlaskit/media-client
2
2
 
3
+ ## 37.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`be8a71519cbc2`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/be8a71519cbc2) -
8
+ Add support for seeding media card file state from SSR media node metadata, behind the
9
+ `platform_media_ssr_data_seed` feature gate.
10
+
11
+ `@atlaskit/media-client` gains a Relay-free `mapSsrMediaItemToFileState`. Malformed, partial, or
12
+ non-array input yields `undefined` rather than throwing.
13
+
14
+ `@atlaskit/media-card` accepts an optional `ssrMediaItem` prop. When `ssrFileState` is absent and
15
+ the gate is on, the card converts `ssrMediaItem` to FileState via `mapSsrMediaItemToFileState` and
16
+ seeds `useFileState`. `ssrFileState` still wins when both are provided (Relay / media-card-relay).
17
+
18
+ `@atlaskit/renderer` extends `MediaSSR` with `ssrMediaItems` — the host's SSR media payload,
19
+ passed through untouched. The renderer finds the matching item by id and forwards it as
20
+ `ssrMediaItem` to Card. Hosts need no knowledge of `FileState` or of media internals. The field is
21
+ optional and additive: hosts that do not supply it, and media ids without an entry, keep the
22
+ current fetch behaviour.
23
+
24
+ `@atlaskit/media-card-relay`'s `MediaCardRelay` / `MediaInlineCardRelay` now call the shared
25
+ `mapSsrMediaItemToFileState` mapper directly (the Relay fragment data is structurally assignable
26
+ to `SsrMediaItem`, so no cast or wrapper is needed). Its public API and behaviour are unchanged.
27
+
28
+ `@atlaskit/media-file-preview` now forwards an SSR-seeded pre-signed `previewCdnUrl` to the new
29
+ optional `MediaClient.getImageUrlSync(id, params, seededCdnUrl)` argument when
30
+ `platform_media_ssr_data_seed` is enabled and CDN delivery is in use. `@atlaskit/media-client`
31
+ preserves the signed CDN asset URL and inserts supported image parameters before the `wm-ari` /
32
+ `wm-v` watermark anchor, avoiding query-string rebuilding or re-encoding that can invalidate
33
+ CloudFront signatures. Path-based routing, isolated cloud, GCP, and callers without a seeded URL
34
+ retain the existing URL-generation behaviour.
35
+
36
+ ## 37.6.6
37
+
38
+ ### Patch Changes
39
+
40
+ - Updated dependencies
41
+
3
42
  ## 37.6.5
4
43
 
5
44
  ### Patch Changes
@@ -60,8 +60,8 @@ var MediaClient = exports.MediaClient = /*#__PURE__*/function () {
60
60
  }
61
61
  }, {
62
62
  key: "getImageUrlSync",
63
- value: function getImageUrlSync(id, params) {
64
- return this.mediaStore.getFileImageURLSync(id, params);
63
+ value: function getImageUrlSync(id, params, seededCdnUrl) {
64
+ return this.mediaStore.getFileImageURLSync(id, params, seededCdnUrl);
65
65
  }
66
66
  }, {
67
67
  key: "getClientId",
@@ -34,9 +34,11 @@ var _fg = require("@atlaskit/platform-feature-flags/fg");
34
34
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
35
35
  var _constants = require("../../constants");
36
36
  var _artifacts = require("../../models/artifacts");
37
+ var _isCDNEnabled = require("../../utils/isCDNEnabled");
37
38
  var _isPathBasedEnabled = require("../../utils/isPathBasedEnabled");
38
39
  var _mapToMediaCdnUrl = require("../../utils/mapToMediaCdnUrl");
39
40
  var _mapToPathBasedUrl = require("../../utils/mapToPathBasedUrl");
41
+ var _mapToSeedBasedCdnUrl = require("../../utils/mapToSeedBasedCdnUrl");
40
42
  var _request3 = require("../../utils/request");
41
43
  var _createMapResponseToBlob = require("../../utils/request/createMapResponseToBlob");
42
44
  var _createMapResponseToJson = require("../../utils/request/createMapResponseToJson");
@@ -460,13 +462,13 @@ var MediaStore = exports.MediaStore = /*#__PURE__*/function () {
460
462
  }() // TODO Create ticket in case Trace Id can be supported through query params
461
463
  }, {
462
464
  key: "getFileImageURLSync",
463
- value: function getFileImageURLSync(id, params) {
465
+ value: function getFileImageURLSync(id, params, seededCdnUrl) {
464
466
  var auth = this.resolveInitialAuth();
465
- return this.createFileImageURL(id, auth, params);
467
+ return this.createFileImageURL(id, auth, params, seededCdnUrl);
466
468
  }
467
469
  }, {
468
470
  key: "createFileImageURL",
469
- value: function createFileImageURL(id, auth, params) {
471
+ value: function createFileImageURL(id, auth, params, seededCdnUrl) {
470
472
  var wmv = (0, _fg.fg)('confluence_watermark_admin_ui') ? (0, _watermarkVersion.getWatermarkVersionFromToken)(auth.token) : undefined;
471
473
  var options = {
472
474
  params: _objectSpread(_objectSpread({}, (0, _extendImageParams.extendImageParams)(params)), wmv ? {
@@ -475,6 +477,9 @@ var MediaStore = exports.MediaStore = /*#__PURE__*/function () {
475
477
  auth: auth
476
478
  };
477
479
  var imageEndpoint = (0, _cdnFeatureFlag.cdnFeatureFlag)('image');
480
+ if (seededCdnUrl && (0, _isCDNEnabled.isCDNEnabled)()) {
481
+ return (0, _mapToSeedBasedCdnUrl.mapToSeedBasedCdnUrl)(seededCdnUrl, options.params);
482
+ }
478
483
  if ((0, _isPathBasedEnabled.isPathBasedEnabled)()) {
479
484
  return (0, _mapToPathBasedUrl.mapToPathBasedUrl)((0, _createUrl.createUrl)("".concat(auth.baseUrl, "/file/").concat(id, "/").concat(imageEndpoint), options));
480
485
  }
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.mapSsrMediaItemToFileState = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _fileState = require("./file-state");
10
+ 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; }
11
+ 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) { (0, _defineProperty2.default)(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; }
12
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
13
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
14
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
15
+ /**
16
+ * Describes the shape of a plain recorded AGG media item as serialized by Confluence SSR.
17
+ * All fields are optional/nullable to tolerate untrusted runtime JSON from window globals.
18
+ *
19
+ * This is the shape as returned by dt-api-filestore `media_items` aggregation.
20
+ */
21
+
22
+ /**
23
+ * Describes a complete SSR media item with id and details.
24
+ * All fields are optional/nullable to tolerate untrusted runtime JSON from window globals.
25
+ */
26
+
27
+ /**
28
+ * Safely coerce a value to a number, returning undefined if the value is null/undefined.
29
+ */
30
+ var toNumber = function toNumber(value) {
31
+ return value == null ? undefined : Number(value);
32
+ };
33
+
34
+ /**
35
+ * Convert abuse classification fields to the keyed format expected by FileState,
36
+ * returning undefined if either classification or confidence is missing/falsy.
37
+ */
38
+ var toAbuseClassification = function toAbuseClassification(value) {
39
+ if (!value || !value.classification || !value.confidence) {
40
+ return undefined;
41
+ }
42
+ return {
43
+ classification: value.classification,
44
+ confidence: value.confidence
45
+ };
46
+ };
47
+
48
+ /**
49
+ * Convert the `artifactsList` array shape into the keyed `MediaFileArtifacts`
50
+ * dict that `MediaItemDetails` / `FileState` consumers expect.
51
+ *
52
+ * Each artifact is keyed by its `name` (e.g. `'image.png'`, `'thumb_120.jpg'`).
53
+ * Artifacts missing required fields (`name`, `url`, `processingStatus`)
54
+ * are skipped rather than coerced — callers should treat absent artifacts as
55
+ * "not yet available" rather than "failed".
56
+ *
57
+ * NOTE: This assumes AGG returns `name` values matching the canonical
58
+ * `MediaFileArtifacts` key vocabulary. If that assumption is broken, the
59
+ * downstream renderer will silently miss SSR thumbnails — verify with a real
60
+ * payload before relying on SSR previews.
61
+ */
62
+ var toArtifacts = function toArtifacts(list) {
63
+ var out = {};
64
+ if (!list) {
65
+ return out;
66
+ }
67
+ var _iterator = _createForOfIteratorHelper(list),
68
+ _step;
69
+ try {
70
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
71
+ var item = _step.value;
72
+ if (!item.name || !item.url || !item.processingStatus) {
73
+ continue;
74
+ }
75
+ var artifact = _objectSpread(_objectSpread(_objectSpread({
76
+ processingStatus: item.processingStatus,
77
+ url: item.url
78
+ }, item.mimeType ? {
79
+ mimeType: item.mimeType
80
+ } : {}), item.size != null ? {
81
+ size: Number(item.size)
82
+ } : {}), item.createdAt != null ? {
83
+ createdAt: Number(item.createdAt)
84
+ } : {});
85
+ out[item.name] = artifact;
86
+ }
87
+ } catch (err) {
88
+ _iterator.e(err);
89
+ } finally {
90
+ _iterator.f();
91
+ }
92
+ return out;
93
+ };
94
+
95
+ /**
96
+ * Map a plain SSR media item (from AGG / dt-api-filestore) to a `FileState`
97
+ * for seeding `<Card />` / `<MediaInlineCard />`.
98
+ *
99
+ * Returns `undefined` when:
100
+ * - `item` is null/undefined or missing `id`/`details`
101
+ * - any of the required `MediaFile` fields (`name`, `mimeType`, `mediaType`,
102
+ * `processingStatus`) are missing or falsy
103
+ * - `size` is missing or cannot be coerced to a number
104
+ *
105
+ * The transformation reshapes `details.artifactsList` (array, AGG-only) into
106
+ * the keyed `details.artifacts` dict expected by `mapMediaItemToFileState`,
107
+ * and coerces `AGG$Long` numerics.
108
+ *
109
+ * MUST NOT throw on malformed input — always return undefined instead.
110
+ */
111
+ var mapSsrMediaItemToFileState = exports.mapSsrMediaItemToFileState = function mapSsrMediaItemToFileState(item) {
112
+ try {
113
+ var _d$representations, _d$mediaMetadata, _d$preview;
114
+ if (!(item !== null && item !== void 0 && item.id) || !item.details) {
115
+ return undefined;
116
+ }
117
+ var d = item.details;
118
+ var processingStatus = d.processingStatus;
119
+ var mediaType = d.mediaType;
120
+ var size = toNumber(d.size);
121
+ if (!d.name || !d.mimeType || !mediaType || !processingStatus || size === undefined) {
122
+ return undefined;
123
+ }
124
+ var abuseClassification = toAbuseClassification(d.abuseClassification);
125
+ var details = _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
126
+ name: d.name,
127
+ mimeType: d.mimeType,
128
+ mediaType: mediaType,
129
+ processingStatus: processingStatus,
130
+ size: size,
131
+ artifacts: toArtifacts(d.artifactsList),
132
+ representations: (_d$representations = d.representations) !== null && _d$representations !== void 0 && _d$representations.image ? {
133
+ image: {}
134
+ } : {}
135
+ }, d.failReason ? {
136
+ failReason: d.failReason
137
+ } : {}), d.createdAt != null ? {
138
+ createdAt: Number(d.createdAt)
139
+ } : {}), ((_d$mediaMetadata = d.mediaMetadata) === null || _d$mediaMetadata === void 0 ? void 0 : _d$mediaMetadata.duration) != null ? {
140
+ mediaMetadata: {
141
+ duration: d.mediaMetadata.duration
142
+ }
143
+ } : {}), abuseClassification ? {
144
+ abuseClassification: abuseClassification
145
+ } : {}), (_d$preview = d.preview) !== null && _d$preview !== void 0 && _d$preview.cdnUrl ? {
146
+ previewCdnUrl: d.preview.cdnUrl
147
+ } : {});
148
+ return (0, _fileState.mapMediaItemToFileState)(item.id, details);
149
+ } catch (_unused) {
150
+ // Silently catch any unexpected errors and return undefined
151
+ return undefined;
152
+ }
153
+ };
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.mapToSeedBasedCdnUrl = void 0;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var IMAGE_PARAM_KEYS = new Set(['width', 'height', 'mode', 'allowAnimated', 'upscale', 'version', 'max-age']);
10
+
11
+ /**
12
+ * Adds supported image parameters to a pre-signed CDN asset URL without
13
+ * re-parsing or re-encoding its existing query string.
14
+ *
15
+ * Watermarked CloudFront policies anchor `wm-ari` and `wm-v` as a literal
16
+ * suffix, so parameters must be inserted before `wm-ari`. Non-watermarked
17
+ * policies have a trailing wildcard, so parameters can be appended.
18
+ */
19
+ var mapToSeedBasedCdnUrl = exports.mapToSeedBasedCdnUrl = function mapToSeedBasedCdnUrl(seededCdnUrl, params) {
20
+ var insert = Object.entries(params !== null && params !== void 0 ? params : {}).filter(function (_ref) {
21
+ var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
22
+ key = _ref2[0],
23
+ value = _ref2[1];
24
+ return value != null && IMAGE_PARAM_KEYS.has(key);
25
+ }).map(function (_ref3) {
26
+ var _ref4 = (0, _slicedToArray2.default)(_ref3, 2),
27
+ key = _ref4[0],
28
+ value = _ref4[1];
29
+ return "".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(String(value)));
30
+ }).join('&');
31
+ if (!insert) {
32
+ return seededCdnUrl;
33
+ }
34
+ var wm = seededCdnUrl.search(/[?&]wm-ari=/);
35
+ if (wm !== -1) {
36
+ var separator = seededCdnUrl[wm];
37
+ return "".concat(seededCdnUrl.slice(0, wm)).concat(separator).concat(insert, "&").concat(seededCdnUrl.slice(wm + 1));
38
+ }
39
+ return "".concat(seededCdnUrl).concat(seededCdnUrl.includes('?') ? '&' : '?').concat(insert);
40
+ };
@@ -4,6 +4,13 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.MEDIA_TOKEN_LENGTH_LIMIT = exports.MEDIA_CDN_MAP = void 0;
7
+ Object.defineProperty(exports, "isCDNEnabled", {
8
+ enumerable: true,
9
+ get: function get() {
10
+ return _isCDNEnabled.isCDNEnabled;
11
+ }
12
+ });
13
+ var _isCDNEnabled = require("./isCDNEnabled");
7
14
  var MEDIA_CDN_MAP = exports.MEDIA_CDN_MAP = {
8
15
  'api.media.atlassian.com': 'media-cdn.atlassian.com',
9
16
  'media.staging.atl-paas.net': 'media-cdn.stg.atlassian.com'
@@ -36,8 +36,8 @@ export class MediaClient {
36
36
  getImageUrl(id, params) {
37
37
  return this.mediaStore.getFileImageURL(id, params);
38
38
  }
39
- getImageUrlSync(id, params) {
40
- return this.mediaStore.getFileImageURLSync(id, params);
39
+ getImageUrlSync(id, params, seededCdnUrl) {
40
+ return this.mediaStore.getFileImageURLSync(id, params, seededCdnUrl);
41
41
  }
42
42
  async getClientId(collectionName) {
43
43
  return this.mediaStore.getClientId(collectionName);
@@ -7,9 +7,11 @@ import { fg } from '@atlaskit/platform-feature-flags/fg';
7
7
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
8
8
  import { FILE_CACHE_MAX_AGE } from '../../constants';
9
9
  import { getArtifactUrl } from '../../models/artifacts';
10
+ import { isCDNEnabled } from '../../utils/isCDNEnabled';
10
11
  import { isPathBasedEnabled } from '../../utils/isPathBasedEnabled';
11
12
  import { mapToMediaCdnUrl } from '../../utils/mapToMediaCdnUrl';
12
13
  import { mapToPathBasedUrl } from '../../utils/mapToPathBasedUrl';
14
+ import { mapToSeedBasedCdnUrl } from '../../utils/mapToSeedBasedCdnUrl';
13
15
  import { isRequestError, request } from '../../utils/request';
14
16
  import { createMapResponseToBlob } from '../../utils/request/createMapResponseToBlob';
15
17
  import { createMapResponseToJson } from '../../utils/request/createMapResponseToJson';
@@ -289,11 +291,11 @@ export class MediaStore {
289
291
  }
290
292
 
291
293
  // TODO Create ticket in case Trace Id can be supported through query params
292
- getFileImageURLSync(id, params) {
294
+ getFileImageURLSync(id, params, seededCdnUrl) {
293
295
  const auth = this.resolveInitialAuth();
294
- return this.createFileImageURL(id, auth, params);
296
+ return this.createFileImageURL(id, auth, params, seededCdnUrl);
295
297
  }
296
- createFileImageURL(id, auth, params) {
298
+ createFileImageURL(id, auth, params, seededCdnUrl) {
297
299
  const wmv = fg('confluence_watermark_admin_ui') ? getWatermarkVersionFromToken(auth.token) : undefined;
298
300
  const options = {
299
301
  params: {
@@ -305,6 +307,9 @@ export class MediaStore {
305
307
  auth
306
308
  };
307
309
  const imageEndpoint = cdnFeatureFlag('image');
310
+ if (seededCdnUrl && isCDNEnabled()) {
311
+ return mapToSeedBasedCdnUrl(seededCdnUrl, options.params);
312
+ }
308
313
  if (isPathBasedEnabled()) {
309
314
  return mapToPathBasedUrl(createUrl(`${auth.baseUrl}/file/${id}/${imageEndpoint}`, options));
310
315
  }
@@ -0,0 +1,138 @@
1
+ import { mapMediaItemToFileState } from './file-state';
2
+
3
+ /**
4
+ * Describes the shape of a plain recorded AGG media item as serialized by Confluence SSR.
5
+ * All fields are optional/nullable to tolerate untrusted runtime JSON from window globals.
6
+ *
7
+ * This is the shape as returned by dt-api-filestore `media_items` aggregation.
8
+ */
9
+
10
+ /**
11
+ * Describes a complete SSR media item with id and details.
12
+ * All fields are optional/nullable to tolerate untrusted runtime JSON from window globals.
13
+ */
14
+
15
+ /**
16
+ * Safely coerce a value to a number, returning undefined if the value is null/undefined.
17
+ */
18
+ const toNumber = value => value == null ? undefined : Number(value);
19
+
20
+ /**
21
+ * Convert abuse classification fields to the keyed format expected by FileState,
22
+ * returning undefined if either classification or confidence is missing/falsy.
23
+ */
24
+ const toAbuseClassification = value => {
25
+ if (!value || !value.classification || !value.confidence) {
26
+ return undefined;
27
+ }
28
+ return {
29
+ classification: value.classification,
30
+ confidence: value.confidence
31
+ };
32
+ };
33
+
34
+ /**
35
+ * Convert the `artifactsList` array shape into the keyed `MediaFileArtifacts`
36
+ * dict that `MediaItemDetails` / `FileState` consumers expect.
37
+ *
38
+ * Each artifact is keyed by its `name` (e.g. `'image.png'`, `'thumb_120.jpg'`).
39
+ * Artifacts missing required fields (`name`, `url`, `processingStatus`)
40
+ * are skipped rather than coerced — callers should treat absent artifacts as
41
+ * "not yet available" rather than "failed".
42
+ *
43
+ * NOTE: This assumes AGG returns `name` values matching the canonical
44
+ * `MediaFileArtifacts` key vocabulary. If that assumption is broken, the
45
+ * downstream renderer will silently miss SSR thumbnails — verify with a real
46
+ * payload before relying on SSR previews.
47
+ */
48
+ const toArtifacts = list => {
49
+ const out = {};
50
+ if (!list) {
51
+ return out;
52
+ }
53
+ for (const item of list) {
54
+ if (!item.name || !item.url || !item.processingStatus) {
55
+ continue;
56
+ }
57
+ const artifact = {
58
+ processingStatus: item.processingStatus,
59
+ url: item.url,
60
+ ...(item.mimeType ? {
61
+ mimeType: item.mimeType
62
+ } : {}),
63
+ ...(item.size != null ? {
64
+ size: Number(item.size)
65
+ } : {}),
66
+ ...(item.createdAt != null ? {
67
+ createdAt: Number(item.createdAt)
68
+ } : {})
69
+ };
70
+ out[item.name] = artifact;
71
+ }
72
+ return out;
73
+ };
74
+
75
+ /**
76
+ * Map a plain SSR media item (from AGG / dt-api-filestore) to a `FileState`
77
+ * for seeding `<Card />` / `<MediaInlineCard />`.
78
+ *
79
+ * Returns `undefined` when:
80
+ * - `item` is null/undefined or missing `id`/`details`
81
+ * - any of the required `MediaFile` fields (`name`, `mimeType`, `mediaType`,
82
+ * `processingStatus`) are missing or falsy
83
+ * - `size` is missing or cannot be coerced to a number
84
+ *
85
+ * The transformation reshapes `details.artifactsList` (array, AGG-only) into
86
+ * the keyed `details.artifacts` dict expected by `mapMediaItemToFileState`,
87
+ * and coerces `AGG$Long` numerics.
88
+ *
89
+ * MUST NOT throw on malformed input — always return undefined instead.
90
+ */
91
+ export const mapSsrMediaItemToFileState = item => {
92
+ try {
93
+ var _d$representations, _d$mediaMetadata, _d$preview;
94
+ if (!(item !== null && item !== void 0 && item.id) || !item.details) {
95
+ return undefined;
96
+ }
97
+ const d = item.details;
98
+ const processingStatus = d.processingStatus;
99
+ const mediaType = d.mediaType;
100
+ const size = toNumber(d.size);
101
+ if (!d.name || !d.mimeType || !mediaType || !processingStatus || size === undefined) {
102
+ return undefined;
103
+ }
104
+ const abuseClassification = toAbuseClassification(d.abuseClassification);
105
+ const details = {
106
+ name: d.name,
107
+ mimeType: d.mimeType,
108
+ mediaType: mediaType,
109
+ processingStatus: processingStatus,
110
+ size,
111
+ artifacts: toArtifacts(d.artifactsList),
112
+ representations: (_d$representations = d.representations) !== null && _d$representations !== void 0 && _d$representations.image ? {
113
+ image: {}
114
+ } : {},
115
+ ...(d.failReason ? {
116
+ failReason: d.failReason
117
+ } : {}),
118
+ ...(d.createdAt != null ? {
119
+ createdAt: Number(d.createdAt)
120
+ } : {}),
121
+ ...(((_d$mediaMetadata = d.mediaMetadata) === null || _d$mediaMetadata === void 0 ? void 0 : _d$mediaMetadata.duration) != null ? {
122
+ mediaMetadata: {
123
+ duration: d.mediaMetadata.duration
124
+ }
125
+ } : {}),
126
+ ...(abuseClassification ? {
127
+ abuseClassification
128
+ } : {}),
129
+ ...((_d$preview = d.preview) !== null && _d$preview !== void 0 && _d$preview.cdnUrl ? {
130
+ previewCdnUrl: d.preview.cdnUrl
131
+ } : {})
132
+ };
133
+ return mapMediaItemToFileState(item.id, details);
134
+ } catch {
135
+ // Silently catch any unexpected errors and return undefined
136
+ return undefined;
137
+ }
138
+ };
@@ -0,0 +1,22 @@
1
+ const IMAGE_PARAM_KEYS = new Set(['width', 'height', 'mode', 'allowAnimated', 'upscale', 'version', 'max-age']);
2
+
3
+ /**
4
+ * Adds supported image parameters to a pre-signed CDN asset URL without
5
+ * re-parsing or re-encoding its existing query string.
6
+ *
7
+ * Watermarked CloudFront policies anchor `wm-ari` and `wm-v` as a literal
8
+ * suffix, so parameters must be inserted before `wm-ari`. Non-watermarked
9
+ * policies have a trailing wildcard, so parameters can be appended.
10
+ */
11
+ export const mapToSeedBasedCdnUrl = (seededCdnUrl, params) => {
12
+ const insert = Object.entries(params !== null && params !== void 0 ? params : {}).filter(([key, value]) => value != null && IMAGE_PARAM_KEYS.has(key)).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`).join('&');
13
+ if (!insert) {
14
+ return seededCdnUrl;
15
+ }
16
+ const wm = seededCdnUrl.search(/[?&]wm-ari=/);
17
+ if (wm !== -1) {
18
+ const separator = seededCdnUrl[wm];
19
+ return `${seededCdnUrl.slice(0, wm)}${separator}${insert}&${seededCdnUrl.slice(wm + 1)}`;
20
+ }
21
+ return `${seededCdnUrl}${seededCdnUrl.includes('?') ? '&' : '?'}${insert}`;
22
+ };
@@ -6,4 +6,5 @@ export const MEDIA_CDN_MAP = {
6
6
  // Cloudfront has a hard limit of 8,192 bytes
7
7
  // https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html
8
8
  // Assuming other parts of the URL make up a max of ~1000 (in reality it's lower), the token can be ~7000
9
- export const MEDIA_TOKEN_LENGTH_LIMIT = 7000;
9
+ export const MEDIA_TOKEN_LENGTH_LIMIT = 7000;
10
+ export { isCDNEnabled } from './isCDNEnabled';
@@ -51,8 +51,8 @@ export var MediaClient = /*#__PURE__*/function () {
51
51
  }
52
52
  }, {
53
53
  key: "getImageUrlSync",
54
- value: function getImageUrlSync(id, params) {
55
- return this.mediaStore.getFileImageURLSync(id, params);
54
+ value: function getImageUrlSync(id, params, seededCdnUrl) {
55
+ return this.mediaStore.getFileImageURLSync(id, params, seededCdnUrl);
56
56
  }
57
57
  }, {
58
58
  key: "getClientId",
@@ -13,9 +13,11 @@ import { fg } from '@atlaskit/platform-feature-flags/fg';
13
13
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
14
14
  import { FILE_CACHE_MAX_AGE } from '../../constants';
15
15
  import { getArtifactUrl } from '../../models/artifacts';
16
+ import { isCDNEnabled } from '../../utils/isCDNEnabled';
16
17
  import { isPathBasedEnabled } from '../../utils/isPathBasedEnabled';
17
18
  import { mapToMediaCdnUrl } from '../../utils/mapToMediaCdnUrl';
18
19
  import { mapToPathBasedUrl } from '../../utils/mapToPathBasedUrl';
20
+ import { mapToSeedBasedCdnUrl } from '../../utils/mapToSeedBasedCdnUrl';
19
21
  import { isRequestError, request as _request } from '../../utils/request';
20
22
  import { createMapResponseToBlob } from '../../utils/request/createMapResponseToBlob';
21
23
  import { createMapResponseToJson } from '../../utils/request/createMapResponseToJson';
@@ -434,13 +436,13 @@ export var MediaStore = /*#__PURE__*/function () {
434
436
  }() // TODO Create ticket in case Trace Id can be supported through query params
435
437
  }, {
436
438
  key: "getFileImageURLSync",
437
- value: function getFileImageURLSync(id, params) {
439
+ value: function getFileImageURLSync(id, params, seededCdnUrl) {
438
440
  var auth = this.resolveInitialAuth();
439
- return this.createFileImageURL(id, auth, params);
441
+ return this.createFileImageURL(id, auth, params, seededCdnUrl);
440
442
  }
441
443
  }, {
442
444
  key: "createFileImageURL",
443
- value: function createFileImageURL(id, auth, params) {
445
+ value: function createFileImageURL(id, auth, params, seededCdnUrl) {
444
446
  var wmv = fg('confluence_watermark_admin_ui') ? getWatermarkVersionFromToken(auth.token) : undefined;
445
447
  var options = {
446
448
  params: _objectSpread(_objectSpread({}, extendImageParams(params)), wmv ? {
@@ -449,6 +451,9 @@ export var MediaStore = /*#__PURE__*/function () {
449
451
  auth: auth
450
452
  };
451
453
  var imageEndpoint = cdnFeatureFlag('image');
454
+ if (seededCdnUrl && isCDNEnabled()) {
455
+ return mapToSeedBasedCdnUrl(seededCdnUrl, options.params);
456
+ }
452
457
  if (isPathBasedEnabled()) {
453
458
  return mapToPathBasedUrl(createUrl("".concat(auth.baseUrl, "/file/").concat(id, "/").concat(imageEndpoint), options));
454
459
  }
@@ -0,0 +1,147 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ 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; }
3
+ 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; }
4
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
5
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
6
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
7
+ import { mapMediaItemToFileState } from './file-state';
8
+
9
+ /**
10
+ * Describes the shape of a plain recorded AGG media item as serialized by Confluence SSR.
11
+ * All fields are optional/nullable to tolerate untrusted runtime JSON from window globals.
12
+ *
13
+ * This is the shape as returned by dt-api-filestore `media_items` aggregation.
14
+ */
15
+
16
+ /**
17
+ * Describes a complete SSR media item with id and details.
18
+ * All fields are optional/nullable to tolerate untrusted runtime JSON from window globals.
19
+ */
20
+
21
+ /**
22
+ * Safely coerce a value to a number, returning undefined if the value is null/undefined.
23
+ */
24
+ var toNumber = function toNumber(value) {
25
+ return value == null ? undefined : Number(value);
26
+ };
27
+
28
+ /**
29
+ * Convert abuse classification fields to the keyed format expected by FileState,
30
+ * returning undefined if either classification or confidence is missing/falsy.
31
+ */
32
+ var toAbuseClassification = function toAbuseClassification(value) {
33
+ if (!value || !value.classification || !value.confidence) {
34
+ return undefined;
35
+ }
36
+ return {
37
+ classification: value.classification,
38
+ confidence: value.confidence
39
+ };
40
+ };
41
+
42
+ /**
43
+ * Convert the `artifactsList` array shape into the keyed `MediaFileArtifacts`
44
+ * dict that `MediaItemDetails` / `FileState` consumers expect.
45
+ *
46
+ * Each artifact is keyed by its `name` (e.g. `'image.png'`, `'thumb_120.jpg'`).
47
+ * Artifacts missing required fields (`name`, `url`, `processingStatus`)
48
+ * are skipped rather than coerced — callers should treat absent artifacts as
49
+ * "not yet available" rather than "failed".
50
+ *
51
+ * NOTE: This assumes AGG returns `name` values matching the canonical
52
+ * `MediaFileArtifacts` key vocabulary. If that assumption is broken, the
53
+ * downstream renderer will silently miss SSR thumbnails — verify with a real
54
+ * payload before relying on SSR previews.
55
+ */
56
+ var toArtifacts = function toArtifacts(list) {
57
+ var out = {};
58
+ if (!list) {
59
+ return out;
60
+ }
61
+ var _iterator = _createForOfIteratorHelper(list),
62
+ _step;
63
+ try {
64
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
65
+ var item = _step.value;
66
+ if (!item.name || !item.url || !item.processingStatus) {
67
+ continue;
68
+ }
69
+ var artifact = _objectSpread(_objectSpread(_objectSpread({
70
+ processingStatus: item.processingStatus,
71
+ url: item.url
72
+ }, item.mimeType ? {
73
+ mimeType: item.mimeType
74
+ } : {}), item.size != null ? {
75
+ size: Number(item.size)
76
+ } : {}), item.createdAt != null ? {
77
+ createdAt: Number(item.createdAt)
78
+ } : {});
79
+ out[item.name] = artifact;
80
+ }
81
+ } catch (err) {
82
+ _iterator.e(err);
83
+ } finally {
84
+ _iterator.f();
85
+ }
86
+ return out;
87
+ };
88
+
89
+ /**
90
+ * Map a plain SSR media item (from AGG / dt-api-filestore) to a `FileState`
91
+ * for seeding `<Card />` / `<MediaInlineCard />`.
92
+ *
93
+ * Returns `undefined` when:
94
+ * - `item` is null/undefined or missing `id`/`details`
95
+ * - any of the required `MediaFile` fields (`name`, `mimeType`, `mediaType`,
96
+ * `processingStatus`) are missing or falsy
97
+ * - `size` is missing or cannot be coerced to a number
98
+ *
99
+ * The transformation reshapes `details.artifactsList` (array, AGG-only) into
100
+ * the keyed `details.artifacts` dict expected by `mapMediaItemToFileState`,
101
+ * and coerces `AGG$Long` numerics.
102
+ *
103
+ * MUST NOT throw on malformed input — always return undefined instead.
104
+ */
105
+ export var mapSsrMediaItemToFileState = function mapSsrMediaItemToFileState(item) {
106
+ try {
107
+ var _d$representations, _d$mediaMetadata, _d$preview;
108
+ if (!(item !== null && item !== void 0 && item.id) || !item.details) {
109
+ return undefined;
110
+ }
111
+ var d = item.details;
112
+ var processingStatus = d.processingStatus;
113
+ var mediaType = d.mediaType;
114
+ var size = toNumber(d.size);
115
+ if (!d.name || !d.mimeType || !mediaType || !processingStatus || size === undefined) {
116
+ return undefined;
117
+ }
118
+ var abuseClassification = toAbuseClassification(d.abuseClassification);
119
+ var details = _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
120
+ name: d.name,
121
+ mimeType: d.mimeType,
122
+ mediaType: mediaType,
123
+ processingStatus: processingStatus,
124
+ size: size,
125
+ artifacts: toArtifacts(d.artifactsList),
126
+ representations: (_d$representations = d.representations) !== null && _d$representations !== void 0 && _d$representations.image ? {
127
+ image: {}
128
+ } : {}
129
+ }, d.failReason ? {
130
+ failReason: d.failReason
131
+ } : {}), d.createdAt != null ? {
132
+ createdAt: Number(d.createdAt)
133
+ } : {}), ((_d$mediaMetadata = d.mediaMetadata) === null || _d$mediaMetadata === void 0 ? void 0 : _d$mediaMetadata.duration) != null ? {
134
+ mediaMetadata: {
135
+ duration: d.mediaMetadata.duration
136
+ }
137
+ } : {}), abuseClassification ? {
138
+ abuseClassification: abuseClassification
139
+ } : {}), (_d$preview = d.preview) !== null && _d$preview !== void 0 && _d$preview.cdnUrl ? {
140
+ previewCdnUrl: d.preview.cdnUrl
141
+ } : {});
142
+ return mapMediaItemToFileState(item.id, details);
143
+ } catch (_unused) {
144
+ // Silently catch any unexpected errors and return undefined
145
+ return undefined;
146
+ }
147
+ };
@@ -0,0 +1,33 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ var IMAGE_PARAM_KEYS = new Set(['width', 'height', 'mode', 'allowAnimated', 'upscale', 'version', 'max-age']);
3
+
4
+ /**
5
+ * Adds supported image parameters to a pre-signed CDN asset URL without
6
+ * re-parsing or re-encoding its existing query string.
7
+ *
8
+ * Watermarked CloudFront policies anchor `wm-ari` and `wm-v` as a literal
9
+ * suffix, so parameters must be inserted before `wm-ari`. Non-watermarked
10
+ * policies have a trailing wildcard, so parameters can be appended.
11
+ */
12
+ export var mapToSeedBasedCdnUrl = function mapToSeedBasedCdnUrl(seededCdnUrl, params) {
13
+ var insert = Object.entries(params !== null && params !== void 0 ? params : {}).filter(function (_ref) {
14
+ var _ref2 = _slicedToArray(_ref, 2),
15
+ key = _ref2[0],
16
+ value = _ref2[1];
17
+ return value != null && IMAGE_PARAM_KEYS.has(key);
18
+ }).map(function (_ref3) {
19
+ var _ref4 = _slicedToArray(_ref3, 2),
20
+ key = _ref4[0],
21
+ value = _ref4[1];
22
+ return "".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(String(value)));
23
+ }).join('&');
24
+ if (!insert) {
25
+ return seededCdnUrl;
26
+ }
27
+ var wm = seededCdnUrl.search(/[?&]wm-ari=/);
28
+ if (wm !== -1) {
29
+ var separator = seededCdnUrl[wm];
30
+ return "".concat(seededCdnUrl.slice(0, wm)).concat(separator).concat(insert, "&").concat(seededCdnUrl.slice(wm + 1));
31
+ }
32
+ return "".concat(seededCdnUrl).concat(seededCdnUrl.includes('?') ? '&' : '?').concat(insert);
33
+ };
@@ -6,4 +6,5 @@ export var MEDIA_CDN_MAP = {
6
6
  // Cloudfront has a hard limit of 8,192 bytes
7
7
  // https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html
8
8
  // Assuming other parts of the URL make up a max of ~1000 (in reality it's lower), the token can be ~7000
9
- export var MEDIA_TOKEN_LENGTH_LIMIT = 7000;
9
+ export var MEDIA_TOKEN_LENGTH_LIMIT = 7000;
10
+ export { isCDNEnabled } from './isCDNEnabled';
@@ -23,7 +23,7 @@ export declare class MediaClient {
23
23
  __DO_NOT_USE__getMediaStore(): MediaStore;
24
24
  getImage(id: string, params?: MediaStoreGetFileImageParams, controller?: AbortController, fetchMaxRes?: boolean, traceContext?: MediaTraceContext): Promise<Blob>;
25
25
  getImageUrl(id: string, params?: MediaStoreGetFileImageParams): Promise<string>;
26
- getImageUrlSync(id: string, params?: MediaStoreGetFileImageParams): string;
26
+ getImageUrlSync(id: string, params?: MediaStoreGetFileImageParams, seededCdnUrl?: string): string;
27
27
  getClientId(collectionName?: string): Promise<string | undefined>;
28
28
  getClientIdSync(): string | undefined;
29
29
  getImageMetadata(id: string, params?: MediaStoreGetFileImageParams): Promise<ImageMetadata>;
@@ -26,7 +26,7 @@ export declare class MediaStore implements MediaApi {
26
26
  }): Promise<MediaStoreResponse<TouchedFiles>>;
27
27
  getFile(fileId: string, params?: MediaStoreGetFileParams, traceContext?: MediaTraceContext): Promise<MediaStoreResponse<MediaFile>>;
28
28
  getFileImageURL(id: string, params?: MediaStoreGetFileImageParams): Promise<string>;
29
- getFileImageURLSync(id: string, params?: MediaStoreGetFileImageParams): string;
29
+ getFileImageURLSync(id: string, params?: MediaStoreGetFileImageParams, seededCdnUrl?: string): string;
30
30
  private createFileImageURL;
31
31
  getFileBinary(id: string, collectionName?: string, abortController?: AbortController, maxAge?: number): Promise<Blob>;
32
32
  getFileBinaryURL(id: string, collectionName?: string, maxAge?: number, name?: string): Promise<string>;
@@ -177,7 +177,7 @@ export interface MediaApi {
177
177
  }) => Promise<MediaStoreResponse<TouchedFiles>>;
178
178
  getFile: (fileId: string, params: MediaStoreGetFileParams, traceContext?: MediaTraceContext) => Promise<MediaStoreResponse<MediaFile>>;
179
179
  getFileImageURL: (id: string, params?: MediaStoreGetFileImageParams) => Promise<string>;
180
- getFileImageURLSync: (id: string, params?: MediaStoreGetFileImageParams) => string;
180
+ getFileImageURLSync: (id: string, params?: MediaStoreGetFileImageParams, seededCdnUrl?: string) => string;
181
181
  getFileBinary: (id: string, collectionName?: string, abortController?: AbortController) => Promise<Blob>;
182
182
  getFileBinaryURL: (id: string, collectionName?: string, maxAge?: number, name?: string) => Promise<string>;
183
183
  getArtifactURL: (artifacts: MediaFileArtifacts, artifactName: keyof MediaFileArtifacts, collectionName?: string) => Promise<string>;
@@ -0,0 +1,65 @@
1
+ import type { FileState } from '@atlaskit/media-state/file-state';
2
+ /**
3
+ * Describes the shape of a plain recorded AGG media item as serialized by Confluence SSR.
4
+ * All fields are optional/nullable to tolerate untrusted runtime JSON from window globals.
5
+ *
6
+ * This is the shape as returned by dt-api-filestore `media_items` aggregation.
7
+ */
8
+ export interface SsrMediaItemDetails {
9
+ readonly name?: string | null;
10
+ readonly size?: number | null;
11
+ readonly mimeType?: string | null;
12
+ readonly mediaType?: string | null;
13
+ readonly processingStatus?: string | null;
14
+ readonly failReason?: string | null;
15
+ readonly createdAt?: number | null;
16
+ readonly preview?: {
17
+ readonly cdnUrl?: string | null;
18
+ } | null;
19
+ readonly artifactsList?: ReadonlyArray<{
20
+ readonly createdAt?: number | null;
21
+ readonly mimeType?: string | null;
22
+ readonly name?: string;
23
+ readonly processingStatus?: string | null;
24
+ readonly size?: number | null;
25
+ readonly url?: string | null;
26
+ }> | null;
27
+ readonly representations?: {
28
+ readonly image?: {
29
+ readonly _empty?: boolean | null;
30
+ } | null;
31
+ } | null;
32
+ readonly mediaMetadata?: {
33
+ readonly duration?: number | null;
34
+ } | null;
35
+ readonly abuseClassification?: {
36
+ readonly classification?: string | null;
37
+ readonly confidence?: string | null;
38
+ } | null;
39
+ }
40
+ /**
41
+ * Describes a complete SSR media item with id and details.
42
+ * All fields are optional/nullable to tolerate untrusted runtime JSON from window globals.
43
+ */
44
+ export interface SsrMediaItem {
45
+ readonly id?: string;
46
+ readonly type?: string;
47
+ readonly details?: SsrMediaItemDetails | null;
48
+ }
49
+ /**
50
+ * Map a plain SSR media item (from AGG / dt-api-filestore) to a `FileState`
51
+ * for seeding `<Card />` / `<MediaInlineCard />`.
52
+ *
53
+ * Returns `undefined` when:
54
+ * - `item` is null/undefined or missing `id`/`details`
55
+ * - any of the required `MediaFile` fields (`name`, `mimeType`, `mediaType`,
56
+ * `processingStatus`) are missing or falsy
57
+ * - `size` is missing or cannot be coerced to a number
58
+ *
59
+ * The transformation reshapes `details.artifactsList` (array, AGG-only) into
60
+ * the keyed `details.artifacts` dict expected by `mapMediaItemToFileState`,
61
+ * and coerces `AGG$Long` numerics.
62
+ *
63
+ * MUST NOT throw on malformed input — always return undefined instead.
64
+ */
65
+ export declare const mapSsrMediaItemToFileState: (item: SsrMediaItem | null | undefined) => FileState | undefined;
@@ -0,0 +1,10 @@
1
+ import type { MediaStoreGetFileImageParams } from '../client/media-store/types';
2
+ /**
3
+ * Adds supported image parameters to a pre-signed CDN asset URL without
4
+ * re-parsing or re-encoding its existing query string.
5
+ *
6
+ * Watermarked CloudFront policies anchor `wm-ari` and `wm-v` as a literal
7
+ * suffix, so parameters must be inserted before `wm-ari`. Non-watermarked
8
+ * policies have a trailing wildcard, so parameters can be appended.
9
+ */
10
+ export declare const mapToSeedBasedCdnUrl: (seededCdnUrl: string, params?: MediaStoreGetFileImageParams) => string;
@@ -2,3 +2,4 @@ export declare const MEDIA_CDN_MAP: {
2
2
  [key: string]: string;
3
3
  };
4
4
  export declare const MEDIA_TOKEN_LENGTH_LIMIT: any;
5
+ export { isCDNEnabled } from './isCDNEnabled';
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "@atlaskit/media-client/media-cdn",
3
+ "main": "../dist/cjs/utils/mediaCdn.js",
4
+ "module": "../dist/esm/utils/mediaCdn.js",
5
+ "module:es2019": "../dist/es2019/utils/mediaCdn.js",
6
+ "sideEffects": false,
7
+ "types": "../dist/types/utils/mediaCdn.d.ts"
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/media-client",
3
- "version": "37.6.5",
3
+ "version": "37.7.0",
4
4
  "description": "Media API Web Client Library",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -25,7 +25,7 @@
25
25
  "@atlaskit/chunkinator": "^8.1.0",
26
26
  "@atlaskit/media-common": "^14.6.0",
27
27
  "@atlaskit/platform-feature-flags": "^2.2.0",
28
- "@atlaskit/tmp-editor-statsig": "^173.0.0",
28
+ "@atlaskit/tmp-editor-statsig": "^174.0.0",
29
29
  "@babel/runtime": "^7.0.0",
30
30
  "dataloader": "^2.1.0",
31
31
  "deep-equal": "^1.0.1",
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "@atlaskit/media-client/ssr-media-item",
3
+ "main": "../dist/cjs/models/ssr-media-item.js",
4
+ "module": "../dist/esm/models/ssr-media-item.js",
5
+ "module:es2019": "../dist/es2019/models/ssr-media-item.js",
6
+ "sideEffects": false,
7
+ "types": "../dist/types/models/ssr-media-item.d.ts"
8
+ }