@atlaskit/media-client 35.6.1 → 35.7.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 +15 -0
- package/dist/cjs/client/media-store/resolveAuth.js +58 -15
- package/dist/es2019/client/media-store/resolveAuth.js +44 -1
- package/dist/esm/client/media-store/resolveAuth.js +58 -15
- package/dist/types/client/events.d.ts +15 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types-ts4.5/client/events.d.ts +15 -0
- package/dist/types-ts4.5/index.d.ts +1 -1
- package/package.json +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @atlaskit/media-client
|
|
2
2
|
|
|
3
|
+
## 35.7.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`5f53f075991b4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/5f53f075991b4) -
|
|
8
|
+
Updated archive viewer to emit media-viewed event on child file download
|
|
9
|
+
|
|
10
|
+
## 35.7.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- [`a9118006d1586`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/a9118006d1586) -
|
|
15
|
+
Add auth provider analytics events via globalMediaEventEmitter behind
|
|
16
|
+
platform_media_auth_provider_analytics feature flag.
|
|
17
|
+
|
|
3
18
|
## 35.6.1
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
|
@@ -7,48 +7,91 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.resolveInitialAuth = exports.resolveAuth = exports.DEFAULT_AUTH_PROVIDER_TIMEOUT = void 0;
|
|
8
8
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
9
9
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
10
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
10
11
|
var _error = require("./error");
|
|
11
12
|
var _setTimeoutPromise = require("../../utils/setTimeoutPromise");
|
|
13
|
+
var _globalMediaEventEmitter = require("../../globalMediaEventEmitter");
|
|
12
14
|
var DEFAULT_AUTH_PROVIDER_TIMEOUT = exports.DEFAULT_AUTH_PROVIDER_TIMEOUT = 10000;
|
|
13
15
|
var resolveAuth = exports.resolveAuth = /*#__PURE__*/function () {
|
|
14
16
|
var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(authProvider, authContext) {
|
|
15
17
|
var authProviderTimeout,
|
|
18
|
+
startTime,
|
|
19
|
+
eventEmitted,
|
|
20
|
+
authProviderPromise,
|
|
16
21
|
auth,
|
|
17
22
|
_args = arguments;
|
|
18
23
|
return _regenerator.default.wrap(function _callee$(_context) {
|
|
19
24
|
while (1) switch (_context.prev = _context.next) {
|
|
20
25
|
case 0:
|
|
21
26
|
authProviderTimeout = _args.length > 2 && _args[2] !== undefined ? _args[2] : DEFAULT_AUTH_PROVIDER_TIMEOUT;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
startTime = performance.now();
|
|
28
|
+
eventEmitted = false; // Feature flag: wrap authProvider with analytics event emission
|
|
29
|
+
authProviderPromise = (0, _platformFeatureFlags.fg)('platform_media_auth_provider_analytics') ? authProvider(authContext).then(function (result) {
|
|
30
|
+
var durationMs = performance.now() - startTime;
|
|
31
|
+
if (!eventEmitted) {
|
|
32
|
+
eventEmitted = true;
|
|
33
|
+
_globalMediaEventEmitter.globalMediaEventEmitter.emit('auth-provider-succeeded', {
|
|
34
|
+
durationMs: durationMs,
|
|
35
|
+
timeoutMs: authProviderTimeout,
|
|
36
|
+
authContext: authContext
|
|
37
|
+
});
|
|
38
|
+
} else {
|
|
39
|
+
// Timeout already fired - auth arrived too late
|
|
40
|
+
var timeoutError = new _error.MediaStoreError('authProviderTimedOut');
|
|
41
|
+
_globalMediaEventEmitter.globalMediaEventEmitter.emit('auth-provider-failed', {
|
|
42
|
+
durationMs: durationMs,
|
|
43
|
+
timeoutMs: authProviderTimeout,
|
|
44
|
+
authContext: authContext,
|
|
45
|
+
error: timeoutError
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}).catch(function (error) {
|
|
50
|
+
var durationMs = performance.now() - startTime;
|
|
51
|
+
eventEmitted = true;
|
|
52
|
+
_globalMediaEventEmitter.globalMediaEventEmitter.emit('auth-provider-failed', {
|
|
53
|
+
durationMs: durationMs,
|
|
54
|
+
timeoutMs: authProviderTimeout,
|
|
55
|
+
authContext: authContext,
|
|
56
|
+
error: error
|
|
57
|
+
});
|
|
58
|
+
throw error;
|
|
59
|
+
}) : authProvider(authContext); // Original behavior when FG off
|
|
60
|
+
_context.prev = 4;
|
|
61
|
+
_context.next = 7;
|
|
62
|
+
return Promise.race([authProviderPromise, (0, _setTimeoutPromise.rejectTimeout)(authProviderTimeout, new _error.MediaStoreError('authProviderTimedOut'))]);
|
|
63
|
+
case 7:
|
|
26
64
|
auth = _context.sent;
|
|
27
|
-
_context.next =
|
|
65
|
+
_context.next = 16;
|
|
28
66
|
break;
|
|
29
|
-
case
|
|
30
|
-
_context.prev =
|
|
31
|
-
_context.t0 = _context["catch"](
|
|
67
|
+
case 10:
|
|
68
|
+
_context.prev = 10;
|
|
69
|
+
_context.t0 = _context["catch"](4);
|
|
70
|
+
// Mark as emitted so late arrivals are handled correctly by .then()/.catch()
|
|
71
|
+
if (!eventEmitted && (0, _platformFeatureFlags.fg)('platform_media_auth_provider_analytics')) {
|
|
72
|
+
eventEmitted = true;
|
|
73
|
+
}
|
|
74
|
+
// PRESERVE ORIGINAL ERROR HANDLING
|
|
32
75
|
if (!(_context.t0 instanceof _error.MediaStoreError)) {
|
|
33
|
-
_context.next =
|
|
76
|
+
_context.next = 15;
|
|
34
77
|
break;
|
|
35
78
|
}
|
|
36
79
|
throw _context.t0;
|
|
37
|
-
case
|
|
80
|
+
case 15:
|
|
38
81
|
throw new _error.MediaStoreError('failedAuthProvider', _context.t0 instanceof Error ? _context.t0 : undefined);
|
|
39
|
-
case
|
|
82
|
+
case 16:
|
|
40
83
|
if (auth) {
|
|
41
|
-
_context.next =
|
|
84
|
+
_context.next = 18;
|
|
42
85
|
break;
|
|
43
86
|
}
|
|
44
87
|
throw new _error.MediaStoreError('emptyAuth');
|
|
45
|
-
case
|
|
88
|
+
case 18:
|
|
46
89
|
return _context.abrupt("return", auth);
|
|
47
|
-
case
|
|
90
|
+
case 19:
|
|
48
91
|
case "end":
|
|
49
92
|
return _context.stop();
|
|
50
93
|
}
|
|
51
|
-
}, _callee, null, [[
|
|
94
|
+
}, _callee, null, [[4, 10]]);
|
|
52
95
|
}));
|
|
53
96
|
return function resolveAuth(_x, _x2) {
|
|
54
97
|
return _ref.apply(this, arguments);
|
|
@@ -1,11 +1,54 @@
|
|
|
1
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
1
2
|
import { MediaStoreError } from './error';
|
|
2
3
|
import { rejectTimeout } from '../../utils/setTimeoutPromise';
|
|
4
|
+
import { globalMediaEventEmitter } from '../../globalMediaEventEmitter';
|
|
3
5
|
export const DEFAULT_AUTH_PROVIDER_TIMEOUT = 10000;
|
|
4
6
|
export const resolveAuth = async (authProvider, authContext, authProviderTimeout = DEFAULT_AUTH_PROVIDER_TIMEOUT) => {
|
|
7
|
+
const startTime = performance.now();
|
|
8
|
+
let eventEmitted = false;
|
|
9
|
+
|
|
10
|
+
// Feature flag: wrap authProvider with analytics event emission
|
|
11
|
+
const authProviderPromise = fg('platform_media_auth_provider_analytics') ? authProvider(authContext).then(result => {
|
|
12
|
+
const durationMs = performance.now() - startTime;
|
|
13
|
+
if (!eventEmitted) {
|
|
14
|
+
eventEmitted = true;
|
|
15
|
+
globalMediaEventEmitter.emit('auth-provider-succeeded', {
|
|
16
|
+
durationMs,
|
|
17
|
+
timeoutMs: authProviderTimeout,
|
|
18
|
+
authContext
|
|
19
|
+
});
|
|
20
|
+
} else {
|
|
21
|
+
// Timeout already fired - auth arrived too late
|
|
22
|
+
const timeoutError = new MediaStoreError('authProviderTimedOut');
|
|
23
|
+
globalMediaEventEmitter.emit('auth-provider-failed', {
|
|
24
|
+
durationMs,
|
|
25
|
+
timeoutMs: authProviderTimeout,
|
|
26
|
+
authContext,
|
|
27
|
+
error: timeoutError
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
}).catch(error => {
|
|
32
|
+
const durationMs = performance.now() - startTime;
|
|
33
|
+
eventEmitted = true;
|
|
34
|
+
globalMediaEventEmitter.emit('auth-provider-failed', {
|
|
35
|
+
durationMs,
|
|
36
|
+
timeoutMs: authProviderTimeout,
|
|
37
|
+
authContext,
|
|
38
|
+
error
|
|
39
|
+
});
|
|
40
|
+
throw error;
|
|
41
|
+
}) : authProvider(authContext); // Original behavior when FG off
|
|
42
|
+
|
|
5
43
|
let auth;
|
|
6
44
|
try {
|
|
7
|
-
auth = await Promise.race([
|
|
45
|
+
auth = await Promise.race([authProviderPromise, rejectTimeout(authProviderTimeout, new MediaStoreError('authProviderTimedOut'))]);
|
|
8
46
|
} catch (err) {
|
|
47
|
+
// Mark as emitted so late arrivals are handled correctly by .then()/.catch()
|
|
48
|
+
if (!eventEmitted && fg('platform_media_auth_provider_analytics')) {
|
|
49
|
+
eventEmitted = true;
|
|
50
|
+
}
|
|
51
|
+
// PRESERVE ORIGINAL ERROR HANDLING
|
|
9
52
|
if (err instanceof MediaStoreError) {
|
|
10
53
|
throw err;
|
|
11
54
|
}
|
|
@@ -1,47 +1,90 @@
|
|
|
1
1
|
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
2
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
3
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
3
4
|
import { MediaStoreError } from './error';
|
|
4
5
|
import { rejectTimeout } from '../../utils/setTimeoutPromise';
|
|
6
|
+
import { globalMediaEventEmitter } from '../../globalMediaEventEmitter';
|
|
5
7
|
export var DEFAULT_AUTH_PROVIDER_TIMEOUT = 10000;
|
|
6
8
|
export var resolveAuth = /*#__PURE__*/function () {
|
|
7
9
|
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(authProvider, authContext) {
|
|
8
10
|
var authProviderTimeout,
|
|
11
|
+
startTime,
|
|
12
|
+
eventEmitted,
|
|
13
|
+
authProviderPromise,
|
|
9
14
|
auth,
|
|
10
15
|
_args = arguments;
|
|
11
16
|
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
12
17
|
while (1) switch (_context.prev = _context.next) {
|
|
13
18
|
case 0:
|
|
14
19
|
authProviderTimeout = _args.length > 2 && _args[2] !== undefined ? _args[2] : DEFAULT_AUTH_PROVIDER_TIMEOUT;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
startTime = performance.now();
|
|
21
|
+
eventEmitted = false; // Feature flag: wrap authProvider with analytics event emission
|
|
22
|
+
authProviderPromise = fg('platform_media_auth_provider_analytics') ? authProvider(authContext).then(function (result) {
|
|
23
|
+
var durationMs = performance.now() - startTime;
|
|
24
|
+
if (!eventEmitted) {
|
|
25
|
+
eventEmitted = true;
|
|
26
|
+
globalMediaEventEmitter.emit('auth-provider-succeeded', {
|
|
27
|
+
durationMs: durationMs,
|
|
28
|
+
timeoutMs: authProviderTimeout,
|
|
29
|
+
authContext: authContext
|
|
30
|
+
});
|
|
31
|
+
} else {
|
|
32
|
+
// Timeout already fired - auth arrived too late
|
|
33
|
+
var timeoutError = new MediaStoreError('authProviderTimedOut');
|
|
34
|
+
globalMediaEventEmitter.emit('auth-provider-failed', {
|
|
35
|
+
durationMs: durationMs,
|
|
36
|
+
timeoutMs: authProviderTimeout,
|
|
37
|
+
authContext: authContext,
|
|
38
|
+
error: timeoutError
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}).catch(function (error) {
|
|
43
|
+
var durationMs = performance.now() - startTime;
|
|
44
|
+
eventEmitted = true;
|
|
45
|
+
globalMediaEventEmitter.emit('auth-provider-failed', {
|
|
46
|
+
durationMs: durationMs,
|
|
47
|
+
timeoutMs: authProviderTimeout,
|
|
48
|
+
authContext: authContext,
|
|
49
|
+
error: error
|
|
50
|
+
});
|
|
51
|
+
throw error;
|
|
52
|
+
}) : authProvider(authContext); // Original behavior when FG off
|
|
53
|
+
_context.prev = 4;
|
|
54
|
+
_context.next = 7;
|
|
55
|
+
return Promise.race([authProviderPromise, rejectTimeout(authProviderTimeout, new MediaStoreError('authProviderTimedOut'))]);
|
|
56
|
+
case 7:
|
|
19
57
|
auth = _context.sent;
|
|
20
|
-
_context.next =
|
|
58
|
+
_context.next = 16;
|
|
21
59
|
break;
|
|
22
|
-
case
|
|
23
|
-
_context.prev =
|
|
24
|
-
_context.t0 = _context["catch"](
|
|
60
|
+
case 10:
|
|
61
|
+
_context.prev = 10;
|
|
62
|
+
_context.t0 = _context["catch"](4);
|
|
63
|
+
// Mark as emitted so late arrivals are handled correctly by .then()/.catch()
|
|
64
|
+
if (!eventEmitted && fg('platform_media_auth_provider_analytics')) {
|
|
65
|
+
eventEmitted = true;
|
|
66
|
+
}
|
|
67
|
+
// PRESERVE ORIGINAL ERROR HANDLING
|
|
25
68
|
if (!(_context.t0 instanceof MediaStoreError)) {
|
|
26
|
-
_context.next =
|
|
69
|
+
_context.next = 15;
|
|
27
70
|
break;
|
|
28
71
|
}
|
|
29
72
|
throw _context.t0;
|
|
30
|
-
case
|
|
73
|
+
case 15:
|
|
31
74
|
throw new MediaStoreError('failedAuthProvider', _context.t0 instanceof Error ? _context.t0 : undefined);
|
|
32
|
-
case
|
|
75
|
+
case 16:
|
|
33
76
|
if (auth) {
|
|
34
|
-
_context.next =
|
|
77
|
+
_context.next = 18;
|
|
35
78
|
break;
|
|
36
79
|
}
|
|
37
80
|
throw new MediaStoreError('emptyAuth');
|
|
38
|
-
case
|
|
81
|
+
case 18:
|
|
39
82
|
return _context.abrupt("return", auth);
|
|
40
|
-
case
|
|
83
|
+
case 19:
|
|
41
84
|
case "end":
|
|
42
85
|
return _context.stop();
|
|
43
86
|
}
|
|
44
|
-
}, _callee, null, [[
|
|
87
|
+
}, _callee, null, [[4, 10]]);
|
|
45
88
|
}));
|
|
46
89
|
return function resolveAuth(_x, _x2) {
|
|
47
90
|
return _ref.apply(this, arguments);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type FileState } from '@atlaskit/media-state';
|
|
2
|
+
import { type AuthContext } from '@atlaskit/media-core';
|
|
2
3
|
export type EventPayloadMap<P> = {
|
|
3
4
|
readonly [event: string]: P;
|
|
4
5
|
};
|
|
@@ -7,8 +8,22 @@ export interface MediaViewedEventPayload {
|
|
|
7
8
|
fileId: string;
|
|
8
9
|
viewingLevel: 'minimal' | 'full' | 'download';
|
|
9
10
|
isUserCollection?: boolean;
|
|
11
|
+
childFileName?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface AuthProviderSucceededEventPayload {
|
|
14
|
+
durationMs: number;
|
|
15
|
+
timeoutMs: number;
|
|
16
|
+
authContext?: AuthContext;
|
|
17
|
+
}
|
|
18
|
+
export interface AuthProviderFailedEventPayload {
|
|
19
|
+
durationMs: number;
|
|
20
|
+
timeoutMs: number;
|
|
21
|
+
authContext?: AuthContext;
|
|
22
|
+
error: Error;
|
|
10
23
|
}
|
|
11
24
|
export type UploadEventPayloadMap = {
|
|
12
25
|
'file-added': FileState;
|
|
13
26
|
'media-viewed': MediaViewedEventPayload;
|
|
27
|
+
'auth-provider-succeeded': AuthProviderSucceededEventPayload;
|
|
28
|
+
'auth-provider-failed': AuthProviderFailedEventPayload;
|
|
14
29
|
};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export type { Dimensions } from './utils/getDimensionsFromBlob';
|
|
|
33
33
|
export { createMediaSubject } from './utils/createMediaSubject';
|
|
34
34
|
export { isFileIdentifier, isExternalImageIdentifier, isDifferentIdentifier } from './identifier';
|
|
35
35
|
export type { Identifier, FileIdentifier, ExternalImageIdentifier } from './identifier';
|
|
36
|
-
export type { EventPayloadListener, UploadEventPayloadMap, MediaViewedEventPayload, } from './client/events';
|
|
36
|
+
export type { EventPayloadListener, UploadEventPayloadMap, MediaViewedEventPayload, AuthProviderSucceededEventPayload, AuthProviderFailedEventPayload, } from './client/events';
|
|
37
37
|
export type { MediaClientConfig } from '@atlaskit/media-core';
|
|
38
38
|
export { globalMediaEventEmitter } from './globalMediaEventEmitter';
|
|
39
39
|
export { isMediaBlobUrl, getAttrsFromUrl, addFileAttrsToUrl, objectToQueryString, } from './utils/url';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type FileState } from '@atlaskit/media-state';
|
|
2
|
+
import { type AuthContext } from '@atlaskit/media-core';
|
|
2
3
|
export type EventPayloadMap<P> = {
|
|
3
4
|
readonly [event: string]: P;
|
|
4
5
|
};
|
|
@@ -7,8 +8,22 @@ export interface MediaViewedEventPayload {
|
|
|
7
8
|
fileId: string;
|
|
8
9
|
viewingLevel: 'minimal' | 'full' | 'download';
|
|
9
10
|
isUserCollection?: boolean;
|
|
11
|
+
childFileName?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface AuthProviderSucceededEventPayload {
|
|
14
|
+
durationMs: number;
|
|
15
|
+
timeoutMs: number;
|
|
16
|
+
authContext?: AuthContext;
|
|
17
|
+
}
|
|
18
|
+
export interface AuthProviderFailedEventPayload {
|
|
19
|
+
durationMs: number;
|
|
20
|
+
timeoutMs: number;
|
|
21
|
+
authContext?: AuthContext;
|
|
22
|
+
error: Error;
|
|
10
23
|
}
|
|
11
24
|
export type UploadEventPayloadMap = {
|
|
12
25
|
'file-added': FileState;
|
|
13
26
|
'media-viewed': MediaViewedEventPayload;
|
|
27
|
+
'auth-provider-succeeded': AuthProviderSucceededEventPayload;
|
|
28
|
+
'auth-provider-failed': AuthProviderFailedEventPayload;
|
|
14
29
|
};
|
|
@@ -33,7 +33,7 @@ export type { Dimensions } from './utils/getDimensionsFromBlob';
|
|
|
33
33
|
export { createMediaSubject } from './utils/createMediaSubject';
|
|
34
34
|
export { isFileIdentifier, isExternalImageIdentifier, isDifferentIdentifier } from './identifier';
|
|
35
35
|
export type { Identifier, FileIdentifier, ExternalImageIdentifier } from './identifier';
|
|
36
|
-
export type { EventPayloadListener, UploadEventPayloadMap, MediaViewedEventPayload, } from './client/events';
|
|
36
|
+
export type { EventPayloadListener, UploadEventPayloadMap, MediaViewedEventPayload, AuthProviderSucceededEventPayload, AuthProviderFailedEventPayload, } from './client/events';
|
|
37
37
|
export type { MediaClientConfig } from '@atlaskit/media-core';
|
|
38
38
|
export { globalMediaEventEmitter } from './globalMediaEventEmitter';
|
|
39
39
|
export { isMediaBlobUrl, getAttrsFromUrl, addFileAttrsToUrl, objectToQueryString, } from './utils/url';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/media-client",
|
|
3
|
-
"version": "35.
|
|
3
|
+
"version": "35.7.1",
|
|
4
4
|
"description": "Media API Web Client Library",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@atlaskit/media-core": "^37.0.0",
|
|
54
54
|
"@atlaskit/media-state": "^1.8.0",
|
|
55
55
|
"@atlaskit/ssr": "workspace:^",
|
|
56
|
-
"@atlaskit/tokens": "^
|
|
56
|
+
"@atlaskit/tokens": "^9.0.0",
|
|
57
57
|
"@atlassian/feature-flags-test-utils": "^1.0.0",
|
|
58
58
|
"@emotion/react": "^11.7.1",
|
|
59
59
|
"@types/deep-equal": "^1.0.1",
|
|
@@ -87,6 +87,9 @@
|
|
|
87
87
|
},
|
|
88
88
|
"platform_media_retry_edge_error": {
|
|
89
89
|
"type": "boolean"
|
|
90
|
+
},
|
|
91
|
+
"platform_media_auth_provider_analytics": {
|
|
92
|
+
"type": "boolean"
|
|
90
93
|
}
|
|
91
94
|
}
|
|
92
95
|
}
|