@devcycle/nodejs-server-sdk
Advanced tools
Comparing version 1.29.0 to 1.30.0
import { DVCLogger } from '@devcycle/types'; | ||
import { ResponseError } from "../server-request/src"; | ||
type ConfigPollingOptions = { | ||
@@ -11,6 +12,11 @@ configPollingIntervalMS?: number; | ||
type ClearIntervalInterface = (intervalTimeout: any) => void; | ||
type SetConfigBuffer = (sdkKey: string, projectConfig: string) => void; | ||
type SetConfigBufferInterface = (sdkKey: string, projectConfig: string) => void; | ||
type TrackSDKConfigEventInterface = (url: string, responseTimeMS: number, res?: Response, err?: ResponseError, reqEtag?: string, reqLastModified?: string) => void; | ||
export declare class EnvironmentConfigManager { | ||
private readonly logger; | ||
private readonly sdkKey; | ||
private readonly setConfigBuffer; | ||
private readonly setInterval; | ||
private readonly clearInterval; | ||
private readonly trackSDKConfigEvent; | ||
private hasConfig; | ||
@@ -25,7 +31,4 @@ configEtag?: string; | ||
private disablePolling; | ||
private readonly setConfigBuffer; | ||
private readonly setInterval; | ||
private readonly clearInterval; | ||
private clientMode; | ||
constructor(logger: DVCLogger, sdkKey: string, setConfigBuffer: SetConfigBuffer, setInterval: SetIntervalInterface, clearInterval: ClearIntervalInterface, { configPollingIntervalMS, configPollingTimeoutMS, configCDNURI, cdnURI, clientMode, }: ConfigPollingOptions); | ||
constructor(logger: DVCLogger, sdkKey: string, setConfigBuffer: SetConfigBufferInterface, setInterval: SetIntervalInterface, clearInterval: ClearIntervalInterface, trackSDKConfigEvent: TrackSDKConfigEventInterface, { configPollingIntervalMS, configPollingTimeoutMS, configCDNURI, cdnURI, clientMode, }: ConfigPollingOptions); | ||
stopPolling(): void; | ||
@@ -32,0 +35,0 @@ cleanup(): void; |
@@ -7,5 +7,3 @@ "use strict"; | ||
class EnvironmentConfigManager { | ||
constructor(logger, sdkKey, setConfigBuffer, setInterval, clearInterval, { configPollingIntervalMS = 10000, configPollingTimeoutMS = 5000, configCDNURI, cdnURI = 'https://config-cdn.devcycle.com', clientMode = false, }) { | ||
this.hasConfig = false; | ||
this.disablePolling = false; | ||
constructor(logger, sdkKey, setConfigBuffer, setInterval, clearInterval, trackSDKConfigEvent, { configPollingIntervalMS = 10000, configPollingTimeoutMS = 5000, configCDNURI, cdnURI = 'https://config-cdn.devcycle.com', clientMode = false, }) { | ||
this.logger = logger; | ||
@@ -16,2 +14,5 @@ this.sdkKey = sdkKey; | ||
this.clearInterval = clearInterval; | ||
this.trackSDKConfigEvent = trackSDKConfigEvent; | ||
this.hasConfig = false; | ||
this.disablePolling = false; | ||
this.clientMode = clientMode; | ||
@@ -61,2 +62,6 @@ this.pollingIntervalMS = | ||
let responseError = null; | ||
const startTime = Date.now(); | ||
let responseTimeMS = 0; | ||
const reqEtag = this.configEtag; | ||
const reqLastModified = this.configLastModified; | ||
const logError = (error) => { | ||
@@ -72,6 +77,12 @@ const errMsg = `Request to get config failed for url: ${url}, ` + | ||
}; | ||
const trackEvent = (err) => { | ||
if ((res && (res === null || res === void 0 ? void 0 : res.status) !== 304) || err) { | ||
this.trackSDKConfigEvent(url, responseTimeMS, res || undefined, err, reqEtag, reqLastModified); | ||
} | ||
}; | ||
try { | ||
this.logger.debug(`Requesting new config for ${url}, etag: ${this.configEtag}` + | ||
`, last-modified: ${this.configLastModified}`); | ||
res = await (0, request_1.getEnvironmentConfig)(url, this.requestTimeoutMS, this.configEtag, this.configLastModified); | ||
res = await (0, request_1.getEnvironmentConfig)(url, this.requestTimeoutMS, reqEtag, reqLastModified); | ||
responseTimeMS = Date.now() - startTime; | ||
projectConfig = await res.text(); | ||
@@ -81,2 +92,3 @@ this.logger.debug(`Downloaded config, status: ${res === null || res === void 0 ? void 0 : res.status}, etag: ${res === null || res === void 0 ? void 0 : res.headers.get('etag')}`); | ||
catch (ex) { | ||
trackEvent(ex); | ||
logError(ex); | ||
@@ -95,8 +107,7 @@ res = null; | ||
try { | ||
const etag = (res === null || res === void 0 ? void 0 : res.headers.get('etag')) || ''; | ||
const lastModified = (res === null || res === void 0 ? void 0 : res.headers.get('last-modified')) || ''; | ||
this.setConfigBuffer(`${this.sdkKey}${this.clientMode ? '_client' : ''}`, projectConfig); | ||
this.hasConfig = true; | ||
this.configEtag = etag; | ||
this.configLastModified = lastModified; | ||
this.configEtag = (res === null || res === void 0 ? void 0 : res.headers.get('etag')) || ''; | ||
this.configLastModified = | ||
(res === null || res === void 0 ? void 0 : res.headers.get('last-modified')) || ''; | ||
return; | ||
@@ -108,2 +119,5 @@ } | ||
} | ||
finally { | ||
trackEvent(); | ||
} | ||
} | ||
@@ -110,0 +124,0 @@ if (this.hasConfig) { |
import { DVCLogger } from '@devcycle/types'; | ||
import { ResponseError } from "../../../../server-request/src"; | ||
type ConfigPollingOptions = { | ||
@@ -11,6 +12,11 @@ configPollingIntervalMS?: number; | ||
type ClearIntervalInterface = (intervalTimeout: any) => void; | ||
type SetConfigBuffer = (sdkKey: string, projectConfig: string) => void; | ||
type SetConfigBufferInterface = (sdkKey: string, projectConfig: string) => void; | ||
type TrackSDKConfigEventInterface = (url: string, responseTimeMS: number, res?: Response, err?: ResponseError, reqEtag?: string, reqLastModified?: string) => void; | ||
export declare class EnvironmentConfigManager { | ||
private readonly logger; | ||
private readonly sdkKey; | ||
private readonly setConfigBuffer; | ||
private readonly setInterval; | ||
private readonly clearInterval; | ||
private readonly trackSDKConfigEvent; | ||
private hasConfig; | ||
@@ -25,7 +31,4 @@ configEtag?: string; | ||
private disablePolling; | ||
private readonly setConfigBuffer; | ||
private readonly setInterval; | ||
private readonly clearInterval; | ||
private clientMode; | ||
constructor(logger: DVCLogger, sdkKey: string, setConfigBuffer: SetConfigBuffer, setInterval: SetIntervalInterface, clearInterval: ClearIntervalInterface, { configPollingIntervalMS, configPollingTimeoutMS, configCDNURI, cdnURI, clientMode, }: ConfigPollingOptions); | ||
constructor(logger: DVCLogger, sdkKey: string, setConfigBuffer: SetConfigBufferInterface, setInterval: SetIntervalInterface, clearInterval: ClearIntervalInterface, trackSDKConfigEvent: TrackSDKConfigEventInterface, { configPollingIntervalMS, configPollingTimeoutMS, configCDNURI, cdnURI, clientMode, }: ConfigPollingOptions); | ||
stopPolling(): void; | ||
@@ -32,0 +35,0 @@ cleanup(): void; |
@@ -7,5 +7,3 @@ "use strict"; | ||
class EnvironmentConfigManager { | ||
constructor(logger, sdkKey, setConfigBuffer, setInterval, clearInterval, { configPollingIntervalMS = 10000, configPollingTimeoutMS = 5000, configCDNURI, cdnURI = 'https://config-cdn.devcycle.com', clientMode = false, }) { | ||
this.hasConfig = false; | ||
this.disablePolling = false; | ||
constructor(logger, sdkKey, setConfigBuffer, setInterval, clearInterval, trackSDKConfigEvent, { configPollingIntervalMS = 10000, configPollingTimeoutMS = 5000, configCDNURI, cdnURI = 'https://config-cdn.devcycle.com', clientMode = false, }) { | ||
this.logger = logger; | ||
@@ -16,2 +14,5 @@ this.sdkKey = sdkKey; | ||
this.clearInterval = clearInterval; | ||
this.trackSDKConfigEvent = trackSDKConfigEvent; | ||
this.hasConfig = false; | ||
this.disablePolling = false; | ||
this.clientMode = clientMode; | ||
@@ -61,2 +62,6 @@ this.pollingIntervalMS = | ||
let responseError = null; | ||
const startTime = Date.now(); | ||
let responseTimeMS = 0; | ||
const reqEtag = this.configEtag; | ||
const reqLastModified = this.configLastModified; | ||
const logError = (error) => { | ||
@@ -72,6 +77,12 @@ const errMsg = `Request to get config failed for url: ${url}, ` + | ||
}; | ||
const trackEvent = (err) => { | ||
if ((res && (res === null || res === void 0 ? void 0 : res.status) !== 304) || err) { | ||
this.trackSDKConfigEvent(url, responseTimeMS, res || undefined, err, reqEtag, reqLastModified); | ||
} | ||
}; | ||
try { | ||
this.logger.debug(`Requesting new config for ${url}, etag: ${this.configEtag}` + | ||
`, last-modified: ${this.configLastModified}`); | ||
res = await (0, request_1.getEnvironmentConfig)(url, this.requestTimeoutMS, this.configEtag, this.configLastModified); | ||
res = await (0, request_1.getEnvironmentConfig)(url, this.requestTimeoutMS, reqEtag, reqLastModified); | ||
responseTimeMS = Date.now() - startTime; | ||
projectConfig = await res.text(); | ||
@@ -81,2 +92,3 @@ this.logger.debug(`Downloaded config, status: ${res === null || res === void 0 ? void 0 : res.status}, etag: ${res === null || res === void 0 ? void 0 : res.headers.get('etag')}`); | ||
catch (ex) { | ||
trackEvent(ex); | ||
logError(ex); | ||
@@ -95,8 +107,7 @@ res = null; | ||
try { | ||
const etag = (res === null || res === void 0 ? void 0 : res.headers.get('etag')) || ''; | ||
const lastModified = (res === null || res === void 0 ? void 0 : res.headers.get('last-modified')) || ''; | ||
this.setConfigBuffer(`${this.sdkKey}${this.clientMode ? '_client' : ''}`, projectConfig); | ||
this.hasConfig = true; | ||
this.configEtag = etag; | ||
this.configLastModified = lastModified; | ||
this.configEtag = (res === null || res === void 0 ? void 0 : res.headers.get('etag')) || ''; | ||
this.configLastModified = | ||
(res === null || res === void 0 ? void 0 : res.headers.get('last-modified')) || ''; | ||
return; | ||
@@ -108,2 +119,5 @@ } | ||
} | ||
finally { | ||
trackEvent(); | ||
} | ||
} | ||
@@ -110,0 +124,0 @@ if (this.hasConfig) { |
{ | ||
"name": "@devcycle/nodejs-server-sdk", | ||
"version": "1.29.0", | ||
"version": "1.30.0", | ||
"description": "The DevCycle NodeJS Server SDK used for feature management.", | ||
@@ -23,5 +23,5 @@ "license": "MIT", | ||
"dependencies": { | ||
"@devcycle/bucketing-assembly-script": "^1.21.0", | ||
"@devcycle/js-cloud-server-sdk": "^1.11.3", | ||
"@devcycle/types": "^1.12.3", | ||
"@devcycle/bucketing-assembly-script": "^1.22.0", | ||
"@devcycle/js-cloud-server-sdk": "^1.12.0", | ||
"@devcycle/types": "^1.13.0", | ||
"cross-fetch": "^4.0.0", | ||
@@ -28,0 +28,0 @@ "fetch-retry": "^5.0.6" |
@@ -6,2 +6,4 @@ import { BucketedUserConfig, DevCycleServerSDKOptions, VariableTypeAlias } from '@devcycle/types'; | ||
export declare class DevCycleClient { | ||
private clientUUID; | ||
private hostname; | ||
private sdkKey; | ||
@@ -30,2 +32,3 @@ private configHelper; | ||
track(user: DevCycleUser, event: DevCycleEvent): void; | ||
private trackSDKConfigEvent; | ||
/** | ||
@@ -32,0 +35,0 @@ * Call this to obtain a config that is suitable for use in the "bootstrapConfig" option of client-side JS SDKs |
@@ -40,2 +40,3 @@ "use strict"; | ||
const populatedUserHelpers_1 = require("./models/populatedUserHelpers"); | ||
const crypto_1 = require("crypto"); | ||
const castIncomingUser = (user) => { | ||
@@ -53,2 +54,4 @@ if (!(user instanceof js_cloud_server_sdk_1.DevCycleUser)) { | ||
this._isInitialized = false; | ||
this.clientUUID = (0, crypto_1.randomUUID)(); | ||
this.hostname = os_1.default.hostname(); | ||
this.sdkKey = sdkKey; | ||
@@ -69,7 +72,7 @@ this.logger = | ||
var _a; | ||
this.configHelper = new config_manager_1.EnvironmentConfigManager(this.logger, sdkKey, bucketing_1.setConfigDataUTF8, setInterval, clearInterval, options || {}); | ||
this.configHelper = new config_manager_1.EnvironmentConfigManager(this.logger, sdkKey, bucketing_1.setConfigDataUTF8, setInterval, clearInterval, this.trackSDKConfigEvent.bind(this), options || {}); | ||
if (options === null || options === void 0 ? void 0 : options.enableClientBootstrapping) { | ||
this.clientConfigHelper = new config_manager_1.EnvironmentConfigManager(this.logger, sdkKey, bucketing_1.setConfigDataUTF8, setInterval, clearInterval, { ...options, clientMode: true }); | ||
this.clientConfigHelper = new config_manager_1.EnvironmentConfigManager(this.logger, sdkKey, bucketing_1.setConfigDataUTF8, setInterval, clearInterval, this.trackSDKConfigEvent.bind(this), { ...options, clientMode: true }); | ||
} | ||
this.eventQueue = new eventQueue_1.EventQueue(sdkKey, { | ||
this.eventQueue = new eventQueue_1.EventQueue(sdkKey, this.clientUUID, { | ||
...options, | ||
@@ -83,3 +86,3 @@ logger: this.logger, | ||
sdkVersion: packageJson.version, | ||
hostname: os_1.default.hostname(), | ||
hostname: this.hostname, | ||
}; | ||
@@ -208,2 +211,23 @@ (0, bucketing_1.getBucketingLib)().setPlatformData(JSON.stringify(platformData)); | ||
} | ||
trackSDKConfigEvent(url, responseTimeMS, res, err, reqEtag, reqLastModified) { | ||
var _a, _b, _c, _d, _e; | ||
const populatedUser = (0, populatedUserHelpers_1.DVCPopulatedUserFromDevCycleUser)({ | ||
user_id: `${this.clientUUID}@${this.hostname}`, | ||
}); | ||
this.eventQueue.queueEvent(populatedUser, { | ||
type: 'sdkConfig', | ||
target: url, | ||
value: responseTimeMS, | ||
metaData: { | ||
clientUUID: this.clientUUID, | ||
reqEtag, | ||
reqLastModified, | ||
resEtag: (_a = res === null || res === void 0 ? void 0 : res.headers.get('etag')) !== null && _a !== void 0 ? _a : undefined, | ||
resLastModified: (_b = res === null || res === void 0 ? void 0 : res.headers.get('last-modified')) !== null && _b !== void 0 ? _b : undefined, | ||
resRayId: (_c = res === null || res === void 0 ? void 0 : res.headers.get('cf-ray')) !== null && _c !== void 0 ? _c : undefined, | ||
resStatus: (_d = ((err === null || err === void 0 ? void 0 : err.status) || (res === null || res === void 0 ? void 0 : res.status))) !== null && _d !== void 0 ? _d : undefined, | ||
errMsg: (_e = err === null || err === void 0 ? void 0 : err.message) !== null && _e !== void 0 ? _e : undefined, | ||
}, | ||
}); | ||
} | ||
/** | ||
@@ -210,0 +234,0 @@ * Call this to obtain a config that is suitable for use in the "bootstrapConfig" option of client-side JS SDKs |
@@ -27,5 +27,6 @@ import { DVCRequestEvent } from './models/requestEvent'; | ||
export declare class EventQueue { | ||
private readonly sdkKey; | ||
private readonly clientUUID; | ||
private readonly logger; | ||
private readonly reporter?; | ||
private readonly sdkKey; | ||
private readonly eventsAPIURI?; | ||
@@ -38,3 +39,3 @@ eventFlushIntervalMS: number; | ||
private flushCallbacks; | ||
constructor(sdkKey: string, options: EventQueueOptions); | ||
constructor(sdkKey: string, clientUUID: string, options: EventQueueOptions); | ||
cleanup(): void; | ||
@@ -41,0 +42,0 @@ private _flushEvents; |
@@ -16,3 +16,5 @@ "use strict"; | ||
class EventQueue { | ||
constructor(sdkKey, options) { | ||
constructor(sdkKey, clientUUID, options) { | ||
this.sdkKey = sdkKey; | ||
this.clientUUID = clientUUID; | ||
this.flushInProgress = false; | ||
@@ -23,3 +25,2 @@ this.flushCallbacks = []; | ||
this.eventsAPIURI = options.eventsAPIURI; | ||
this.sdkKey = sdkKey; | ||
this.eventFlushIntervalMS = (options === null || options === void 0 ? void 0 : options.eventFlushIntervalMS) || 10 * 1000; | ||
@@ -52,3 +53,3 @@ if (this.eventFlushIntervalMS < 500) { | ||
this.flushInterval = setInterval(this.flushEvents.bind(this), this.eventFlushIntervalMS); | ||
(0, bucketing_1.getBucketingLib)().initEventQueue(sdkKey, JSON.stringify(options)); | ||
(0, bucketing_1.getBucketingLib)().initEventQueue(sdkKey, this.clientUUID, JSON.stringify(options)); | ||
} | ||
@@ -55,0 +56,0 @@ cleanup() { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
250506
2385
1
67