@webex/webex-core 2.59.3-next.1 → 2.59.4
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/.eslintrc.js +6 -6
- package/README.md +79 -79
- package/babel.config.js +3 -3
- package/dist/config.js +24 -24
- package/dist/config.js.map +1 -1
- package/dist/credentials-config.js +56 -56
- package/dist/credentials-config.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interceptors/auth.js +28 -28
- package/dist/interceptors/auth.js.map +1 -1
- package/dist/interceptors/default-options.js +24 -24
- package/dist/interceptors/default-options.js.map +1 -1
- package/dist/interceptors/embargo.js +9 -9
- package/dist/interceptors/embargo.js.map +1 -1
- package/dist/interceptors/network-timing.js +19 -19
- package/dist/interceptors/network-timing.js.map +1 -1
- package/dist/interceptors/payload-transformer.js +19 -19
- package/dist/interceptors/payload-transformer.js.map +1 -1
- package/dist/interceptors/rate-limit.js +40 -40
- package/dist/interceptors/rate-limit.js.map +1 -1
- package/dist/interceptors/redirect.js +13 -13
- package/dist/interceptors/redirect.js.map +1 -1
- package/dist/interceptors/request-event.js +23 -23
- package/dist/interceptors/request-event.js.map +1 -1
- package/dist/interceptors/request-logger.js +13 -13
- package/dist/interceptors/request-logger.js.map +1 -1
- package/dist/interceptors/request-timing.js +23 -23
- package/dist/interceptors/request-timing.js.map +1 -1
- package/dist/interceptors/response-logger.js +19 -19
- package/dist/interceptors/response-logger.js.map +1 -1
- package/dist/interceptors/user-agent.js +29 -29
- package/dist/interceptors/user-agent.js.map +1 -1
- package/dist/interceptors/webex-tracking-id.js +15 -15
- package/dist/interceptors/webex-tracking-id.js.map +1 -1
- package/dist/interceptors/webex-user-agent.js +13 -13
- package/dist/interceptors/webex-user-agent.js.map +1 -1
- package/dist/lib/batcher.js +83 -83
- package/dist/lib/batcher.js.map +1 -1
- package/dist/lib/credentials/credentials.js +103 -103
- package/dist/lib/credentials/credentials.js.map +1 -1
- package/dist/lib/credentials/grant-errors.js +17 -17
- package/dist/lib/credentials/grant-errors.js.map +1 -1
- package/dist/lib/credentials/index.js +2 -2
- package/dist/lib/credentials/index.js.map +1 -1
- package/dist/lib/credentials/scope.js +11 -11
- package/dist/lib/credentials/scope.js.map +1 -1
- package/dist/lib/credentials/token-collection.js +2 -2
- package/dist/lib/credentials/token-collection.js.map +1 -1
- package/dist/lib/credentials/token.js +145 -145
- package/dist/lib/credentials/token.js.map +1 -1
- package/dist/lib/page.js +49 -49
- package/dist/lib/page.js.map +1 -1
- package/dist/lib/services/constants.js.map +1 -1
- package/dist/lib/services/index.js +2 -2
- package/dist/lib/services/index.js.map +1 -1
- package/dist/lib/services/interceptors/server-error.js +9 -9
- package/dist/lib/services/interceptors/server-error.js.map +1 -1
- package/dist/lib/services/interceptors/service.js +24 -24
- package/dist/lib/services/interceptors/service.js.map +1 -1
- package/dist/lib/services/metrics.js.map +1 -1
- package/dist/lib/services/service-catalog.js +104 -104
- package/dist/lib/services/service-catalog.js.map +1 -1
- package/dist/lib/services/service-fed-ramp.js.map +1 -1
- package/dist/lib/services/service-host.js +134 -134
- package/dist/lib/services/service-host.js.map +1 -1
- package/dist/lib/services/service-registry.js +175 -175
- package/dist/lib/services/service-registry.js.map +1 -1
- package/dist/lib/services/service-state.js +38 -38
- package/dist/lib/services/service-state.js.map +1 -1
- package/dist/lib/services/service-url.js +31 -31
- package/dist/lib/services/service-url.js.map +1 -1
- package/dist/lib/services/services.js +245 -245
- package/dist/lib/services/services.js.map +1 -1
- package/dist/lib/stateless-webex-plugin.js +28 -28
- package/dist/lib/stateless-webex-plugin.js.map +1 -1
- package/dist/lib/storage/decorators.js +27 -27
- package/dist/lib/storage/decorators.js.map +1 -1
- package/dist/lib/storage/errors.js +4 -4
- package/dist/lib/storage/errors.js.map +1 -1
- package/dist/lib/storage/index.js.map +1 -1
- package/dist/lib/storage/make-webex-plugin-store.js +44 -44
- package/dist/lib/storage/make-webex-plugin-store.js.map +1 -1
- package/dist/lib/storage/make-webex-store.js +40 -40
- package/dist/lib/storage/make-webex-store.js.map +1 -1
- package/dist/lib/storage/memory-store-adapter.js +9 -9
- package/dist/lib/storage/memory-store-adapter.js.map +1 -1
- package/dist/lib/webex-core-plugin-mixin.js +13 -13
- package/dist/lib/webex-core-plugin-mixin.js.map +1 -1
- package/dist/lib/webex-http-error.js +9 -9
- package/dist/lib/webex-http-error.js.map +1 -1
- package/dist/lib/webex-internal-core-plugin-mixin.js +13 -13
- package/dist/lib/webex-internal-core-plugin-mixin.js.map +1 -1
- package/dist/lib/webex-plugin.js +36 -36
- package/dist/lib/webex-plugin.js.map +1 -1
- package/dist/plugins/logger.js +9 -9
- package/dist/plugins/logger.js.map +1 -1
- package/dist/webex-core.js +104 -104
- package/dist/webex-core.js.map +1 -1
- package/dist/webex-internal-core.js +12 -12
- package/dist/webex-internal-core.js.map +1 -1
- package/jest.config.js +3 -3
- package/package.json +19 -20
- package/process +1 -1
- package/src/config.js +90 -90
- package/src/credentials-config.js +212 -212
- package/src/index.js +62 -62
- package/src/interceptors/auth.js +186 -186
- package/src/interceptors/default-options.js +55 -55
- package/src/interceptors/embargo.js +43 -43
- package/src/interceptors/network-timing.js +54 -54
- package/src/interceptors/payload-transformer.js +55 -55
- package/src/interceptors/rate-limit.js +169 -169
- package/src/interceptors/redirect.js +106 -106
- package/src/interceptors/request-event.js +93 -93
- package/src/interceptors/request-logger.js +78 -78
- package/src/interceptors/request-timing.js +65 -65
- package/src/interceptors/response-logger.js +98 -98
- package/src/interceptors/user-agent.js +77 -77
- package/src/interceptors/webex-tracking-id.js +73 -73
- package/src/interceptors/webex-user-agent.js +79 -79
- package/src/lib/batcher.js +307 -307
- package/src/lib/credentials/credentials.js +552 -552
- package/src/lib/credentials/grant-errors.js +92 -92
- package/src/lib/credentials/index.js +16 -16
- package/src/lib/credentials/scope.js +34 -34
- package/src/lib/credentials/token-collection.js +17 -17
- package/src/lib/credentials/token.js +559 -559
- package/src/lib/page.js +159 -159
- package/src/lib/services/constants.js +9 -9
- package/src/lib/services/index.js +26 -26
- package/src/lib/services/interceptors/server-error.js +48 -48
- package/src/lib/services/interceptors/service.js +101 -101
- package/src/lib/services/metrics.js +4 -4
- package/src/lib/services/service-catalog.js +435 -435
- package/src/lib/services/service-fed-ramp.js +4 -4
- package/src/lib/services/service-host.js +267 -267
- package/src/lib/services/service-registry.js +465 -465
- package/src/lib/services/service-state.js +78 -78
- package/src/lib/services/service-url.js +124 -124
- package/src/lib/services/services.js +1018 -1018
- package/src/lib/stateless-webex-plugin.js +98 -98
- package/src/lib/storage/decorators.js +220 -220
- package/src/lib/storage/errors.js +15 -15
- package/src/lib/storage/index.js +10 -10
- package/src/lib/storage/make-webex-plugin-store.js +211 -211
- package/src/lib/storage/make-webex-store.js +140 -140
- package/src/lib/storage/memory-store-adapter.js +79 -79
- package/src/lib/webex-core-plugin-mixin.js +114 -114
- package/src/lib/webex-http-error.js +61 -61
- package/src/lib/webex-internal-core-plugin-mixin.js +107 -107
- package/src/lib/webex-plugin.js +222 -222
- package/src/plugins/logger.js +60 -60
- package/src/webex-core.js +745 -745
- package/src/webex-internal-core.js +46 -46
- package/test/integration/spec/credentials/credentials.js +139 -139
- package/test/integration/spec/credentials/token.js +102 -102
- package/test/integration/spec/services/service-catalog.js +838 -838
- package/test/integration/spec/services/services.js +1221 -1221
- package/test/integration/spec/webex-core.js +178 -178
- package/test/unit/spec/_setup.js +44 -44
- package/test/unit/spec/credentials/credentials.js +1017 -1017
- package/test/unit/spec/credentials/token.js +441 -441
- package/test/unit/spec/interceptors/auth.js +521 -521
- package/test/unit/spec/interceptors/default-options.js +84 -84
- package/test/unit/spec/interceptors/embargo.js +144 -144
- package/test/unit/spec/interceptors/network-timing.js +49 -49
- package/test/unit/spec/interceptors/payload-transformer.js +155 -155
- package/test/unit/spec/interceptors/rate-limit.js +302 -302
- package/test/unit/spec/interceptors/redirect.js +102 -102
- package/test/unit/spec/interceptors/request-timing.js +92 -92
- package/test/unit/spec/interceptors/user-agent.js +76 -76
- package/test/unit/spec/interceptors/webex-tracking-id.js +76 -76
- package/test/unit/spec/interceptors/webex-user-agent.js +159 -159
- package/test/unit/spec/lib/batcher.js +330 -330
- package/test/unit/spec/lib/page.js +148 -148
- package/test/unit/spec/lib/webex-plugin.js +48 -48
- package/test/unit/spec/services/interceptors/server-error.js +204 -204
- package/test/unit/spec/services/interceptors/service.js +188 -188
- package/test/unit/spec/services/service-catalog.js +194 -194
- package/test/unit/spec/services/service-host.js +260 -260
- package/test/unit/spec/services/service-registry.js +747 -747
- package/test/unit/spec/services/service-state.js +60 -60
- package/test/unit/spec/services/service-url.js +258 -258
- package/test/unit/spec/services/services.js +348 -348
- package/test/unit/spec/storage/persist.js +50 -50
- package/test/unit/spec/storage/storage-adapter.js +12 -12
- package/test/unit/spec/storage/wait-for-value.js +81 -81
- package/test/unit/spec/webex-core.js +253 -253
- package/test/unit/spec/webex-internal-core.js +91 -91
|
@@ -1,98 +1,98 @@
|
|
|
1
|
-
import {readonly} from 'core-decorators';
|
|
2
|
-
import AmpEvents from 'ampersand-events';
|
|
3
|
-
|
|
4
|
-
// hold onto weak references to parent' Webexs to help avoid retain cycles
|
|
5
|
-
const webexs = new WeakMap();
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Base plugin class. Doesn't depend on Ampersand State
|
|
9
|
-
*/
|
|
10
|
-
export default class StatelessWebexPlugin {
|
|
11
|
-
/**
|
|
12
|
-
* The config for this plugin's namespace. If no namespace has been set
|
|
13
|
-
* returns all of webex's config.
|
|
14
|
-
* @type {Object}
|
|
15
|
-
*/
|
|
16
|
-
get config() {
|
|
17
|
-
let namespace = this.getNamespace ? this.getNamespace() : this.namespace;
|
|
18
|
-
|
|
19
|
-
if (namespace) {
|
|
20
|
-
namespace = namespace.toLowerCase();
|
|
21
|
-
|
|
22
|
-
return this.webex.config[namespace];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return this.webex.config;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* A reference to the webex logger.
|
|
30
|
-
* @type {Logger}
|
|
31
|
-
*/
|
|
32
|
-
get logger() {
|
|
33
|
-
return this.webex.logger;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* A reference to the main sdk instance
|
|
38
|
-
* @type {WebexCore}
|
|
39
|
-
*/
|
|
40
|
-
get webex() {
|
|
41
|
-
return webexs.get(this);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
@readonly
|
|
45
|
-
/**
|
|
46
|
-
* Mostly here for compatibility with legacy WebexPlugins.
|
|
47
|
-
* StatelessWebexPlugins will never have a state other than ready, however, if
|
|
48
|
-
* we implement stateful WebexPlugins as es6 classes, they may have the option
|
|
49
|
-
* to have ready be false
|
|
50
|
-
* @private
|
|
51
|
-
* @type {boolean}
|
|
52
|
-
*/
|
|
53
|
-
ready = true;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Constructor. One of attrs.webex or options.parent is required
|
|
57
|
-
* @param {Object} attrs
|
|
58
|
-
* @param {WebexCore} [attrs.webex]
|
|
59
|
-
* @param {Object} options
|
|
60
|
-
* @param {WebexCore} [options.parent]
|
|
61
|
-
*/
|
|
62
|
-
constructor(attrs = {}, options = {}) {
|
|
63
|
-
let webex = attrs.webex || options.parent;
|
|
64
|
-
|
|
65
|
-
if (!webex) {
|
|
66
|
-
throw new Error(
|
|
67
|
-
'One of `attrs.webex` or `options.parent` must be supplied when initializing a StatelessWebexPlugin'
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
while (webex.parent || webex.collection) {
|
|
72
|
-
webex = webex.parent || webex.collection;
|
|
73
|
-
}
|
|
74
|
-
webexs.set(this, webex);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Proxies to {@link WebexPlugin#webex}'s `request()` method.
|
|
79
|
-
* @see WebexCore#request
|
|
80
|
-
* @param {Array<mixed>} args
|
|
81
|
-
* @returns {Promise}
|
|
82
|
-
*/
|
|
83
|
-
request(...args) {
|
|
84
|
-
return this.webex.request(...args);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Proxies to {@link WebexPlugin#webex}'s `upload()` method.
|
|
89
|
-
* @see WebexCore#upload
|
|
90
|
-
* @param {Array<mixed>} args
|
|
91
|
-
* @returns {Promise}
|
|
92
|
-
*/
|
|
93
|
-
upload(...args) {
|
|
94
|
-
return this.webex.upload(...args);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
Object.assign(StatelessWebexPlugin.prototype, AmpEvents);
|
|
1
|
+
import {readonly} from 'core-decorators';
|
|
2
|
+
import AmpEvents from 'ampersand-events';
|
|
3
|
+
|
|
4
|
+
// hold onto weak references to parent' Webexs to help avoid retain cycles
|
|
5
|
+
const webexs = new WeakMap();
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Base plugin class. Doesn't depend on Ampersand State
|
|
9
|
+
*/
|
|
10
|
+
export default class StatelessWebexPlugin {
|
|
11
|
+
/**
|
|
12
|
+
* The config for this plugin's namespace. If no namespace has been set
|
|
13
|
+
* returns all of webex's config.
|
|
14
|
+
* @type {Object}
|
|
15
|
+
*/
|
|
16
|
+
get config() {
|
|
17
|
+
let namespace = this.getNamespace ? this.getNamespace() : this.namespace;
|
|
18
|
+
|
|
19
|
+
if (namespace) {
|
|
20
|
+
namespace = namespace.toLowerCase();
|
|
21
|
+
|
|
22
|
+
return this.webex.config[namespace];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return this.webex.config;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A reference to the webex logger.
|
|
30
|
+
* @type {Logger}
|
|
31
|
+
*/
|
|
32
|
+
get logger() {
|
|
33
|
+
return this.webex.logger;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A reference to the main sdk instance
|
|
38
|
+
* @type {WebexCore}
|
|
39
|
+
*/
|
|
40
|
+
get webex() {
|
|
41
|
+
return webexs.get(this);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@readonly
|
|
45
|
+
/**
|
|
46
|
+
* Mostly here for compatibility with legacy WebexPlugins.
|
|
47
|
+
* StatelessWebexPlugins will never have a state other than ready, however, if
|
|
48
|
+
* we implement stateful WebexPlugins as es6 classes, they may have the option
|
|
49
|
+
* to have ready be false
|
|
50
|
+
* @private
|
|
51
|
+
* @type {boolean}
|
|
52
|
+
*/
|
|
53
|
+
ready = true;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Constructor. One of attrs.webex or options.parent is required
|
|
57
|
+
* @param {Object} attrs
|
|
58
|
+
* @param {WebexCore} [attrs.webex]
|
|
59
|
+
* @param {Object} options
|
|
60
|
+
* @param {WebexCore} [options.parent]
|
|
61
|
+
*/
|
|
62
|
+
constructor(attrs = {}, options = {}) {
|
|
63
|
+
let webex = attrs.webex || options.parent;
|
|
64
|
+
|
|
65
|
+
if (!webex) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
'One of `attrs.webex` or `options.parent` must be supplied when initializing a StatelessWebexPlugin'
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
while (webex.parent || webex.collection) {
|
|
72
|
+
webex = webex.parent || webex.collection;
|
|
73
|
+
}
|
|
74
|
+
webexs.set(this, webex);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Proxies to {@link WebexPlugin#webex}'s `request()` method.
|
|
79
|
+
* @see WebexCore#request
|
|
80
|
+
* @param {Array<mixed>} args
|
|
81
|
+
* @returns {Promise}
|
|
82
|
+
*/
|
|
83
|
+
request(...args) {
|
|
84
|
+
return this.webex.request(...args);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Proxies to {@link WebexPlugin#webex}'s `upload()` method.
|
|
89
|
+
* @see WebexCore#upload
|
|
90
|
+
* @param {Array<mixed>} args
|
|
91
|
+
* @returns {Promise}
|
|
92
|
+
*/
|
|
93
|
+
upload(...args) {
|
|
94
|
+
return this.webex.upload(...args);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
Object.assign(StatelessWebexPlugin.prototype, AmpEvents);
|
|
@@ -1,220 +1,220 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/* eslint no-invalid-this: [0] */
|
|
6
|
-
|
|
7
|
-
import {curry, debounce, identity, result, wrap} from 'lodash';
|
|
8
|
-
import {make} from '@webex/common';
|
|
9
|
-
|
|
10
|
-
import {NotFoundError} from './errors';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Stores the result of fn before returning it
|
|
14
|
-
* @param {string} key
|
|
15
|
-
* @private
|
|
16
|
-
* @returns {Promise} resolves with the result of fn
|
|
17
|
-
*/
|
|
18
|
-
export function persist(...args) {
|
|
19
|
-
if (args.length === 3) {
|
|
20
|
-
return persist('@')(...args);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const [key, decider] = args;
|
|
24
|
-
|
|
25
|
-
return function persistDecorator(target, prop, descriptor) {
|
|
26
|
-
if (prop !== 'initialize') {
|
|
27
|
-
// Once we have class-based alternative to AmpersandState, it should be
|
|
28
|
-
// detected here.
|
|
29
|
-
throw new TypeError(
|
|
30
|
-
'@persist can only currently be applied to AmpersandState objects or their derivatives and must be applied to the initialize method'
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
descriptor.value = wrap(descriptor.value, function persistExecutor(fn, ...initializeArgs) {
|
|
35
|
-
const ret = Reflect.apply(fn, this, initializeArgs);
|
|
36
|
-
const changeEvent = key === '@' ? 'change' : `change:${key}`;
|
|
37
|
-
|
|
38
|
-
// Some scenarios will lead to lots of change events on a single tick; we
|
|
39
|
-
// really only care about writing once things have stopped changing. with
|
|
40
|
-
// a debounce of zero, we're effectively coalescing all the changes
|
|
41
|
-
// triggered by a single call to set() and commiting them on the next tick
|
|
42
|
-
// eslint-disable-next-line no-invalid-this
|
|
43
|
-
this.on(
|
|
44
|
-
changeEvent,
|
|
45
|
-
debounce(() => {
|
|
46
|
-
const shouldPersist = !decider || Reflect.apply(decider, this, ...initializeArgs);
|
|
47
|
-
|
|
48
|
-
if (!shouldPersist) {
|
|
49
|
-
return Promise.resolve();
|
|
50
|
-
}
|
|
51
|
-
if (key === '@') {
|
|
52
|
-
// eslint-disable-next-line no-invalid-this
|
|
53
|
-
return this.boundedStorage.put(key, this);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// eslint-disable-next-line no-invalid-this
|
|
57
|
-
return this.boundedStorage.put(key, this[key]);
|
|
58
|
-
}, 0)
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
return ret;
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
prepareInitialize(target, prop);
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const M = Map;
|
|
69
|
-
const S = Set;
|
|
70
|
-
const BlockingKeyMap = make(M, M, S);
|
|
71
|
-
const blockingKeys = new BlockingKeyMap();
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Prevents fn from executing until key has been (attempted to be) loaded
|
|
75
|
-
* @param {string} key
|
|
76
|
-
* @param {Function} fn
|
|
77
|
-
* @private
|
|
78
|
-
* @returns {Promise} result of fn
|
|
79
|
-
*/
|
|
80
|
-
export function waitForValue(key) {
|
|
81
|
-
if (!key) {
|
|
82
|
-
throw new Error('`key` is required');
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return function waitForValueDecorator(target, prop, descriptor) {
|
|
86
|
-
blockingKeys.add(target, prop, key);
|
|
87
|
-
descriptor.value = wrap(descriptor.value, function waitForValueExecutor(fn, ...args) {
|
|
88
|
-
const keys = blockingKeys.get(target, prop);
|
|
89
|
-
|
|
90
|
-
return Promise.all([...keys].map((k) => this.boundedStorage.waitFor(k))).then(() =>
|
|
91
|
-
Reflect.apply(fn, this, args)
|
|
92
|
-
);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
// This *should* make decorators compatible with AmpersandState class
|
|
96
|
-
// definitions
|
|
97
|
-
if (typeof target === 'object' && !target.prototype) {
|
|
98
|
-
target[prop] = descriptor.value;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
prepareInitialize(target, prop);
|
|
102
|
-
|
|
103
|
-
return descriptor;
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const inited = new Set();
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* finds a means of identitying the `target` param passed to
|
|
111
|
-
* `prepareInitialize()`. When possible, avoids duplicate `init()` calls if
|
|
112
|
-
* namespaces collide
|
|
113
|
-
*
|
|
114
|
-
* @param {Object|Constructor} target
|
|
115
|
-
* @private
|
|
116
|
-
* @returns {String|Constructor}
|
|
117
|
-
*/
|
|
118
|
-
function identifyTarget(target) {
|
|
119
|
-
if (target.namespace) {
|
|
120
|
-
return target.namespace;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return target;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const stack = new Set();
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* @param {Function} target
|
|
130
|
-
* @param {string} prop
|
|
131
|
-
* @private
|
|
132
|
-
* @returns {undefined}
|
|
133
|
-
*/
|
|
134
|
-
function prepareInitialize(target, prop) {
|
|
135
|
-
const id = identifyTarget(target);
|
|
136
|
-
|
|
137
|
-
if (!inited.has(id)) {
|
|
138
|
-
inited.add(id);
|
|
139
|
-
if (target.initialize) {
|
|
140
|
-
target.initialize = wrap(target.initialize, function applyInit(fn, ...args) {
|
|
141
|
-
const ret = Reflect.apply(fn, this, args);
|
|
142
|
-
|
|
143
|
-
Reflect.apply(init, this, args);
|
|
144
|
-
|
|
145
|
-
return ret;
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
target.initialize = init;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* @private
|
|
156
|
-
* @returns {undefined}
|
|
157
|
-
*/
|
|
158
|
-
function init() {
|
|
159
|
-
const self = this;
|
|
160
|
-
const namespace = this.getNamespace();
|
|
161
|
-
|
|
162
|
-
this.webex.initialize = wrap(
|
|
163
|
-
this.webex.initialize || identity,
|
|
164
|
-
function applyInit(fn, ...args) {
|
|
165
|
-
// Call webex's initalize method first
|
|
166
|
-
// Reminder: in order for MockWebex to accept initial storage data, the
|
|
167
|
-
// wrapped initialize() must be invoked before attempting to load data.
|
|
168
|
-
// Reminder: context here is `webex`, not `self`.
|
|
169
|
-
stack.add(namespace);
|
|
170
|
-
Reflect.apply(fn, this, args);
|
|
171
|
-
|
|
172
|
-
// Then prepare a function for setting values retrieved from storage
|
|
173
|
-
const set = curry((key, value) => {
|
|
174
|
-
this.logger.debug(`storage:(${namespace}): got \`${key}\` for first time`);
|
|
175
|
-
if (key === '@') {
|
|
176
|
-
self.parent.set({
|
|
177
|
-
[namespace.toLowerCase()]: value,
|
|
178
|
-
});
|
|
179
|
-
} else if (result(self[key], 'isState')) {
|
|
180
|
-
self[key].set(value);
|
|
181
|
-
} else {
|
|
182
|
-
self.set(key, value);
|
|
183
|
-
}
|
|
184
|
-
this.logger.debug(`storage:(${namespace}): set \`${key}\` for first time`);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
// And prepare an error handler for when those keys can't be found
|
|
188
|
-
const handle = curry((key, reason) => {
|
|
189
|
-
if (
|
|
190
|
-
reason instanceof NotFoundError ||
|
|
191
|
-
(process.env.NODE_ENV !== 'production' &&
|
|
192
|
-
reason.toString().includes('MockNotFoundError'))
|
|
193
|
-
) {
|
|
194
|
-
this.logger.debug(`storage(${namespace}): no data for \`${key}\`, continuing`);
|
|
195
|
-
|
|
196
|
-
return Promise.resolve();
|
|
197
|
-
}
|
|
198
|
-
this.logger.error(`storage(${namespace}): failed to init \`${key}\``, reason);
|
|
199
|
-
|
|
200
|
-
return Promise.reject(reason);
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
// Iterate over the list of keys marked as blocking via `@waitForValue`
|
|
204
|
-
const keys = blockingKeys.get(target, prop);
|
|
205
|
-
const promises = [];
|
|
206
|
-
|
|
207
|
-
keys.forEach((key) => {
|
|
208
|
-
promises.push(this.boundedStorage.get(namespace, key).then(set(key)).catch(handle(key)));
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
Promise.all(promises).then(() => {
|
|
212
|
-
stack.delete(namespace);
|
|
213
|
-
if (stack.size === 0) {
|
|
214
|
-
this.loaded = true;
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/* eslint no-invalid-this: [0] */
|
|
6
|
+
|
|
7
|
+
import {curry, debounce, identity, result, wrap} from 'lodash';
|
|
8
|
+
import {make} from '@webex/common';
|
|
9
|
+
|
|
10
|
+
import {NotFoundError} from './errors';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Stores the result of fn before returning it
|
|
14
|
+
* @param {string} key
|
|
15
|
+
* @private
|
|
16
|
+
* @returns {Promise} resolves with the result of fn
|
|
17
|
+
*/
|
|
18
|
+
export function persist(...args) {
|
|
19
|
+
if (args.length === 3) {
|
|
20
|
+
return persist('@')(...args);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const [key, decider] = args;
|
|
24
|
+
|
|
25
|
+
return function persistDecorator(target, prop, descriptor) {
|
|
26
|
+
if (prop !== 'initialize') {
|
|
27
|
+
// Once we have class-based alternative to AmpersandState, it should be
|
|
28
|
+
// detected here.
|
|
29
|
+
throw new TypeError(
|
|
30
|
+
'@persist can only currently be applied to AmpersandState objects or their derivatives and must be applied to the initialize method'
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
descriptor.value = wrap(descriptor.value, function persistExecutor(fn, ...initializeArgs) {
|
|
35
|
+
const ret = Reflect.apply(fn, this, initializeArgs);
|
|
36
|
+
const changeEvent = key === '@' ? 'change' : `change:${key}`;
|
|
37
|
+
|
|
38
|
+
// Some scenarios will lead to lots of change events on a single tick; we
|
|
39
|
+
// really only care about writing once things have stopped changing. with
|
|
40
|
+
// a debounce of zero, we're effectively coalescing all the changes
|
|
41
|
+
// triggered by a single call to set() and commiting them on the next tick
|
|
42
|
+
// eslint-disable-next-line no-invalid-this
|
|
43
|
+
this.on(
|
|
44
|
+
changeEvent,
|
|
45
|
+
debounce(() => {
|
|
46
|
+
const shouldPersist = !decider || Reflect.apply(decider, this, ...initializeArgs);
|
|
47
|
+
|
|
48
|
+
if (!shouldPersist) {
|
|
49
|
+
return Promise.resolve();
|
|
50
|
+
}
|
|
51
|
+
if (key === '@') {
|
|
52
|
+
// eslint-disable-next-line no-invalid-this
|
|
53
|
+
return this.boundedStorage.put(key, this);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// eslint-disable-next-line no-invalid-this
|
|
57
|
+
return this.boundedStorage.put(key, this[key]);
|
|
58
|
+
}, 0)
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
return ret;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
prepareInitialize(target, prop);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const M = Map;
|
|
69
|
+
const S = Set;
|
|
70
|
+
const BlockingKeyMap = make(M, M, S);
|
|
71
|
+
const blockingKeys = new BlockingKeyMap();
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Prevents fn from executing until key has been (attempted to be) loaded
|
|
75
|
+
* @param {string} key
|
|
76
|
+
* @param {Function} fn
|
|
77
|
+
* @private
|
|
78
|
+
* @returns {Promise} result of fn
|
|
79
|
+
*/
|
|
80
|
+
export function waitForValue(key) {
|
|
81
|
+
if (!key) {
|
|
82
|
+
throw new Error('`key` is required');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return function waitForValueDecorator(target, prop, descriptor) {
|
|
86
|
+
blockingKeys.add(target, prop, key);
|
|
87
|
+
descriptor.value = wrap(descriptor.value, function waitForValueExecutor(fn, ...args) {
|
|
88
|
+
const keys = blockingKeys.get(target, prop);
|
|
89
|
+
|
|
90
|
+
return Promise.all([...keys].map((k) => this.boundedStorage.waitFor(k))).then(() =>
|
|
91
|
+
Reflect.apply(fn, this, args)
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// This *should* make decorators compatible with AmpersandState class
|
|
96
|
+
// definitions
|
|
97
|
+
if (typeof target === 'object' && !target.prototype) {
|
|
98
|
+
target[prop] = descriptor.value;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
prepareInitialize(target, prop);
|
|
102
|
+
|
|
103
|
+
return descriptor;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const inited = new Set();
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* finds a means of identitying the `target` param passed to
|
|
111
|
+
* `prepareInitialize()`. When possible, avoids duplicate `init()` calls if
|
|
112
|
+
* namespaces collide
|
|
113
|
+
*
|
|
114
|
+
* @param {Object|Constructor} target
|
|
115
|
+
* @private
|
|
116
|
+
* @returns {String|Constructor}
|
|
117
|
+
*/
|
|
118
|
+
function identifyTarget(target) {
|
|
119
|
+
if (target.namespace) {
|
|
120
|
+
return target.namespace;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return target;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const stack = new Set();
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @param {Function} target
|
|
130
|
+
* @param {string} prop
|
|
131
|
+
* @private
|
|
132
|
+
* @returns {undefined}
|
|
133
|
+
*/
|
|
134
|
+
function prepareInitialize(target, prop) {
|
|
135
|
+
const id = identifyTarget(target);
|
|
136
|
+
|
|
137
|
+
if (!inited.has(id)) {
|
|
138
|
+
inited.add(id);
|
|
139
|
+
if (target.initialize) {
|
|
140
|
+
target.initialize = wrap(target.initialize, function applyInit(fn, ...args) {
|
|
141
|
+
const ret = Reflect.apply(fn, this, args);
|
|
142
|
+
|
|
143
|
+
Reflect.apply(init, this, args);
|
|
144
|
+
|
|
145
|
+
return ret;
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
target.initialize = init;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @private
|
|
156
|
+
* @returns {undefined}
|
|
157
|
+
*/
|
|
158
|
+
function init() {
|
|
159
|
+
const self = this;
|
|
160
|
+
const namespace = this.getNamespace();
|
|
161
|
+
|
|
162
|
+
this.webex.initialize = wrap(
|
|
163
|
+
this.webex.initialize || identity,
|
|
164
|
+
function applyInit(fn, ...args) {
|
|
165
|
+
// Call webex's initalize method first
|
|
166
|
+
// Reminder: in order for MockWebex to accept initial storage data, the
|
|
167
|
+
// wrapped initialize() must be invoked before attempting to load data.
|
|
168
|
+
// Reminder: context here is `webex`, not `self`.
|
|
169
|
+
stack.add(namespace);
|
|
170
|
+
Reflect.apply(fn, this, args);
|
|
171
|
+
|
|
172
|
+
// Then prepare a function for setting values retrieved from storage
|
|
173
|
+
const set = curry((key, value) => {
|
|
174
|
+
this.logger.debug(`storage:(${namespace}): got \`${key}\` for first time`);
|
|
175
|
+
if (key === '@') {
|
|
176
|
+
self.parent.set({
|
|
177
|
+
[namespace.toLowerCase()]: value,
|
|
178
|
+
});
|
|
179
|
+
} else if (result(self[key], 'isState')) {
|
|
180
|
+
self[key].set(value);
|
|
181
|
+
} else {
|
|
182
|
+
self.set(key, value);
|
|
183
|
+
}
|
|
184
|
+
this.logger.debug(`storage:(${namespace}): set \`${key}\` for first time`);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// And prepare an error handler for when those keys can't be found
|
|
188
|
+
const handle = curry((key, reason) => {
|
|
189
|
+
if (
|
|
190
|
+
reason instanceof NotFoundError ||
|
|
191
|
+
(process.env.NODE_ENV !== 'production' &&
|
|
192
|
+
reason.toString().includes('MockNotFoundError'))
|
|
193
|
+
) {
|
|
194
|
+
this.logger.debug(`storage(${namespace}): no data for \`${key}\`, continuing`);
|
|
195
|
+
|
|
196
|
+
return Promise.resolve();
|
|
197
|
+
}
|
|
198
|
+
this.logger.error(`storage(${namespace}): failed to init \`${key}\``, reason);
|
|
199
|
+
|
|
200
|
+
return Promise.reject(reason);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Iterate over the list of keys marked as blocking via `@waitForValue`
|
|
204
|
+
const keys = blockingKeys.get(target, prop);
|
|
205
|
+
const promises = [];
|
|
206
|
+
|
|
207
|
+
keys.forEach((key) => {
|
|
208
|
+
promises.push(this.boundedStorage.get(namespace, key).then(set(key)).catch(handle(key)));
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
Promise.all(promises).then(() => {
|
|
212
|
+
stack.delete(namespace);
|
|
213
|
+
if (stack.size === 0) {
|
|
214
|
+
this.loaded = true;
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {Exception} from '@webex/common';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* General storage layer error
|
|
9
|
-
*/
|
|
10
|
-
export class StorageError extends Exception {}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* StorageError thrown when the storage layer does not contain the request key
|
|
14
|
-
*/
|
|
15
|
-
export class NotFoundError extends StorageError {}
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {Exception} from '@webex/common';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* General storage layer error
|
|
9
|
+
*/
|
|
10
|
+
export class StorageError extends Exception {}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* StorageError thrown when the storage layer does not contain the request key
|
|
14
|
+
*/
|
|
15
|
+
export class NotFoundError extends StorageError {}
|