Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"node": ">= 12"
},
"devDependencies": {
"@types/eventsource": "^1.1.6",
"@types/jest": "~26.0.23",
"@types/node": "^14.17.11",
"@typescript-eslint/eslint-plugin": "~4.28.2",
Expand Down Expand Up @@ -35,7 +36,9 @@
"license": "Apache-2.0",
"dependencies": {
"@openapitools/openapi-generator-cli": "^2.3.10",
"eventsource": "^1.1.0",
"jwt-decode": "^3.1.2",
"node-cache": "^5.1.2",
"tslib": "~2.3.0"
},
"volta": {
Expand Down
31 changes: 31 additions & 0 deletions src/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { FeatureConfig, Segment } from "./openapi";

export type CacheValueType = FeatureConfig | Segment;

export interface Cache {
set(key: string, value: CacheValueType): void;
get(key: string): CacheValueType;
del(key: string): void;
}

export class SimpleCache implements Cache {
private cache = {};

set(key: string, value: CacheValueType): void {
this.cache[key] = value;
}
get(key: string): CacheValueType {
return this.cache[key];
}
del(key: string): void {
delete this.cache[key];
}
}

export const formatFlagKey = (key: string): string => {
return `flags/${key}`
}

export const formatSegmentKey = (key: string): string => {
return `segments/${key}`
}
75 changes: 38 additions & 37 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import jwt_decode from 'jwt-decode';
import { Claims, defaultOptions, Options } from './types';
import { Configuration, DefaultApi, Target } from './openapi';
import { VERSION } from './utils';
import { log, VERSION } from './utils';
import { PollingProcessor } from './polling';
import { StreamProcessor } from './streaming';
import * as events from 'events';

export class CfClient {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I'd consider this in the scope of this ticket, but since we no longer use "Continuous Features", should this be FFClient?

private api: DefaultApi;
Expand All @@ -11,6 +14,9 @@ export class CfClient {
private configuration: Configuration;
private options: Options;
private cluster = '1';
private eventBus = new events.EventEmitter();
private pollProcessor: PollingProcessor;
private streamProcessor: StreamProcessor;

constructor(sdkKey: string, options: Options = {}) {
this.sdkKey = sdkKey;
Expand Down Expand Up @@ -43,45 +49,33 @@ export class CfClient {
return this.authToken;
}

fetchData(): Promise<[void, void]> {
const flags = this.api
.getFeatureConfig(this.environment, {
params: {
cluster: this.cluster,
},
})
.then((response) => {
// prepare cache for storing flags
console.log(response.data);
})
.catch((error: Error) => {
console.error('Error loading flags', error);
throw error;
});
const segments = this.api
.getAllSegments(this.environment, {
params: {
cluster: this.cluster,
},
})
.then((response) => {
// prepare cache for storing segments
console.log(response.data);
})
.catch((error: Error) => {
console.error('Error loading segments', error);
throw error;
});

return Promise.all([flags, segments]);
}

async run(): Promise<void> {
await this.authenticate();
await this.fetchData();
this.pollProcessor = new PollingProcessor(
this.environment,
this.cluster,
this.api,
this.options,
this.eventBus,
);

// start processors
this.pollProcessor.start();
if (this.options.enableStream) {
// setup SSE client
this.streamProcessor = new StreamProcessor(
this.api,
this.sdkKey,
this.environment,
this.authToken,
this.options,
this.cluster,
this.eventBus,
);

this.streamProcessor.start();
}

log.info('finished setting up processors');
}

boolVariation(
Expand All @@ -92,8 +86,15 @@ export class CfClient {
console.log(identifier, target);
return defaultValue;
}

close(): void {
this.pollProcessor.close();
if (this.options.enableStream) {
this.streamProcessor.close();
}
}
}

// need to setup example project and remove this later
const client = new CfClient('sdk key');
const client = new CfClient('1c100d25-4c3f-487b-b198-3b3d01df5794');
client.boolVariation('test', null, false);
27 changes: 27 additions & 0 deletions src/log.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export interface Logger {
trace(message?: unknown, ...optionalParams: unknown[]): void;
debug(message?: unknown, ...optionalParams: unknown[]): void;
info(message?: unknown, ...optionalParams: unknown[]): void;
warn(message?: unknown, ...optionalParams: unknown[]): void;
error(message?: unknown, ...optionalParams: unknown[]): void;
}

// Wrapper for console
export class ConsoleLog implements Logger {

trace(message?: unknown, ...optionalParams: unknown[]): void {
console.trace(message, ...optionalParams);
}
debug(message?: unknown, ...optionalParams: unknown[]): void {
console.debug(message, ...optionalParams);
}
info(message?: unknown, ...optionalParams: unknown[]): void {
console.info(message, ...optionalParams);
}
warn(message?: unknown, ...optionalParams: unknown[]): void {
console.warn(message, ...optionalParams);
}
error(message?: unknown, ...optionalParams: unknown[]): void {
console.error(message, ...optionalParams);
}
}
Loading