@featbit/js-client-sdk 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +289 -0
- package/esm/constants.d.ts +7 -0
- package/esm/constants.js +8 -0
- package/esm/constants.js.map +1 -0
- package/esm/events.d.ts +14 -0
- package/esm/events.js +27 -0
- package/esm/events.js.map +1 -0
- package/esm/featbit.d.ts +34 -0
- package/esm/featbit.js +382 -0
- package/esm/featbit.js.map +1 -0
- package/esm/index.d.ts +4 -0
- package/esm/index.js +5 -0
- package/esm/index.js.map +1 -0
- package/esm/logger.d.ts +4 -0
- package/esm/logger.js +24 -0
- package/esm/logger.js.map +1 -0
- package/esm/network.service.d.ts +27 -0
- package/esm/network.service.js +288 -0
- package/esm/network.service.js.map +1 -0
- package/esm/optionMessages.d.ts +5 -0
- package/esm/optionMessages.js +16 -0
- package/esm/optionMessages.js.map +1 -0
- package/esm/queue.d.ts +8 -0
- package/esm/queue.js +35 -0
- package/esm/queue.js.map +1 -0
- package/esm/store.d.ts +20 -0
- package/esm/store.js +143 -0
- package/esm/store.js.map +1 -0
- package/esm/throttleutil.d.ts +9 -0
- package/esm/throttleutil.js +133 -0
- package/esm/throttleutil.js.map +1 -0
- package/esm/types.d.ts +94 -0
- package/esm/types.js +24 -0
- package/esm/types.js.map +1 -0
- package/esm/umd.d.ts +2 -0
- package/esm/utils.d.ts +11 -0
- package/esm/utils.js +142 -0
- package/esm/utils.js.map +1 -0
- package/package.json +48 -0
- package/src/constants.ts +7 -0
- package/src/events.ts +29 -0
- package/src/featbit.ts +343 -0
- package/src/index.ts +6 -0
- package/src/logger.ts +18 -0
- package/src/network.service.ts +223 -0
- package/src/optionMessages.ts +13 -0
- package/src/queue.ts +23 -0
- package/src/store.ts +169 -0
- package/src/throttleutil.ts +72 -0
- package/src/types.ts +113 -0
- package/src/umd.ts +15 -0
- package/src/utils.ts +173 -0
- package/umd/featbit-js-client-sdk-2.0.0.js +2 -0
- package/umd/featbit-js-client-sdk-2.0.0.js.map +1 -0
- package/umd/featbit-js-client-sdk.js +2 -0
- package/umd/featbit-js-client-sdk.js.map +1 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
23
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
+
function step(op) {
|
|
26
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
28
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
+
switch (op[0]) {
|
|
31
|
+
case 0: case 1: t = op; break;
|
|
32
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
+
default:
|
|
36
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
+
if (t[2]) _.ops.pop();
|
|
41
|
+
_.trys.pop(); continue;
|
|
42
|
+
}
|
|
43
|
+
op = body.call(thisArg, _);
|
|
44
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
49
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
50
|
+
if (ar || !(i in from)) {
|
|
51
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
52
|
+
ar[i] = from[i];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
56
|
+
};
|
|
57
|
+
import { uuid } from "./utils";
|
|
58
|
+
var API_CALL_RESULTS = {};
|
|
59
|
+
var FOOT_PRINTS = [];
|
|
60
|
+
var _throttleWait = 0; // send immediately
|
|
61
|
+
var ThrottleUtil = /** @class */ (function () {
|
|
62
|
+
function ThrottleUtil() {
|
|
63
|
+
this._key = uuid();
|
|
64
|
+
}
|
|
65
|
+
ThrottleUtil.prototype.setKey = function (key) {
|
|
66
|
+
this._key = key || this._key;
|
|
67
|
+
};
|
|
68
|
+
ThrottleUtil.prototype.throttle = function (fn, ms) {
|
|
69
|
+
var timer = 0;
|
|
70
|
+
return function () {
|
|
71
|
+
var args = [];
|
|
72
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
73
|
+
args[_i] = arguments[_i];
|
|
74
|
+
}
|
|
75
|
+
clearTimeout(timer);
|
|
76
|
+
timer = setTimeout(fn.bind.apply(fn, __spreadArray([null], args, false)), ms || 0);
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
ThrottleUtil.prototype.throttleAsync = function (callback) {
|
|
80
|
+
var _this = this;
|
|
81
|
+
var waiting = false;
|
|
82
|
+
var getFootprint = function (args) {
|
|
83
|
+
var params = args.map(function (arg) {
|
|
84
|
+
if (typeof arg === 'object' &&
|
|
85
|
+
typeof arg !== "function" &&
|
|
86
|
+
arg !== null) {
|
|
87
|
+
if (Array.isArray(arg)) {
|
|
88
|
+
return arg.map(function (a) { return (__assign(__assign({}, a), { timestamp: null })); });
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return __assign(__assign({}, arg), { timestamp: null });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return arg;
|
|
95
|
+
});
|
|
96
|
+
return _this._key + JSON.stringify(params);
|
|
97
|
+
};
|
|
98
|
+
return function () {
|
|
99
|
+
var args = [];
|
|
100
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
101
|
+
args[_i] = arguments[_i];
|
|
102
|
+
}
|
|
103
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
104
|
+
var footprint, idx, _a, _b;
|
|
105
|
+
return __generator(this, function (_c) {
|
|
106
|
+
switch (_c.label) {
|
|
107
|
+
case 0:
|
|
108
|
+
footprint = getFootprint(args);
|
|
109
|
+
idx = FOOT_PRINTS.findIndex(function (f) { return f === footprint; });
|
|
110
|
+
if (!(!waiting || idx === -1)) return [3 /*break*/, 2];
|
|
111
|
+
waiting = true;
|
|
112
|
+
if (idx === -1) {
|
|
113
|
+
FOOT_PRINTS.push(footprint);
|
|
114
|
+
}
|
|
115
|
+
_a = API_CALL_RESULTS;
|
|
116
|
+
_b = footprint;
|
|
117
|
+
return [4 /*yield*/, callback.apply(null, args)];
|
|
118
|
+
case 1:
|
|
119
|
+
_a[_b] = _c.sent();
|
|
120
|
+
setTimeout(function () {
|
|
121
|
+
waiting = false;
|
|
122
|
+
}, _throttleWait);
|
|
123
|
+
_c.label = 2;
|
|
124
|
+
case 2: return [2 /*return*/, API_CALL_RESULTS[footprint]];
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
return ThrottleUtil;
|
|
131
|
+
}());
|
|
132
|
+
export default new ThrottleUtil();
|
|
133
|
+
//# sourceMappingURL=throttleutil.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"throttleutil.js","sourceRoot":"","sources":["../src/throttleutil.ts"],"names":[],"mappings":"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"}
|
package/esm/types.d.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
export type FeatureFlagValue = any;
|
|
2
|
+
export interface IFeatureFlagSet {
|
|
3
|
+
[key: string]: FeatureFlagValue;
|
|
4
|
+
}
|
|
5
|
+
export interface IFeatureFlagChange {
|
|
6
|
+
id: string;
|
|
7
|
+
oldValue: FeatureFlagValue;
|
|
8
|
+
newValue: FeatureFlagValue;
|
|
9
|
+
}
|
|
10
|
+
export interface IOption {
|
|
11
|
+
secret: string;
|
|
12
|
+
anonymous?: boolean;
|
|
13
|
+
bootstrap?: IFeatureFlag[];
|
|
14
|
+
streamingUri?: string;
|
|
15
|
+
eventsUri?: string;
|
|
16
|
+
api?: string;
|
|
17
|
+
appType?: string;
|
|
18
|
+
user?: IUser;
|
|
19
|
+
enableDataSync?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface IUser {
|
|
22
|
+
name: string;
|
|
23
|
+
keyId: string;
|
|
24
|
+
customizedProperties?: ICustomizedProperty[];
|
|
25
|
+
}
|
|
26
|
+
export interface ICustomizedProperty {
|
|
27
|
+
name: string;
|
|
28
|
+
value: string | number | boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface IVariationOption {
|
|
31
|
+
id: number;
|
|
32
|
+
value: FeatureFlagValue;
|
|
33
|
+
}
|
|
34
|
+
export interface IFeatureFlagVariation {
|
|
35
|
+
id?: string;
|
|
36
|
+
sendToExperiment?: boolean;
|
|
37
|
+
timestamp?: number;
|
|
38
|
+
variation?: {
|
|
39
|
+
id: number;
|
|
40
|
+
value: FeatureFlagValue;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export interface IFeatureFlagVariationBuffer {
|
|
44
|
+
id: string;
|
|
45
|
+
timestamp: number;
|
|
46
|
+
variationValue: FeatureFlagValue;
|
|
47
|
+
}
|
|
48
|
+
export declare enum InsightType {
|
|
49
|
+
featureFlagUsage = 1,
|
|
50
|
+
customEvent = 2,
|
|
51
|
+
pageView = 3,
|
|
52
|
+
click = 4
|
|
53
|
+
}
|
|
54
|
+
export declare enum VariationDataType {
|
|
55
|
+
string = "string",
|
|
56
|
+
boolean = "boolean",
|
|
57
|
+
number = "number",
|
|
58
|
+
json = "json"
|
|
59
|
+
}
|
|
60
|
+
export interface IInsight extends IFeatureFlagVariation, ICustomEvent {
|
|
61
|
+
insightType: InsightType;
|
|
62
|
+
}
|
|
63
|
+
export interface IFeatureFlagBase {
|
|
64
|
+
id: string;
|
|
65
|
+
variation: FeatureFlagValue;
|
|
66
|
+
variationType: VariationDataType;
|
|
67
|
+
}
|
|
68
|
+
export interface IFeatureFlag extends IFeatureFlagBase {
|
|
69
|
+
sendToExperiment: boolean;
|
|
70
|
+
timestamp: number;
|
|
71
|
+
variationOptions: IVariationOption[];
|
|
72
|
+
}
|
|
73
|
+
export interface IDataStore {
|
|
74
|
+
featureFlags: {
|
|
75
|
+
[key: string]: IFeatureFlag;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export declare enum StreamResponseEventType {
|
|
79
|
+
full = "full",
|
|
80
|
+
patch = "patch"
|
|
81
|
+
}
|
|
82
|
+
export declare enum FeatureFlagUpdateOperation {
|
|
83
|
+
update = "update"
|
|
84
|
+
}
|
|
85
|
+
export interface IStreamResponse {
|
|
86
|
+
eventType: StreamResponseEventType;
|
|
87
|
+
userKeyId: string;
|
|
88
|
+
featureFlags: IFeatureFlag[];
|
|
89
|
+
}
|
|
90
|
+
export interface ICustomEvent {
|
|
91
|
+
type?: string;
|
|
92
|
+
eventName: string;
|
|
93
|
+
numericValue?: number;
|
|
94
|
+
}
|
package/esm/types.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export var InsightType;
|
|
2
|
+
(function (InsightType) {
|
|
3
|
+
InsightType[InsightType["featureFlagUsage"] = 1] = "featureFlagUsage";
|
|
4
|
+
InsightType[InsightType["customEvent"] = 2] = "customEvent";
|
|
5
|
+
InsightType[InsightType["pageView"] = 3] = "pageView";
|
|
6
|
+
InsightType[InsightType["click"] = 4] = "click";
|
|
7
|
+
})(InsightType || (InsightType = {}));
|
|
8
|
+
export var VariationDataType;
|
|
9
|
+
(function (VariationDataType) {
|
|
10
|
+
VariationDataType["string"] = "string";
|
|
11
|
+
VariationDataType["boolean"] = "boolean";
|
|
12
|
+
VariationDataType["number"] = "number";
|
|
13
|
+
VariationDataType["json"] = "json";
|
|
14
|
+
})(VariationDataType || (VariationDataType = {}));
|
|
15
|
+
export var StreamResponseEventType;
|
|
16
|
+
(function (StreamResponseEventType) {
|
|
17
|
+
StreamResponseEventType["full"] = "full";
|
|
18
|
+
StreamResponseEventType["patch"] = "patch";
|
|
19
|
+
})(StreamResponseEventType || (StreamResponseEventType = {}));
|
|
20
|
+
export var FeatureFlagUpdateOperation;
|
|
21
|
+
(function (FeatureFlagUpdateOperation) {
|
|
22
|
+
FeatureFlagUpdateOperation["update"] = "update";
|
|
23
|
+
})(FeatureFlagUpdateOperation || (FeatureFlagUpdateOperation = {}));
|
|
24
|
+
//# sourceMappingURL=types.js.map
|
package/esm/types.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA2DA,MAAM,CAAN,IAAY,WAKX;AALD,WAAY,WAAW;IACrB,qEAAoB,CAAA;IACpB,2DAAe,CAAA;IACf,qDAAY,CAAA;IACZ,+CAAS,CAAA;AACX,CAAC,EALW,WAAW,KAAX,WAAW,QAKtB;AAED,MAAM,CAAN,IAAY,iBAKX;AALD,WAAY,iBAAiB;IAC3B,sCAAiB,CAAA;IACjB,wCAAmB,CAAA;IACnB,sCAAiB,CAAA;IACjB,kCAAa,CAAA;AACf,CAAC,EALW,iBAAiB,KAAjB,iBAAiB,QAK5B;AAsBD,MAAM,CAAN,IAAY,uBAGX;AAHD,WAAY,uBAAuB;IACjC,wCAAa,CAAA;IACb,0CAAe,CAAA;AACjB,CAAC,EAHW,uBAAuB,KAAvB,uBAAuB,QAGlC;AAED,MAAM,CAAN,IAAY,0BAEX;AAFD,WAAY,0BAA0B;IACpC,+CAAiB,CAAA;AACnB,CAAC,EAFW,0BAA0B,KAA1B,0BAA0B,QAErC"}
|
package/esm/umd.d.ts
ADDED
package/esm/utils.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FeatureFlagValue, IOption, IUser, VariationDataType } from "./types";
|
|
2
|
+
export declare function generateorGetGuid(): string;
|
|
3
|
+
export declare function serializeUser(user: IUser | undefined): string;
|
|
4
|
+
export declare function isNumeric(str: string): boolean;
|
|
5
|
+
export declare function parseVariation(type: VariationDataType, value: string): FeatureFlagValue;
|
|
6
|
+
export declare function uuid(): string;
|
|
7
|
+
export declare function validateUser(user: IUser): string | null;
|
|
8
|
+
export declare function isNullOrUndefinedOrWhiteSpace(value?: string): boolean;
|
|
9
|
+
export declare function validateOption(option: IOption): string | null;
|
|
10
|
+
export declare function generateConnectionToken(text: string): string;
|
|
11
|
+
/********************** encode text end *****************************/
|
package/esm/utils.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { VariationDataType } from "./types";
|
|
2
|
+
import { logger } from "./logger";
|
|
3
|
+
import OptionMessages from "./optionMessages";
|
|
4
|
+
// generate default user info
|
|
5
|
+
export function generateorGetGuid() {
|
|
6
|
+
var guid = localStorage.getItem("fb-guid");
|
|
7
|
+
if (guid) {
|
|
8
|
+
return guid;
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
var id = uuid();
|
|
12
|
+
localStorage.setItem("fb-guid", id);
|
|
13
|
+
return id;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function serializeUser(user) {
|
|
17
|
+
var _a;
|
|
18
|
+
if (!user) {
|
|
19
|
+
return '';
|
|
20
|
+
}
|
|
21
|
+
var builtInProperties = "".concat(user.keyId, ",").concat(user.name);
|
|
22
|
+
var customizedProperties = (_a = user.customizedProperties) === null || _a === void 0 ? void 0 : _a.map(function (p) { return "".concat(p.name, ":").concat(p.value); }).join(',');
|
|
23
|
+
return "".concat(builtInProperties, ",").concat(customizedProperties);
|
|
24
|
+
}
|
|
25
|
+
export function isNumeric(str) {
|
|
26
|
+
if (typeof str != "string")
|
|
27
|
+
return false; // we only process strings!
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
return !isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
|
|
30
|
+
!isNaN(parseFloat(str)); // ...and ensure strings of whitespace fail
|
|
31
|
+
}
|
|
32
|
+
export function parseVariation(type, value) {
|
|
33
|
+
switch (type) {
|
|
34
|
+
case VariationDataType.string:
|
|
35
|
+
return value;
|
|
36
|
+
case VariationDataType.boolean:
|
|
37
|
+
if (value === 'true') {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
if (value === 'false') {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
logger.log("expected boolean value, but got ".concat(value));
|
|
44
|
+
return value;
|
|
45
|
+
case VariationDataType.number:
|
|
46
|
+
if (isNumeric(value)) {
|
|
47
|
+
return +value;
|
|
48
|
+
}
|
|
49
|
+
logger.log("expected numeric value, but got ".concat(value));
|
|
50
|
+
return value;
|
|
51
|
+
case VariationDataType.json:
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(value);
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
logger.log("expected json value, but got ".concat(value));
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
default:
|
|
60
|
+
logger.log("unexpected variation type ".concat(type, " for ").concat(value));
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export function uuid() {
|
|
65
|
+
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
66
|
+
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
|
67
|
+
return v.toString(16);
|
|
68
|
+
});
|
|
69
|
+
return uuid;
|
|
70
|
+
}
|
|
71
|
+
export function validateUser(user) {
|
|
72
|
+
if (!user) {
|
|
73
|
+
return OptionMessages.mandatory('user');
|
|
74
|
+
}
|
|
75
|
+
var keyId = user.keyId, name = user.name;
|
|
76
|
+
if (keyId === undefined || keyId === null || keyId.trim() === '') {
|
|
77
|
+
return OptionMessages.mandatory('user.keyId');
|
|
78
|
+
}
|
|
79
|
+
if (name === undefined || name === null || name.trim() === '') {
|
|
80
|
+
return OptionMessages.mandatory('user.name');
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
export function isNullOrUndefinedOrWhiteSpace(value) {
|
|
85
|
+
return value === null || value === undefined || value.trim() === '';
|
|
86
|
+
}
|
|
87
|
+
export function validateOption(option) {
|
|
88
|
+
if (option === undefined || option === null) {
|
|
89
|
+
return OptionMessages.mandatory('option');
|
|
90
|
+
}
|
|
91
|
+
var streamingUri = option.streamingUri, eventsUri = option.eventsUri, secret = option.secret, anonymous = option.anonymous, user = option.user, enableDataSync = option.enableDataSync;
|
|
92
|
+
var streamingUriMissing = isNullOrUndefinedOrWhiteSpace(streamingUri);
|
|
93
|
+
var eventsUriMissing = isNullOrUndefinedOrWhiteSpace(eventsUri);
|
|
94
|
+
if (enableDataSync && (streamingUriMissing || eventsUriMissing)) {
|
|
95
|
+
if (eventsUriMissing) {
|
|
96
|
+
return OptionMessages.partialEndpoint('eventsUri');
|
|
97
|
+
}
|
|
98
|
+
if (streamingUriMissing) {
|
|
99
|
+
return OptionMessages.partialEndpoint('streamingUri');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (enableDataSync && isNullOrUndefinedOrWhiteSpace(secret)) {
|
|
103
|
+
return OptionMessages.invalidParam('secret');
|
|
104
|
+
}
|
|
105
|
+
// validate user
|
|
106
|
+
if (!!anonymous === false && !user) {
|
|
107
|
+
return OptionMessages.mandatory('user');
|
|
108
|
+
}
|
|
109
|
+
if (user) {
|
|
110
|
+
return validateUser(user);
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
/********************** encode text begin *****************************/
|
|
115
|
+
var alphabet = {
|
|
116
|
+
"0": "Q",
|
|
117
|
+
"1": "B",
|
|
118
|
+
"2": "W",
|
|
119
|
+
"3": "S",
|
|
120
|
+
"4": "P",
|
|
121
|
+
"5": "H",
|
|
122
|
+
"6": "D",
|
|
123
|
+
"7": "X",
|
|
124
|
+
"8": "Z",
|
|
125
|
+
"9": "U",
|
|
126
|
+
};
|
|
127
|
+
function encodeNumber(param, length) {
|
|
128
|
+
var s = "000000000000" + param;
|
|
129
|
+
var numberWithLeadingZeros = s.slice(s.length - length);
|
|
130
|
+
return numberWithLeadingZeros.split('').map(function (n) { return alphabet[n]; }).join('');
|
|
131
|
+
}
|
|
132
|
+
// generate connection token
|
|
133
|
+
export function generateConnectionToken(text) {
|
|
134
|
+
text = text.replace(/=*$/, '');
|
|
135
|
+
var timestamp = Date.now();
|
|
136
|
+
var timestampCode = encodeNumber(timestamp, timestamp.toString().length);
|
|
137
|
+
// get random number less than the length of the text as the start point, and it must be greater or equal to 2
|
|
138
|
+
var start = Math.max(Math.floor(Math.random() * text.length), 2);
|
|
139
|
+
return "".concat(encodeNumber(start, 3)).concat(encodeNumber(timestampCode.length, 2)).concat(text.slice(0, start)).concat(timestampCode).concat(text.slice(start));
|
|
140
|
+
}
|
|
141
|
+
/********************** encode text end *****************************/
|
|
142
|
+
//# sourceMappingURL=utils.js.map
|
package/esm/utils.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@featbit/js-client-sdk",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "https://github.com/featbit/featbit-js-client-sdk",
|
|
5
|
+
"main": "esm/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"watch-esm": "rimraf esm && tsc --watch",
|
|
8
|
+
"watch-umd": "rimraf umd && webpack --watch --mode development",
|
|
9
|
+
"build": "rimraf umd && rimraf esm && tsc && webpack --mode production",
|
|
10
|
+
"prepublishOnly": "npm run build",
|
|
11
|
+
"lint": "gts lint",
|
|
12
|
+
"clean": "gts clean",
|
|
13
|
+
"compile": "tsc",
|
|
14
|
+
"fix": "gts fix"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/featbit/featbit-js-client-sdk.git"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"featbit",
|
|
22
|
+
"feature flags",
|
|
23
|
+
"feature management"
|
|
24
|
+
],
|
|
25
|
+
"author": "featbit.co",
|
|
26
|
+
"license": "ISC",
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/featbit/featbit-js-client-sdk/issues"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/featbit/featbit-js-client-sdk#readme",
|
|
31
|
+
"files": [
|
|
32
|
+
"/esm",
|
|
33
|
+
"/umd",
|
|
34
|
+
"/src"
|
|
35
|
+
],
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"gts": "^5.2.0",
|
|
38
|
+
"rimraf": "^3.0.2",
|
|
39
|
+
"string-replace-loader": "^3.1.0",
|
|
40
|
+
"ts-loader": "^9.2.6",
|
|
41
|
+
"tslint": "^6.1.3",
|
|
42
|
+
"typescript": "^5.2.2",
|
|
43
|
+
"webpack": "^5.67.0",
|
|
44
|
+
"webpack-cli": "^4.9.2"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const insightsFlushTopic = 'insights.flush';
|
|
2
|
+
export const featureFlagEvaluatedTopic = 'featureflag.evaluated.topic';
|
|
3
|
+
export const featureFlagEvaluatedBufferTopic = 'featureflag.evaluated.buffer.topic';
|
|
4
|
+
export const websocketReconnectTopic = 'network.websocket.reconnect';
|
|
5
|
+
export const debugModeQueryStr = 'debugmode'; // will print debug logs if true
|
|
6
|
+
export const insightsTopic = 'insights.topic';
|
|
7
|
+
export const currentUserStorageKey = 'fb-user';
|
package/src/events.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
interface Events {
|
|
2
|
+
[key: string]: Function[];
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
class EventEmitter {
|
|
6
|
+
public events: Events;
|
|
7
|
+
constructor(events?: Events) {
|
|
8
|
+
this.events = events || {};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public subscribe(name: string, cb: Function) {
|
|
12
|
+
(this.events[name] || (this.events[name] = [])).push(cb);
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
unsubscribe: () =>
|
|
16
|
+
this.events[name] && this.events[name].splice(this.events[name].indexOf(cb) >>> 0, 1)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public unsubscribe(name: string, cb: Function) {
|
|
21
|
+
this.events[name] && this.events[name].splice(this.events[name].indexOf(cb) >>> 0, 1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public emit(name: string, ...args: any[]): void {
|
|
25
|
+
(this.events[name] || []).forEach(fn => fn(...args));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const eventHub = new EventEmitter();
|