@atlaskit/media-client 37.0.0 → 37.1.1

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,27 @@
1
1
  # @atlaskit/media-client
2
2
 
3
+ ## 37.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`8bac4be486285`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8bac4be486285) -
8
+ Adds a client-side validation guard in media-client's resolveAuth that rejects an auth resolving
9
+ to neither a valid clientId nor a valid asapIssuer, behind the platform_media_validate_client_id
10
+
11
+ ## 37.1.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [`0a00d74d3fe12`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0a00d74d3fe12) -
16
+ Surface the underlying `DOMException` (e.g. `NotReadableError`, `NotFoundError`, `SecurityError`)
17
+ when a `FileReader` fails while hashing an upload, instead of leaking the browser `ProgressEvent`
18
+ which analytics serialised to the opaque `{"isTrusted":true}` error detail. Gated behind
19
+ `platform_media_filereader_error_surfacing`.
20
+
21
+ `@atlaskit/media-client` also exposes the `toFileReaderError` helper via a new
22
+ `@atlaskit/media-client/hashing/file-reader-error` entry point so consumers can normalise
23
+ `FileReader`/`DOMException` failures consistently without duplicating the logic.
24
+
3
25
  ## 37.0.0
4
26
 
5
27
  ### Major Changes
@@ -87,8 +87,14 @@ var resolveAuth = exports.resolveAuth = /*#__PURE__*/function () {
87
87
  }
88
88
  throw new _error.MediaStoreError('emptyAuth');
89
89
  case 6:
90
- return _context.abrupt("return", auth);
90
+ if (!('clientId' in auth && !auth.clientId && (0, _platformFeatureFlags.fg)('platform_media_validate_client_id'))) {
91
+ _context.next = 7;
92
+ break;
93
+ }
94
+ throw new _error.MediaStoreError('emptyClientId');
91
95
  case 7:
96
+ return _context.abrupt("return", auth);
97
+ case 8:
92
98
  case "end":
93
99
  return _context.stop();
94
100
  }
@@ -3,11 +3,23 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.RECENTS_COLLECTION = exports.PROCESSING_BATCH_SIZE = exports.MAX_UPLOAD_FILE_SIZE = exports.MAX_RESOLUTION = exports.FILE_CACHE_MAX_AGE = exports.CHUNK_SIZE = void 0;
6
+ exports.RECENTS_COLLECTION = exports.PROCESSING_BATCH_SIZE = exports.MAX_UPLOAD_FILE_SIZE = exports.MAX_RESOLUTION = exports.FILE_READER_FALLBACK_ERROR_NAME = exports.FILE_CACHE_MAX_AGE = exports.CHUNK_SIZE = void 0;
7
7
  var _media = require("./models/media");
8
8
  var RECENTS_COLLECTION = exports.RECENTS_COLLECTION = 'recents';
9
9
  var FILE_CACHE_MAX_AGE = exports.FILE_CACHE_MAX_AGE = 60 * 60 * 24 * 30; // Retain for 30 days
10
10
  var MAX_RESOLUTION = exports.MAX_RESOLUTION = 4096;
11
11
  var CHUNK_SIZE = exports.CHUNK_SIZE = 5 * _media.DATA_UNIT.MB;
12
12
  var PROCESSING_BATCH_SIZE = exports.PROCESSING_BATCH_SIZE = 1000;
13
- var MAX_UPLOAD_FILE_SIZE = exports.MAX_UPLOAD_FILE_SIZE = 2 * _media.DATA_UNIT.TB;
13
+ var MAX_UPLOAD_FILE_SIZE = exports.MAX_UPLOAD_FILE_SIZE = 2 * _media.DATA_UNIT.TB;
14
+
15
+ /**
16
+ * Sentinel error name used when a `FileReader`/upload failure cannot be attributed
17
+ * to a concrete `DOMException` (e.g. `reader.error` is `null` or has an empty name).
18
+ *
19
+ * This value ends up as the analytics `errorDetail`/`failReason`, so it is an
20
+ * implicit contract that dashboards/SLO filters key off. It lives here (a public
21
+ * `@atlaskit/media-client/constants` entry point) so both media-client and
22
+ * downstream packages (e.g. media-picker) import a single source of truth rather
23
+ * than re-typing the literal and risking analytics bucket drift.
24
+ */
25
+ var FILE_READER_FALLBACK_ERROR_NAME = exports.FILE_READER_FALLBACK_ERROR_NAME = 'FileReaderError';
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.toFileReaderError = void 0;
7
+ var _constants = require("../../constants");
8
+ /**
9
+ * `FileReader.onerror` hands back a `ProgressEvent`, not an `Error`. Rejecting a
10
+ * promise with that event causes downstream analytics (`JSON.stringify`) to
11
+ * collapse it to `{"isTrusted":true}`, hiding the real cause. The actual failure
12
+ * is on `reader.error` as a `DOMException` whose `name` identifies the problem
13
+ * (e.g. `NotReadableError`, `NotFoundError`, `SecurityError`).
14
+ *
15
+ * This converts that `DOMException` into a real `Error` that preserves the name,
16
+ * so the failure stays legible as it travels through the upload pipeline. The
17
+ * original `DOMException` (including its descriptive message) is retained on the
18
+ * `cause` property for debugging — defined non-enumerable, mirroring the native
19
+ * `new Error(message, { cause })` form, so it never leaks into analytics that
20
+ * read `name`/`message` or serialise the error via `JSON.stringify`.
21
+ */
22
+ var toFileReaderError = exports.toFileReaderError = function toFileReaderError(error) {
23
+ var _error$name;
24
+ var name = error !== null && error !== void 0 && (_error$name = error.name) !== null && _error$name !== void 0 && _error$name.trim() ? error.name : _constants.FILE_READER_FALLBACK_ERROR_NAME;
25
+ var normalized = new Error(name);
26
+ normalized.name = name;
27
+ if (error) {
28
+ Object.defineProperty(normalized, 'cause', {
29
+ value: error,
30
+ enumerable: false,
31
+ configurable: true,
32
+ writable: true
33
+ });
34
+ }
35
+ return normalized;
36
+ };
@@ -8,6 +8,8 @@ exports.SimpleHasher = void 0;
8
8
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
9
9
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
10
  var _jsSha = require("js-sha256");
11
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
12
+ var _fileReaderError = require("./fileReaderError");
11
13
  var SimpleHasher = exports.SimpleHasher = /*#__PURE__*/function () {
12
14
  function SimpleHasher() {
13
15
  (0, _classCallCheck2.default)(this, SimpleHasher);
@@ -22,7 +24,13 @@ var SimpleHasher = exports.SimpleHasher = /*#__PURE__*/function () {
22
24
  var _reader$result;
23
25
  resolve("sha256-".concat(_jsSha.sha256.create().update((_reader$result = reader.result) !== null && _reader$result !== void 0 ? _reader$result : '').hex()));
24
26
  };
25
- reader.onerror = reject;
27
+ reader.onerror = function (event) {
28
+ if ((0, _platformFeatureFlags.fg)('platform_media_filereader_error_surfacing')) {
29
+ reject((0, _fileReaderError.toFileReaderError)(reader.error));
30
+ } else {
31
+ reject(event);
32
+ }
33
+ };
26
34
  });
27
35
  }
28
36
  }]);
@@ -9,6 +9,8 @@ exports.SimpleHasher = void 0;
9
9
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
10
10
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
11
11
  var Rusha = _interopRequireWildcard(require("rusha"));
12
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
13
+ var _fileReaderError = require("./fileReaderError");
12
14
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
13
15
  var SimpleHasher = exports.SimpleHasher = /*#__PURE__*/function () {
14
16
  function SimpleHasher() {
@@ -24,7 +26,13 @@ var SimpleHasher = exports.SimpleHasher = /*#__PURE__*/function () {
24
26
  var _reader$result;
25
27
  resolve(Rusha.createHash().update((_reader$result = reader.result) !== null && _reader$result !== void 0 ? _reader$result : '').digest('hex'));
26
28
  };
27
- reader.onerror = reject;
29
+ reader.onerror = function (event) {
30
+ if ((0, _platformFeatureFlags.fg)('platform_media_filereader_error_surfacing')) {
31
+ reject((0, _fileReaderError.toFileReaderError)(reader.error));
32
+ } else {
33
+ reject(event);
34
+ }
35
+ };
28
36
  });
29
37
  }
30
38
  }]);
@@ -58,6 +58,14 @@ export const resolveAuth = async (authProvider, authContext, authProviderTimeout
58
58
  throw new MediaStoreError('emptyAuth');
59
59
  }
60
60
 
61
+ /*
62
+ Only client-based auth carries a clientId. Fail fast when it is present but empty, instead of
63
+ letting the request reach dt-auth and get rejected with `Client id "" is invalid`.
64
+ */
65
+ if ('clientId' in auth && !auth.clientId && fg('platform_media_validate_client_id')) {
66
+ throw new MediaStoreError('emptyClientId');
67
+ }
68
+
61
69
  /*
62
70
  We added a token expiration check here in the past, and then we had to revert due to edge cases in the client that we can't control.
63
71
  Token expiration check in the frontend is a bad idea. Don't do it!
@@ -4,4 +4,16 @@ export const FILE_CACHE_MAX_AGE = 60 * 60 * 24 * 30; // Retain for 30 days
4
4
  export const MAX_RESOLUTION = 4096;
5
5
  export const CHUNK_SIZE = 5 * DATA_UNIT.MB;
6
6
  export const PROCESSING_BATCH_SIZE = 1000;
7
- export const MAX_UPLOAD_FILE_SIZE = 2 * DATA_UNIT.TB;
7
+ export const MAX_UPLOAD_FILE_SIZE = 2 * DATA_UNIT.TB;
8
+
9
+ /**
10
+ * Sentinel error name used when a `FileReader`/upload failure cannot be attributed
11
+ * to a concrete `DOMException` (e.g. `reader.error` is `null` or has an empty name).
12
+ *
13
+ * This value ends up as the analytics `errorDetail`/`failReason`, so it is an
14
+ * implicit contract that dashboards/SLO filters key off. It lives here (a public
15
+ * `@atlaskit/media-client/constants` entry point) so both media-client and
16
+ * downstream packages (e.g. media-picker) import a single source of truth rather
17
+ * than re-typing the literal and risking analytics bucket drift.
18
+ */
19
+ export const FILE_READER_FALLBACK_ERROR_NAME = 'FileReaderError';
@@ -0,0 +1,31 @@
1
+ import { FILE_READER_FALLBACK_ERROR_NAME } from '../../constants';
2
+
3
+ /**
4
+ * `FileReader.onerror` hands back a `ProgressEvent`, not an `Error`. Rejecting a
5
+ * promise with that event causes downstream analytics (`JSON.stringify`) to
6
+ * collapse it to `{"isTrusted":true}`, hiding the real cause. The actual failure
7
+ * is on `reader.error` as a `DOMException` whose `name` identifies the problem
8
+ * (e.g. `NotReadableError`, `NotFoundError`, `SecurityError`).
9
+ *
10
+ * This converts that `DOMException` into a real `Error` that preserves the name,
11
+ * so the failure stays legible as it travels through the upload pipeline. The
12
+ * original `DOMException` (including its descriptive message) is retained on the
13
+ * `cause` property for debugging — defined non-enumerable, mirroring the native
14
+ * `new Error(message, { cause })` form, so it never leaks into analytics that
15
+ * read `name`/`message` or serialise the error via `JSON.stringify`.
16
+ */
17
+ export const toFileReaderError = error => {
18
+ var _error$name;
19
+ const name = error !== null && error !== void 0 && (_error$name = error.name) !== null && _error$name !== void 0 && _error$name.trim() ? error.name : FILE_READER_FALLBACK_ERROR_NAME;
20
+ const normalized = new Error(name);
21
+ normalized.name = name;
22
+ if (error) {
23
+ Object.defineProperty(normalized, 'cause', {
24
+ value: error,
25
+ enumerable: false,
26
+ configurable: true,
27
+ writable: true
28
+ });
29
+ }
30
+ return normalized;
31
+ };
@@ -1,4 +1,6 @@
1
1
  import { sha256 } from 'js-sha256';
2
+ import { fg } from '@atlaskit/platform-feature-flags';
3
+ import { toFileReaderError } from './fileReaderError';
2
4
  export class SimpleHasher {
3
5
  hash(blob) {
4
6
  return new Promise((resolve, reject) => {
@@ -8,7 +10,13 @@ export class SimpleHasher {
8
10
  var _reader$result;
9
11
  resolve(`sha256-${sha256.create().update((_reader$result = reader.result) !== null && _reader$result !== void 0 ? _reader$result : '').hex()}`);
10
12
  };
11
- reader.onerror = reject;
13
+ reader.onerror = event => {
14
+ if (fg('platform_media_filereader_error_surfacing')) {
15
+ reject(toFileReaderError(reader.error));
16
+ } else {
17
+ reject(event);
18
+ }
19
+ };
12
20
  });
13
21
  }
14
22
  }
@@ -1,4 +1,6 @@
1
1
  import * as Rusha from 'rusha';
2
+ import { fg } from '@atlaskit/platform-feature-flags';
3
+ import { toFileReaderError } from './fileReaderError';
2
4
  export class SimpleHasher {
3
5
  hash(blob) {
4
6
  return new Promise((resolve, reject) => {
@@ -8,7 +10,13 @@ export class SimpleHasher {
8
10
  var _reader$result;
9
11
  resolve(Rusha.createHash().update((_reader$result = reader.result) !== null && _reader$result !== void 0 ? _reader$result : '').digest('hex'));
10
12
  };
11
- reader.onerror = reject;
13
+ reader.onerror = event => {
14
+ if (fg('platform_media_filereader_error_surfacing')) {
15
+ reject(toFileReaderError(reader.error));
16
+ } else {
17
+ reject(event);
18
+ }
19
+ };
12
20
  });
13
21
  }
14
22
  }
@@ -80,8 +80,14 @@ export var resolveAuth = /*#__PURE__*/function () {
80
80
  }
81
81
  throw new MediaStoreError('emptyAuth');
82
82
  case 6:
83
- return _context.abrupt("return", auth);
83
+ if (!('clientId' in auth && !auth.clientId && fg('platform_media_validate_client_id'))) {
84
+ _context.next = 7;
85
+ break;
86
+ }
87
+ throw new MediaStoreError('emptyClientId');
84
88
  case 7:
89
+ return _context.abrupt("return", auth);
90
+ case 8:
85
91
  case "end":
86
92
  return _context.stop();
87
93
  }
@@ -4,4 +4,16 @@ export var FILE_CACHE_MAX_AGE = 60 * 60 * 24 * 30; // Retain for 30 days
4
4
  export var MAX_RESOLUTION = 4096;
5
5
  export var CHUNK_SIZE = 5 * DATA_UNIT.MB;
6
6
  export var PROCESSING_BATCH_SIZE = 1000;
7
- export var MAX_UPLOAD_FILE_SIZE = 2 * DATA_UNIT.TB;
7
+ export var MAX_UPLOAD_FILE_SIZE = 2 * DATA_UNIT.TB;
8
+
9
+ /**
10
+ * Sentinel error name used when a `FileReader`/upload failure cannot be attributed
11
+ * to a concrete `DOMException` (e.g. `reader.error` is `null` or has an empty name).
12
+ *
13
+ * This value ends up as the analytics `errorDetail`/`failReason`, so it is an
14
+ * implicit contract that dashboards/SLO filters key off. It lives here (a public
15
+ * `@atlaskit/media-client/constants` entry point) so both media-client and
16
+ * downstream packages (e.g. media-picker) import a single source of truth rather
17
+ * than re-typing the literal and risking analytics bucket drift.
18
+ */
19
+ export var FILE_READER_FALLBACK_ERROR_NAME = 'FileReaderError';
@@ -0,0 +1,31 @@
1
+ import { FILE_READER_FALLBACK_ERROR_NAME } from '../../constants';
2
+
3
+ /**
4
+ * `FileReader.onerror` hands back a `ProgressEvent`, not an `Error`. Rejecting a
5
+ * promise with that event causes downstream analytics (`JSON.stringify`) to
6
+ * collapse it to `{"isTrusted":true}`, hiding the real cause. The actual failure
7
+ * is on `reader.error` as a `DOMException` whose `name` identifies the problem
8
+ * (e.g. `NotReadableError`, `NotFoundError`, `SecurityError`).
9
+ *
10
+ * This converts that `DOMException` into a real `Error` that preserves the name,
11
+ * so the failure stays legible as it travels through the upload pipeline. The
12
+ * original `DOMException` (including its descriptive message) is retained on the
13
+ * `cause` property for debugging — defined non-enumerable, mirroring the native
14
+ * `new Error(message, { cause })` form, so it never leaks into analytics that
15
+ * read `name`/`message` or serialise the error via `JSON.stringify`.
16
+ */
17
+ export var toFileReaderError = function toFileReaderError(error) {
18
+ var _error$name;
19
+ var name = error !== null && error !== void 0 && (_error$name = error.name) !== null && _error$name !== void 0 && _error$name.trim() ? error.name : FILE_READER_FALLBACK_ERROR_NAME;
20
+ var normalized = new Error(name);
21
+ normalized.name = name;
22
+ if (error) {
23
+ Object.defineProperty(normalized, 'cause', {
24
+ value: error,
25
+ enumerable: false,
26
+ configurable: true,
27
+ writable: true
28
+ });
29
+ }
30
+ return normalized;
31
+ };
@@ -1,6 +1,8 @@
1
1
  import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
2
  import _createClass from "@babel/runtime/helpers/createClass";
3
3
  import { sha256 } from 'js-sha256';
4
+ import { fg } from '@atlaskit/platform-feature-flags';
5
+ import { toFileReaderError } from './fileReaderError';
4
6
  export var SimpleHasher = /*#__PURE__*/function () {
5
7
  function SimpleHasher() {
6
8
  _classCallCheck(this, SimpleHasher);
@@ -15,7 +17,13 @@ export var SimpleHasher = /*#__PURE__*/function () {
15
17
  var _reader$result;
16
18
  resolve("sha256-".concat(sha256.create().update((_reader$result = reader.result) !== null && _reader$result !== void 0 ? _reader$result : '').hex()));
17
19
  };
18
- reader.onerror = reject;
20
+ reader.onerror = function (event) {
21
+ if (fg('platform_media_filereader_error_surfacing')) {
22
+ reject(toFileReaderError(reader.error));
23
+ } else {
24
+ reject(event);
25
+ }
26
+ };
19
27
  });
20
28
  }
21
29
  }]);
@@ -1,6 +1,8 @@
1
1
  import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
2
  import _createClass from "@babel/runtime/helpers/createClass";
3
3
  import * as Rusha from 'rusha';
4
+ import { fg } from '@atlaskit/platform-feature-flags';
5
+ import { toFileReaderError } from './fileReaderError';
4
6
  export var SimpleHasher = /*#__PURE__*/function () {
5
7
  function SimpleHasher() {
6
8
  _classCallCheck(this, SimpleHasher);
@@ -15,7 +17,13 @@ export var SimpleHasher = /*#__PURE__*/function () {
15
17
  var _reader$result;
16
18
  resolve(Rusha.createHash().update((_reader$result = reader.result) !== null && _reader$result !== void 0 ? _reader$result : '').digest('hex'));
17
19
  };
18
- reader.onerror = reject;
20
+ reader.onerror = function (event) {
21
+ if (fg('platform_media_filereader_error_surfacing')) {
22
+ reject(toFileReaderError(reader.error));
23
+ } else {
24
+ reject(event);
25
+ }
26
+ };
19
27
  });
20
28
  }
21
29
  }]);
@@ -1,5 +1,5 @@
1
1
  import { BaseMediaClientError } from '../../models/errors';
2
- export type MediaStoreErrorReason = 'failedAuthProvider' | 'tokenExpired' | 'missingInitialAuth' | 'emptyAuth' | 'authProviderTimedOut';
2
+ export type MediaStoreErrorReason = 'failedAuthProvider' | 'tokenExpired' | 'missingInitialAuth' | 'emptyAuth' | 'emptyClientId' | 'authProviderTimedOut';
3
3
  export type MediaStoreErrorAttributes = {
4
4
  readonly reason: MediaStoreErrorReason;
5
5
  readonly innerError?: Error;
@@ -4,3 +4,14 @@ export declare const MAX_RESOLUTION = 4096;
4
4
  export declare const CHUNK_SIZE: number;
5
5
  export declare const PROCESSING_BATCH_SIZE = 1000;
6
6
  export declare const MAX_UPLOAD_FILE_SIZE: number;
7
+ /**
8
+ * Sentinel error name used when a `FileReader`/upload failure cannot be attributed
9
+ * to a concrete `DOMException` (e.g. `reader.error` is `null` or has an empty name).
10
+ *
11
+ * This value ends up as the analytics `errorDetail`/`failReason`, so it is an
12
+ * implicit contract that dashboards/SLO filters key off. It lives here (a public
13
+ * `@atlaskit/media-client/constants` entry point) so both media-client and
14
+ * downstream packages (e.g. media-picker) import a single source of truth rather
15
+ * than re-typing the literal and risking analytics bucket drift.
16
+ */
17
+ export declare const FILE_READER_FALLBACK_ERROR_NAME = "FileReaderError";
@@ -2,7 +2,7 @@ import { type MediaTraceContext } from '@atlaskit/media-common';
2
2
  export interface SerializableObject {
3
3
  [key: string]: string | number | boolean | null | undefined | SerializableObject;
4
4
  }
5
- export type MediaClientErrorReason = 'clientOffline' | 'clientAbortedRequest' | 'clientTimeoutRequest' | 'serverInvalidBody' | 'serverBadRequest' | 'serverUnauthorized' | 'serverForbidden' | 'serverNotFound' | 'serverRateLimited' | 'serverInternalError' | 'serverBadGateway' | 'serverUnexpectedError' | 'serverUnprocessableEntity' | 'serverEntityLocked' | 'failedAuthProvider' | 'tokenExpired' | 'missingInitialAuth' | 'emptyAuth' | 'authProviderTimedOut' | 'invalidFileId' | 'emptyItems' | 'zeroVersionFile' | 'emptyFileName' | 'pollingMaxAttemptsExceeded' | 'fileSizeExceedsLimit' | 'deprecatedEndpoint';
5
+ export type MediaClientErrorReason = 'clientOffline' | 'clientAbortedRequest' | 'clientTimeoutRequest' | 'serverInvalidBody' | 'serverBadRequest' | 'serverUnauthorized' | 'serverForbidden' | 'serverNotFound' | 'serverRateLimited' | 'serverInternalError' | 'serverBadGateway' | 'serverUnexpectedError' | 'serverUnprocessableEntity' | 'serverEntityLocked' | 'failedAuthProvider' | 'tokenExpired' | 'missingInitialAuth' | 'emptyAuth' | 'authProviderTimedOut' | 'emptyClientId' | 'invalidFileId' | 'emptyItems' | 'zeroVersionFile' | 'emptyFileName' | 'pollingMaxAttemptsExceeded' | 'fileSizeExceedsLimit' | 'deprecatedEndpoint';
6
6
  export type MediaClientErrorMetadata = SerializableObject & {
7
7
  traceContext?: MediaTraceContext;
8
8
  };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `FileReader.onerror` hands back a `ProgressEvent`, not an `Error`. Rejecting a
3
+ * promise with that event causes downstream analytics (`JSON.stringify`) to
4
+ * collapse it to `{"isTrusted":true}`, hiding the real cause. The actual failure
5
+ * is on `reader.error` as a `DOMException` whose `name` identifies the problem
6
+ * (e.g. `NotReadableError`, `NotFoundError`, `SecurityError`).
7
+ *
8
+ * This converts that `DOMException` into a real `Error` that preserves the name,
9
+ * so the failure stays legible as it travels through the upload pipeline. The
10
+ * original `DOMException` (including its descriptive message) is retained on the
11
+ * `cause` property for debugging — defined non-enumerable, mirroring the native
12
+ * `new Error(message, { cause })` form, so it never leaks into analytics that
13
+ * read `name`/`message` or serialise the error via `JSON.stringify`.
14
+ */
15
+ export declare const toFileReaderError: (error: DOMException | null) => Error;
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "@atlaskit/media-client/hashing/file-reader-error",
3
+ "main": "../../dist/cjs/utils/hashing/fileReaderError.js",
4
+ "module": "../../dist/esm/utils/hashing/fileReaderError.js",
5
+ "module:es2019": "../../dist/es2019/utils/hashing/fileReaderError.js",
6
+ "sideEffects": false,
7
+ "types": "../../dist/types/utils/hashing/fileReaderError.d.ts"
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/media-client",
3
- "version": "37.0.0",
3
+ "version": "37.1.1",
4
4
  "description": "Media API Web Client Library",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -23,7 +23,7 @@
23
23
  "dependencies": {
24
24
  "@atlaskit/atlassian-context": "^1.0.0",
25
25
  "@atlaskit/chunkinator": "^8.0.0",
26
- "@atlaskit/media-common": "^14.0.0",
26
+ "@atlaskit/media-common": "^14.1.0",
27
27
  "@atlaskit/platform-feature-flags": "^2.0.0",
28
28
  "@babel/runtime": "^7.0.0",
29
29
  "dataloader": "^2.1.0",
@@ -85,11 +85,18 @@
85
85
  "platform_media_auth_provider_analytics": {
86
86
  "type": "boolean"
87
87
  },
88
+ "platform_media_validate_client_id": {
89
+ "type": "boolean"
90
+ },
88
91
  "confluence_watermark_admin_ui": {
89
92
  "type": "boolean"
90
93
  },
91
94
  "platform_media_upload_expected_size_header": {
92
95
  "type": "boolean"
96
+ },
97
+ "platform_media_filereader_error_surfacing": {
98
+ "type": "boolean",
99
+ "referenceOnly": true
93
100
  }
94
101
  }
95
102
  }