@featbit/js-client-sdk 3.0.13 → 3.0.14
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/LICENSE +21 -21
- package/README.md +301 -301
- package/dist/esm/IFbClientCore.d.ts +1 -1
- package/dist/esm/IFbClientCore.d.ts.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/umd/{featbit-js-client-sdk-3.0.13.js → featbit-js-client-sdk-3.0.14.js} +2 -2
- package/dist/umd/featbit-js-client-sdk-3.0.14.js.map +1 -0
- package/dist/umd/featbit-js-client-sdk.js +1 -1
- package/dist/umd/featbit-js-client-sdk.js.map +1 -1
- package/package.json +46 -46
- package/src/Configuration.ts +232 -232
- package/src/Context.ts +61 -61
- package/src/FbClientBuilder.ts +167 -167
- package/src/FbClientCore.ts +405 -405
- package/src/IContextProperty.ts +3 -3
- package/src/IDataKind.ts +11 -11
- package/src/IFbClient.ts +29 -29
- package/src/IFbClientCore.ts +290 -290
- package/src/IVersionedData.ts +18 -18
- package/src/bootstrap/IBootstrapProvider.ts +4 -4
- package/src/bootstrap/JsonBootstrapProvider.ts +34 -34
- package/src/bootstrap/NullBootstrapProvider.ts +20 -20
- package/src/bootstrap/index.ts +2 -2
- package/src/constants.ts +1 -1
- package/src/data-sources/DataSourceUpdates.ts +116 -116
- package/src/data-sources/createStreamListeners.ts +67 -67
- package/src/data-sources/index.ts +1 -1
- package/src/data-sync/DataSyncMode.ts +3 -3
- package/src/data-sync/IDataSynchronizer.ts +15 -15
- package/src/data-sync/IRequestor.ts +10 -10
- package/src/data-sync/NullDataSynchronizer.ts +14 -14
- package/src/data-sync/PollingDataSynchronizer.ts +125 -125
- package/src/data-sync/Requestor.ts +61 -61
- package/src/data-sync/WebSocketDataSynchronizer.ts +77 -77
- package/src/data-sync/index.ts +8 -8
- package/src/data-sync/types.ts +19 -19
- package/src/data-sync/utils.ts +31 -31
- package/src/errors.ts +47 -47
- package/src/evaluation/EvalResult.ts +35 -35
- package/src/evaluation/Evaluator.ts +26 -26
- package/src/evaluation/IEvalDetail.ts +23 -23
- package/src/evaluation/ReasonKinds.ts +9 -9
- package/src/evaluation/data/IFlag.ts +29 -29
- package/src/evaluation/index.ts +4 -4
- package/src/events/DefaultEventProcessor.ts +83 -83
- package/src/events/DefaultEventQueue.ts +49 -49
- package/src/events/DefaultEventSender.ts +73 -73
- package/src/events/DefaultEventSerializer.ts +11 -11
- package/src/events/EventDispatcher.ts +127 -127
- package/src/events/EventSerializer.ts +4 -4
- package/src/events/IEventProcessor.ts +8 -8
- package/src/events/IEventQueue.ts +16 -16
- package/src/events/IEventSender.ts +13 -13
- package/src/events/NullEventProcessor.ts +15 -15
- package/src/events/event.ts +129 -129
- package/src/events/index.ts +11 -11
- package/src/index.ts +21 -21
- package/src/integrations/TestLogger.ts +24 -24
- package/src/integrations/index.ts +1 -1
- package/src/integrations/test_data/FlagBuilder.ts +59 -59
- package/src/integrations/test_data/TestData.ts +57 -57
- package/src/integrations/test_data/TestDataSynchronizer.ts +49 -49
- package/src/integrations/test_data/index.ts +4 -4
- package/src/logging/BasicLogger.ts +108 -108
- package/src/logging/IBasicLoggerOptions.ts +46 -46
- package/src/logging/ILogger.ts +49 -49
- package/src/logging/LogLevel.ts +8 -8
- package/src/logging/SafeLogger.ts +69 -69
- package/src/logging/format.ts +154 -154
- package/src/logging/index.ts +5 -5
- package/src/options/ClientContext.ts +39 -39
- package/src/options/IClientContext.ts +53 -53
- package/src/options/IOptions.ts +123 -123
- package/src/options/IUser.ts +6 -6
- package/src/options/IValidatedOptions.ts +29 -29
- package/src/options/OptionMessages.ts +35 -35
- package/src/options/UserBuilder.ts +35 -35
- package/src/options/Validators.ts +300 -300
- package/src/options/index.ts +7 -7
- package/src/platform/IInfo.ts +102 -102
- package/src/platform/IPlatform.ts +20 -20
- package/src/platform/IStore.ts +112 -112
- package/src/platform/IWebSocket.ts +22 -22
- package/src/platform/browser/BrowserInfo.ts +24 -24
- package/src/platform/browser/BrowserPlatform.ts +19 -19
- package/src/platform/browser/BrowserRequests.ts +6 -6
- package/src/platform/browser/BrowserWebSocket.ts +147 -147
- package/src/platform/browser/FbClient.ts +65 -65
- package/src/platform/browser/LocalStorageStore.ts +59 -59
- package/src/platform/index.ts +11 -11
- package/src/platform/requests.ts +76 -76
- package/src/store/BaseStore.ts +125 -125
- package/src/store/DataKinds.ts +6 -6
- package/src/store/IDataSourceUpdates.ts +68 -68
- package/src/store/InMemoryStore.ts +36 -36
- package/src/store/index.ts +5 -5
- package/src/store/serialization.ts +52 -52
- package/src/store/store.ts +37 -37
- package/src/utils/Emits.ts +75 -75
- package/src/utils/EventEmitter.ts +128 -128
- package/src/utils/IEventEmitter.ts +14 -14
- package/src/utils/Regex.ts +21 -21
- package/src/utils/ValueConverters.ts +55 -55
- package/src/utils/canonicalizeUri.ts +3 -3
- package/src/utils/debounce.ts +33 -33
- package/src/utils/http.ts +40 -40
- package/src/utils/index.ts +5 -5
- package/src/utils/isNullOrUndefined.ts +2 -2
- package/src/utils/serializeUser.ts +27 -27
- package/src/utils/sleep.ts +5 -5
- package/src/version.ts +1 -1
- package/dist/umd/featbit-js-client-sdk-3.0.13.js.map +0 -1
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
import { Regex } from "./Regex";
|
|
2
|
-
|
|
3
|
-
export interface IConvertResult<TValue> {
|
|
4
|
-
isSucceeded: boolean,
|
|
5
|
-
value?: TValue
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export class ValueConverters {
|
|
9
|
-
static bool(value: string): IConvertResult<boolean> {
|
|
10
|
-
if (value?.toUpperCase() === 'TRUE') {
|
|
11
|
-
return ValueConverters.success<boolean>(true);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (value?.toUpperCase() === 'FALSE') {
|
|
15
|
-
return ValueConverters.success<boolean>(false);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return ValueConverters.error<boolean>();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
static number(value: string): IConvertResult<number> {
|
|
22
|
-
const num = Number(value);
|
|
23
|
-
|
|
24
|
-
if (Number.isNaN(num)) {
|
|
25
|
-
return ValueConverters.error<number>();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return ValueConverters.success<number>(num);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
static string(value: string): IConvertResult<string> {
|
|
32
|
-
return ValueConverters.success<string>(value);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
static json(value: string): IConvertResult<unknown> {
|
|
36
|
-
try {
|
|
37
|
-
const val = JSON.parse(value);
|
|
38
|
-
return ValueConverters.success<unknown>(val);
|
|
39
|
-
} catch (err) {
|
|
40
|
-
return ValueConverters.error<unknown>();
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
private static success<TValue>(value: TValue): IConvertResult<TValue> {
|
|
45
|
-
return {
|
|
46
|
-
isSucceeded: true,
|
|
47
|
-
value: value
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
private static error<TValue>(): IConvertResult<TValue> {
|
|
52
|
-
return {
|
|
53
|
-
isSucceeded: false
|
|
54
|
-
}
|
|
55
|
-
}
|
|
1
|
+
import { Regex } from "./Regex";
|
|
2
|
+
|
|
3
|
+
export interface IConvertResult<TValue> {
|
|
4
|
+
isSucceeded: boolean,
|
|
5
|
+
value?: TValue
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class ValueConverters {
|
|
9
|
+
static bool(value: string): IConvertResult<boolean> {
|
|
10
|
+
if (value?.toUpperCase() === 'TRUE') {
|
|
11
|
+
return ValueConverters.success<boolean>(true);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (value?.toUpperCase() === 'FALSE') {
|
|
15
|
+
return ValueConverters.success<boolean>(false);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return ValueConverters.error<boolean>();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static number(value: string): IConvertResult<number> {
|
|
22
|
+
const num = Number(value);
|
|
23
|
+
|
|
24
|
+
if (Number.isNaN(num)) {
|
|
25
|
+
return ValueConverters.error<number>();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return ValueConverters.success<number>(num);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static string(value: string): IConvertResult<string> {
|
|
32
|
+
return ValueConverters.success<string>(value);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static json(value: string): IConvertResult<unknown> {
|
|
36
|
+
try {
|
|
37
|
+
const val = JSON.parse(value);
|
|
38
|
+
return ValueConverters.success<unknown>(val);
|
|
39
|
+
} catch (err) {
|
|
40
|
+
return ValueConverters.error<unknown>();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private static success<TValue>(value: TValue): IConvertResult<TValue> {
|
|
45
|
+
return {
|
|
46
|
+
isSucceeded: true,
|
|
47
|
+
value: value
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private static error<TValue>(): IConvertResult<TValue> {
|
|
52
|
+
return {
|
|
53
|
+
isSucceeded: false
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
56
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// This function is designed to remove any trailing forward slashes at the end of the provided URI string
|
|
2
|
-
export function canonicalizeUri(uri: string): string {
|
|
3
|
-
return uri.replace(/\/+$/, '');
|
|
1
|
+
// This function is designed to remove any trailing forward slashes at the end of the provided URI string
|
|
2
|
+
export function canonicalizeUri(uri: string): string {
|
|
3
|
+
return uri.replace(/\/+$/, '');
|
|
4
4
|
}
|
package/src/utils/debounce.ts
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Wait before calling the same function. Useful for expensive calls.
|
|
3
|
-
* Adapted from https://amitd.co/code/typescript/debounce.
|
|
4
|
-
*
|
|
5
|
-
* @return The debounced function.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
*
|
|
9
|
-
* ```js
|
|
10
|
-
* const debouncedFunction = debounce(e => {
|
|
11
|
-
* console.log(e);
|
|
12
|
-
* }, 5000);
|
|
13
|
-
*
|
|
14
|
-
* // Console logs 'Hello world again ' after 5 seconds
|
|
15
|
-
* debouncedFunction('Hello world');
|
|
16
|
-
* debouncedFunction('Hello world again');
|
|
17
|
-
* ```
|
|
18
|
-
* @param fn The function to be debounced.
|
|
19
|
-
* @param delayMs Defaults to 5 seconds.
|
|
20
|
-
*/
|
|
21
|
-
export const debounce = <T extends (...args: any[]) => ReturnType<T>>(
|
|
22
|
-
fn: T,
|
|
23
|
-
delayMs: number = 5000,
|
|
24
|
-
): ((...args: Parameters<T>) => void) => {
|
|
25
|
-
let timer: ReturnType<typeof setTimeout>;
|
|
26
|
-
|
|
27
|
-
return (...args: Parameters<T>) => {
|
|
28
|
-
clearTimeout(timer);
|
|
29
|
-
timer = setTimeout(() => {
|
|
30
|
-
fn(...args);
|
|
31
|
-
}, delayMs);
|
|
32
|
-
};
|
|
33
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Wait before calling the same function. Useful for expensive calls.
|
|
3
|
+
* Adapted from https://amitd.co/code/typescript/debounce.
|
|
4
|
+
*
|
|
5
|
+
* @return The debounced function.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
*
|
|
9
|
+
* ```js
|
|
10
|
+
* const debouncedFunction = debounce(e => {
|
|
11
|
+
* console.log(e);
|
|
12
|
+
* }, 5000);
|
|
13
|
+
*
|
|
14
|
+
* // Console logs 'Hello world again ' after 5 seconds
|
|
15
|
+
* debouncedFunction('Hello world');
|
|
16
|
+
* debouncedFunction('Hello world again');
|
|
17
|
+
* ```
|
|
18
|
+
* @param fn The function to be debounced.
|
|
19
|
+
* @param delayMs Defaults to 5 seconds.
|
|
20
|
+
*/
|
|
21
|
+
export const debounce = <T extends (...args: any[]) => ReturnType<T>>(
|
|
22
|
+
fn: T,
|
|
23
|
+
delayMs: number = 5000,
|
|
24
|
+
): ((...args: Parameters<T>) => void) => {
|
|
25
|
+
let timer: ReturnType<typeof setTimeout>;
|
|
26
|
+
|
|
27
|
+
return (...args: Parameters<T>) => {
|
|
28
|
+
clearTimeout(timer);
|
|
29
|
+
timer = setTimeout(() => {
|
|
30
|
+
fn(...args);
|
|
31
|
+
}, delayMs);
|
|
32
|
+
};
|
|
33
|
+
};
|
package/src/utils/http.ts
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
import { IInfo } from "../platform/IInfo";
|
|
2
|
-
|
|
3
|
-
export type Headers = {
|
|
4
|
-
Authorization: string;
|
|
5
|
-
'X-User-Agent': string;
|
|
6
|
-
'Content-Type': string;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export function defaultHeaders(
|
|
10
|
-
sdkKey: string,
|
|
11
|
-
info: IInfo
|
|
12
|
-
): Headers {
|
|
13
|
-
const {userAgent, version} = info.sdkData();
|
|
14
|
-
|
|
15
|
-
const headers: Headers = {
|
|
16
|
-
'Content-Type': 'application/json',
|
|
17
|
-
'X-User-Agent': userAgent ?? `${info.appType}/${version}`,
|
|
18
|
-
'Authorization': sdkKey
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
return headers;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function httpErrorMessage(
|
|
25
|
-
err: {
|
|
26
|
-
status: number;
|
|
27
|
-
message: string;
|
|
28
|
-
},
|
|
29
|
-
context: string,
|
|
30
|
-
retryMessage?: string,
|
|
31
|
-
): string {
|
|
32
|
-
let desc;
|
|
33
|
-
if (err.status) {
|
|
34
|
-
desc = `error ${ err.status }${ err.status === 401 ? ' (invalid SDK key)' : '' }`;
|
|
35
|
-
} else {
|
|
36
|
-
desc = `I/O error (${ err.message || err })`;
|
|
37
|
-
}
|
|
38
|
-
const action = retryMessage ?? 'giving up permanently';
|
|
39
|
-
return `Received ${ desc } for ${ context } - ${ action }`;
|
|
40
|
-
}
|
|
1
|
+
import { IInfo } from "../platform/IInfo";
|
|
2
|
+
|
|
3
|
+
export type Headers = {
|
|
4
|
+
Authorization: string;
|
|
5
|
+
'X-User-Agent': string;
|
|
6
|
+
'Content-Type': string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export function defaultHeaders(
|
|
10
|
+
sdkKey: string,
|
|
11
|
+
info: IInfo
|
|
12
|
+
): Headers {
|
|
13
|
+
const {userAgent, version} = info.sdkData();
|
|
14
|
+
|
|
15
|
+
const headers: Headers = {
|
|
16
|
+
'Content-Type': 'application/json',
|
|
17
|
+
'X-User-Agent': userAgent ?? `${info.appType}/${version}`,
|
|
18
|
+
'Authorization': sdkKey
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
return headers;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function httpErrorMessage(
|
|
25
|
+
err: {
|
|
26
|
+
status: number;
|
|
27
|
+
message: string;
|
|
28
|
+
},
|
|
29
|
+
context: string,
|
|
30
|
+
retryMessage?: string,
|
|
31
|
+
): string {
|
|
32
|
+
let desc;
|
|
33
|
+
if (err.status) {
|
|
34
|
+
desc = `error ${ err.status }${ err.status === 401 ? ' (invalid SDK key)' : '' }`;
|
|
35
|
+
} else {
|
|
36
|
+
desc = `I/O error (${ err.message || err })`;
|
|
37
|
+
}
|
|
38
|
+
const action = retryMessage ?? 'giving up permanently';
|
|
39
|
+
return `Received ${ desc } for ${ context } - ${ action }`;
|
|
40
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export * from './isNullOrUndefined';
|
|
2
|
-
export * from './sleep';
|
|
3
|
-
export * from './ValueConverters';
|
|
4
|
-
export * from './VoidFunction';
|
|
5
|
-
export * from './serializeUser';
|
|
1
|
+
export * from './isNullOrUndefined';
|
|
2
|
+
export * from './sleep';
|
|
3
|
+
export * from './ValueConverters';
|
|
4
|
+
export * from './VoidFunction';
|
|
5
|
+
export * from './serializeUser';
|
|
6
6
|
export * from './debounce';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export function isNullOrUndefined(val: any) {
|
|
2
|
-
return val === null || val === undefined;
|
|
1
|
+
export function isNullOrUndefined(val: any) {
|
|
2
|
+
return val === null || val === undefined;
|
|
3
3
|
}
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { IUser } from "../options/IUser";
|
|
2
|
-
|
|
3
|
-
export function serializeUser(user: IUser | undefined): string {
|
|
4
|
-
if (!user) {
|
|
5
|
-
return '';
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const builtInProperties = `${user.keyId},${user.name}`;
|
|
9
|
-
|
|
10
|
-
const customizedProperties = user.customizedProperties
|
|
11
|
-
?.sort((a, b) => {
|
|
12
|
-
const nameA = a.name.toLowerCase();
|
|
13
|
-
const nameB = b.name.toLowerCase();
|
|
14
|
-
if (nameA < nameB) {
|
|
15
|
-
return -1;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (nameA > nameB) {
|
|
19
|
-
return 1;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return 0;
|
|
23
|
-
})
|
|
24
|
-
.map(p => `${p.name}:${p.value}`)
|
|
25
|
-
.join(',');
|
|
26
|
-
|
|
27
|
-
return `${builtInProperties},${customizedProperties}`;
|
|
1
|
+
import { IUser } from "../options/IUser";
|
|
2
|
+
|
|
3
|
+
export function serializeUser(user: IUser | undefined): string {
|
|
4
|
+
if (!user) {
|
|
5
|
+
return '';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const builtInProperties = `${user.keyId},${user.name}`;
|
|
9
|
+
|
|
10
|
+
const customizedProperties = user.customizedProperties
|
|
11
|
+
?.sort((a, b) => {
|
|
12
|
+
const nameA = a.name.toLowerCase();
|
|
13
|
+
const nameB = b.name.toLowerCase();
|
|
14
|
+
if (nameA < nameB) {
|
|
15
|
+
return -1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (nameA > nameB) {
|
|
19
|
+
return 1;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return 0;
|
|
23
|
+
})
|
|
24
|
+
.map(p => `${p.name}:${p.value}`)
|
|
25
|
+
.join(',');
|
|
26
|
+
|
|
27
|
+
return `${builtInProperties},${customizedProperties}`;
|
|
28
28
|
}
|
package/src/utils/sleep.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const sleep = async (delayMillis: number = 1000) =>
|
|
2
|
-
new Promise((resolve) => {
|
|
3
|
-
setTimeout(resolve, delayMillis);
|
|
4
|
-
});
|
|
5
|
-
|
|
1
|
+
const sleep = async (delayMillis: number = 1000) =>
|
|
2
|
+
new Promise((resolve) => {
|
|
3
|
+
setTimeout(resolve, delayMillis);
|
|
4
|
+
});
|
|
5
|
+
|
|
6
6
|
export default sleep;
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = "3.0.
|
|
1
|
+
export const version = "3.0.14"; export const name = "@featbit/js-client-sdk";
|