Skip to content

Commit 981454f

Browse files
committed
Initial commit
0 parents  commit 981454f

File tree

12 files changed

+298
-0
lines changed

12 files changed

+298
-0
lines changed

.gitignore

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
package-lock.json
15+
16+
# misc
17+
.DS_Store
18+
.env.local
19+
.env.development.local
20+
.env.test.local
21+
.env.production.local
22+
23+
npm-debug.log*
24+
yarn-debug.log*
25+
yarn-error.log*
26+
jmeter.log
27+
jmeter/results.xml
28+
.eslintcache

package-lock.json

+13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "node_sdk",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "src/index.js",
6+
"scripts": {
7+
"start": "node src/index.js",
8+
"test": "echo \"Error: no test specified\" && exit 1"
9+
},
10+
"type": "module",
11+
"author": "",
12+
"license": "ISC",
13+
"dependencies": {
14+
"object-assign": "^4.1.1"
15+
}
16+
}

src/client/ulClient.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
export function ulClient(config) {
3+
return {
4+
config: config,
5+
variation : (flagKey,identity,attributes={}) =>{
6+
if(flagKey == undefined || flagKey.length < 0){
7+
console.error('Please provide valid flagKey');
8+
return "control";
9+
}
10+
if(identity == undefined || identity.length<0){
11+
console.error('Please provide valid identity')
12+
return "control";
13+
}
14+
console.log('evaluating variation')
15+
return "variation-1";
16+
}
17+
}
18+
19+
}

src/client/ulFactory.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* Factory method for UnLaunch Client
3+
*/
4+
5+
import { ConfigsFactory } from '../utils/settings/index.js'
6+
import { validateApiKey } from '../utils/validations/apiKey.js';
7+
import Store from '../utils/store/index.js';
8+
import {CONFIGURATIONS,READY} from '../utils/store/constants.js';
9+
import {ulClient} from '../client/ulClient.js'
10+
11+
12+
export function UnlaunchFactory(configurations) {
13+
const store = new Store();
14+
const configs = ConfigsFactory(configurations);
15+
store.set(CONFIGURATIONS, configs);
16+
store.set(READY, true);
17+
18+
console.log(store.getAll())
19+
if (!configs.core.sdkKey) {
20+
throw ('Factory intantiation requires a valid sdk key');
21+
} else {
22+
if (!validateApiKey(configs.core.sdkKey)) {
23+
throw ('Client intantiation requires a valid sdk key');
24+
}
25+
}
26+
return {
27+
client() {
28+
console.info('New client instance created.');
29+
return ulClient(configs);
30+
},
31+
logger: 'Logger' // add it later
32+
}
33+
}

src/constants/constants.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//constants
2+
export const CONSTANTS = {
3+
SDK_READY: 'Getting ready - Unlaunch SDK',
4+
SDK_VARIATION: 'SDK - Get Variation',
5+
SDK_VARIATION_WITH_CONFIG: 'SDK - Get Variation with config',
6+
FLAGS_READY: 'Getting ready - Feature Flags',
7+
METRICS_PUSH: 'Pushing - Metrics',
8+
IMPRESSIONS_PUSH: 'Pushing - Impressions',
9+
EVENTS_PUSH: 'Pushing - Events',
10+
FLAGS_FETCH: 'Fetching - Feature Flags'
11+
};

src/index.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {UnlaunchFactory} from '../src/client/ulFactory.js';
2+
3+
var factory = UnlaunchFactory({
4+
core:{
5+
sdkKey:'111'
6+
},
7+
intervals: {
8+
// fetch feature updates each 30 sec
9+
pollingInterval: 440,
10+
// publish metrics each 120 sec
11+
metricsFlushInterval: 120,
12+
// flush events every 60 seconds after the first flush
13+
eventsFlushInterval: 60,
14+
// http connection timeout
15+
httpConnectionTimeout: 10
16+
}
17+
});
18+
19+
const client = factory.client();
20+
const variation = client.variation();
21+
console.log("Evaluation Result: "+ variation);

src/utils/lang/index.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
/**
3+
* Checks if a given value is a string.
4+
*/
5+
export function isString(val) {
6+
return typeof val === 'string' || val instanceof String;
7+
}
8+
9+
/**
10+
* Validates if a value is an object.
11+
*/
12+
13+
export function isObject(obj) {
14+
return obj && typeof obj === 'object' && obj.constructor === Object;
15+
}
16+
17+
/**
18+
* Overwriting default with custom configuration
19+
* Validation: Parameters should always be correct (at least have a target and a source, of type object).
20+
*/
21+
22+
export function merge(source, custom) {
23+
let res = {};
24+
25+
isObject(source) && Object.keys(source).forEach(key => {
26+
let val = source[key];
27+
if(custom[key] && isObject(custom[key])){
28+
Object.keys(custom[key]).forEach(customkey =>{
29+
source[key][customkey] = custom[key][customkey];
30+
})
31+
}
32+
33+
});
34+
35+
return source;
36+
}

src/utils/settings/index.js

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import objectAssign from 'object-assign';
2+
import { merge } from "../../../src/utils/lang/index.js";
3+
4+
const base = {
5+
core:{
6+
sdkKey:'',
7+
host:'http://app.unlaunch.io/'
8+
},
9+
intervals: {
10+
// fetch feature updates each 30 sec
11+
pollingInterval: 30,
12+
// publish metrics each 120 sec
13+
metricsFlushInterval: 120,
14+
// flush events every 60 seconds after the first flush
15+
eventsFlushInterval: 60,
16+
// http connection timeout
17+
httpConnectionTimeout: 10
18+
},
19+
mode: {
20+
offlineMode: false
21+
},
22+
23+
urls: {
24+
// CDN having all the information for your environment
25+
sdk: '/api/v1/flags',
26+
// Storage for your SDK events
27+
events: '/api/v1/events'
28+
},
29+
30+
};
31+
32+
function fromSecondsToMillis(n) {
33+
return Math.round(n * 1000);
34+
}
35+
36+
function defaults(custom) {
37+
const withDefaults = merge(base, custom);
38+
39+
// // Scheduler periods
40+
withDefaults.intervals.pollingInterval = fromSecondsToMillis(withDefaults.intervals.pollingInterval);
41+
withDefaults.intervals.metricsFlushInterval = fromSecondsToMillis(withDefaults.intervals.metricsFlushInterval);
42+
withDefaults.intervals.httpConnectionTimeout = fromSecondsToMillis(withDefaults.intervals.httpConnectionTimeout);
43+
withDefaults.intervals.eventsFlushInterval = fromSecondsToMillis(withDefaults.intervals.eventsFlushInterval);
44+
45+
// // mode
46+
// withDefaults.mode.offlineMode = false;
47+
48+
// Startup periods
49+
// withDefaults.startup.requestTimeoutBeforeReady = fromSecondsToMillis(withDefaults.startup.requestTimeoutBeforeReady);
50+
// withDefaults.startup.readyTimeout = fromSecondsToMillis(withDefaults.startup.readyTimeout);
51+
// withDefaults.startup.eventsFirstPushWindow = fromSecondsToMillis(withDefaults.startup.eventsFirstPushWindow);
52+
53+
return withDefaults;
54+
}
55+
56+
export const ConfigsFactory = (configurations) => objectAssign(Object.create({}), defaults(configurations));

src/utils/store/constants.js

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const CONFIGURATIONS = "configs"
2+
export const READY="ready"

src/utils/store/index.js

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import objectAssign from 'object-assign'
2+
3+
class Store {
4+
constructor() {
5+
this._unlaunchMap = {};
6+
}
7+
// set key value in map
8+
set(key, value) {
9+
if (typeof key !== 'string' || (typeof key === 'string' && !key.length) || key === undefined) return false; // We can't store this.
10+
this._unlaunchMap[key] = value;
11+
return true;
12+
}
13+
14+
//get a particular key from context
15+
get(key){
16+
if (typeof key !== 'string' || typeof key === 'string' && !key.length) return null;
17+
const value = this._unlaunchMap[key];
18+
if (value !== undefined) {
19+
return value;
20+
}
21+
return null;
22+
}
23+
24+
// get all items stored in context
25+
getAll() { return objectAssign({}, this._unlaunchMap); }
26+
27+
}
28+
29+
export default Store;

src/utils/validations/apiKey.js

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { isString } from "../../../src/utils/lang/index.js";
2+
3+
const usedKeysMap = {};
4+
5+
export function validateApiKey(maybeApiKey) {
6+
let apiKey = false;
7+
if (maybeApiKey == undefined) { // eslint-disable-line eqeqeq
8+
console.log('Factory instantiation: you passed a null or undefined api_key, api_key must be a non-empty string.');
9+
//log.error
10+
} else if (isString(maybeApiKey)) {
11+
if (maybeApiKey.length > 0)
12+
apiKey = maybeApiKey;
13+
else
14+
console.error('Factory instantiation: you passed an empty api_key, api_key must be a non-empty string.');
15+
} else {
16+
console.error('Factory instantiation: you passed an invalid api_key, api_key must be a non-empty string.');
17+
}
18+
19+
// // If the apiKey is correct, we'll save it as the instance creation should work.
20+
// if (apiKey) {
21+
// if (!usedKeysMap[apiKey]) {
22+
// // If this key is not present, only warning scenarios is that we have factories for other keys.
23+
// usedKeysMap[apiKey] = 1;
24+
// if (Object.keys(usedKeysMap).length > 1) {
25+
// console.log('Factory instantiation: You already have an instance of the Split factory. Make sure you definitely want this additional instance. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.');
26+
// }
27+
// } else {
28+
// console.log(`Factory instantiation: You already have ${usedKeysMap[apiKey]} ${usedKeysMap[apiKey] === 1 ? 'factory' : 'factories'} with this API Key. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application.`);
29+
// usedKeysMap[apiKey]++;
30+
// }
31+
// }
32+
33+
return apiKey;
34+
}

0 commit comments

Comments
 (0)