diff --git a/sdk/nodejs/__tests__/client.spec.ts b/sdk/nodejs/__tests__/client.spec.ts index 0a6b2515b..8a2e4e9d8 100644 --- a/sdk/nodejs/__tests__/client.spec.ts +++ b/sdk/nodejs/__tests__/client.spec.ts @@ -1,5 +1,4 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ -import { getBucketingLib } from '../src/bucketing' import { DevCycleClient } from '../src/client' import { DevCycleUser } from '@devcycle/js-cloud-server-sdk' @@ -33,10 +32,10 @@ jest.mock('../src/eventQueue') describe('DevCycleClient', () => { it('imports bucketing lib on initialize', async () => { const client = new DevCycleClient('token') - expect(() => getBucketingLib()).toThrow() + expect((client as any).bucketing).toBeUndefined() await client.onClientInitialized() - const platformData = (getBucketingLib().setPlatformData as any).mock - .calls[0][0] + const platformData = ((client as any).bucketing.setPlatformData as any) + .mock.calls[0][0] expect(JSON.parse(platformData)).toEqual({ platform: 'NodeJS', @@ -92,19 +91,19 @@ describe('variable', () => { it('returns a valid variable object for a variable that is not in the config', () => { // @ts-ignore - getBucketingLib().variableForUser_PB.mockReturnValueOnce(null) + client.bucketing.variableForUser_PB.mockReturnValueOnce(null) const variable = client.variable(user, 'test-key2', false) expect(variable.value).toEqual(false) expect(variable.isDefaulted).toEqual(true) // @ts-ignore - getBucketingLib().variableForUser_PB.mockReturnValueOnce(null) + client.bucketing.variableForUser_PB.mockReturnValueOnce(null) expect(client.variableValue(user, 'test-key2', false)).toEqual(false) }) it('returns a defaulted variable object for a variable that is in the config but the wrong type', () => { // @ts-ignore - getBucketingLib().variableForUser.mockReturnValueOnce(null) + client.bucketing.variableForUser.mockReturnValueOnce(null) const variable = client.variable(user, 'test-key', 'test') expect(variable.value).toEqual('test') expect(variable.isDefaulted).toEqual(true) diff --git a/sdk/nodejs/__tests__/eventQueue.test.ts b/sdk/nodejs/__tests__/eventQueue.test.ts index 1860e462a..15d353604 100644 --- a/sdk/nodejs/__tests__/eventQueue.test.ts +++ b/sdk/nodejs/__tests__/eventQueue.test.ts @@ -1,13 +1,11 @@ +import { Exports } from '@devcycle/bucketing-assembly-script' + jest.mock('../src/request') import { EventQueue, EventQueueOptions } from '../src/eventQueue' import { EventTypes } from '../src/eventQueue' import { BucketedUserConfig, DVCReporter, PublicProject } from '@devcycle/types' import { mocked } from 'jest-mock' -import { - cleanupBucketingLib, - getBucketingLib, - importBucketingLib, -} from '../src/bucketing' +import { importBucketingLib } from '../src/bucketing' import { setPlatformDataJSON } from './utils/setPlatformData' import { Response } from 'cross-fetch' import { dvcDefaultLogger } from '@devcycle/js-cloud-server-sdk' @@ -21,6 +19,7 @@ const publishEvents_mock = mocked(publishEvents) const defaultLogger = dvcDefaultLogger() describe('EventQueue Unit Tests', () => { + let bucketing: Exports const bucketedUserConfig: BucketedUserConfig = { environment: { _id: '', key: '' }, features: {}, @@ -70,27 +69,23 @@ describe('EventQueue Unit Tests', () => { clientUUID: string, optionsOverrides?: Partial, ): EventQueue => { - getBucketingLib().setConfigData(sdkKey, JSON.stringify(config)) + bucketing.setConfigData(sdkKey, JSON.stringify(config)) currentEventKey = sdkKey const options = { logger: defaultLogger, ...optionsOverrides, } - return new EventQueue(sdkKey, clientUUID, options) + return new EventQueue(sdkKey, clientUUID, bucketing, options) } beforeAll(async () => { - await importBucketingLib() - setPlatformDataJSON() - }) - - afterAll(() => { - cleanupBucketingLib() + ;[bucketing] = await importBucketingLib() + setPlatformDataJSON(bucketing) }) afterEach(() => { publishEvents_mock.mockReset() - getBucketingLib().cleanupEventQueue(currentEventKey) + bucketing.cleanupEventQueue(currentEventKey) }) it('should report metrics', async () => { @@ -853,12 +848,12 @@ describe('EventQueue Unit Tests', () => { for (let i = 0; i < 500; i++) { eventQueue.queueEvent(user, { type: 'test_event' }) } - expect(getBucketingLib().eventQueueSize(sdkKey)).toEqual(1000) + expect(bucketing.eventQueueSize(sdkKey)).toEqual(1000) for (let i = 0; i < 1000; i++) { eventQueue.queueEvent(user, { type: 'test_event' }) } - expect(getBucketingLib().eventQueueSize(sdkKey)).toEqual(2000) + expect(bucketing.eventQueueSize(sdkKey)).toEqual(2000) eventQueue.queueEvent(user, { type: 'test_event2' }) @@ -868,7 +863,7 @@ describe('EventQueue Unit Tests', () => { 'Max event queue size reached, dropping event', ), ) - expect(getBucketingLib().eventQueueSize(sdkKey)).toEqual(2000) + expect(bucketing.eventQueueSize(sdkKey)).toEqual(2000) }, ) @@ -901,12 +896,12 @@ describe('EventQueue Unit Tests', () => { }, }) } - expect(getBucketingLib().eventQueueSize(sdkKey)).toEqual(1000) + expect(bucketing.eventQueueSize(sdkKey)).toEqual(1000) for (let i = 0; i < 1000; i++) { eventQueue.queueEvent(user, { type: 'test_event' }) } - expect(getBucketingLib().eventQueueSize(sdkKey)).toEqual(2000) + expect(bucketing.eventQueueSize(sdkKey)).toEqual(2000) eventQueue.queueAggregateEvent( user, @@ -923,7 +918,7 @@ describe('EventQueue Unit Tests', () => { 'Max event queue size reached, dropping aggregate event', ), ) - expect(getBucketingLib().eventQueueSize(sdkKey)).toEqual(2000) + expect(bucketing.eventQueueSize(sdkKey)).toEqual(2000) }, ) @@ -956,12 +951,12 @@ describe('EventQueue Unit Tests', () => { }) } expect(flushEvents_mock).toBeCalledTimes(0) - expect(getBucketingLib().eventQueueSize(sdkKey)).toEqual(1000) + expect(bucketing.eventQueueSize(sdkKey)).toEqual(1000) // since max event queue size has been reached, attempting to add a new user event will flush the queue eventQueue.queueEvent(user, { type: 'test_event' }) expect(flushEvents_mock).toBeCalledTimes(1) - expect(getBucketingLib().eventQueueSize(sdkKey)).toEqual(1001) + expect(bucketing.eventQueueSize(sdkKey)).toEqual(1001) }, ) @@ -995,7 +990,7 @@ describe('EventQueue Unit Tests', () => { }) } expect(flushEvents_mock).toBeCalledTimes(0) - expect(getBucketingLib().eventQueueSize(sdkKey)).toEqual(1000) + expect(bucketing.eventQueueSize(sdkKey)).toEqual(1000) // since max event queue size has been reached, attempting to add a new agg event will flush the queue eventQueue.queueAggregateEvent( @@ -1012,7 +1007,7 @@ describe('EventQueue Unit Tests', () => { }, ) expect(flushEvents_mock).toBeCalledTimes(1) - expect(getBucketingLib().eventQueueSize(sdkKey)).toEqual(1001) + expect(bucketing.eventQueueSize(sdkKey)).toEqual(1001) }, ) }) @@ -1021,14 +1016,14 @@ describe('EventQueue Unit Tests', () => { it('should validate flushEventsMS', () => { expect( () => - new EventQueue('test', 'uuid', { + new EventQueue('test', 'uuid', bucketing, { logger: defaultLogger, eventFlushIntervalMS: 400, }), ).toThrow('eventFlushIntervalMS: 400 must be larger than 500ms') expect( () => - new EventQueue('test', 'uuid', { + new EventQueue('test', 'uuid', bucketing, { logger: defaultLogger, eventFlushIntervalMS: 10 * 60 * 1000, }), @@ -1042,7 +1037,7 @@ describe('EventQueue Unit Tests', () => { it('should validate flushEventQueueSize and maxEventQueueSize', () => { expect( () => - new EventQueue('test', 'uuid', { + new EventQueue('test', 'uuid', bucketing, { logger: defaultLogger, flushEventQueueSize: 2000, maxEventQueueSize: 2000, @@ -1053,7 +1048,7 @@ describe('EventQueue Unit Tests', () => { expect( () => - new EventQueue('test', 'uuid', { + new EventQueue('test', 'uuid', bucketing, { logger: defaultLogger, flushEventQueueSize: 1000, maxEventQueueSize: 2000, @@ -1066,7 +1061,7 @@ describe('EventQueue Unit Tests', () => { expect( () => - new EventQueue('test', 'uuid', { + new EventQueue('test', 'uuid', bucketing, { logger: defaultLogger, flushEventQueueSize: 25000, maxEventQueueSize: 40000, diff --git a/sdk/nodejs/__tests__/utils/setPlatformData.ts b/sdk/nodejs/__tests__/utils/setPlatformData.ts index 0581daa49..8b3faaab3 100644 --- a/sdk/nodejs/__tests__/utils/setPlatformData.ts +++ b/sdk/nodejs/__tests__/utils/setPlatformData.ts @@ -1,4 +1,4 @@ -import { getBucketingLib } from '../../src/bucketing' +import { Exports } from '@devcycle/bucketing-assembly-script' const defaultPlatformData = { platform: 'NodeJS', @@ -10,7 +10,8 @@ const defaultPlatformData = { } export const setPlatformDataJSON = ( + bucketing: Exports, data: unknown = defaultPlatformData, ): void => { - getBucketingLib().setPlatformData(JSON.stringify(data)) + bucketing.setPlatformData(JSON.stringify(data)) } diff --git a/sdk/nodejs/src/__mocks__/bucketing.ts b/sdk/nodejs/src/__mocks__/bucketing.ts index 836d74683..ef1a5ff46 100644 --- a/sdk/nodejs/src/__mocks__/bucketing.ts +++ b/sdk/nodejs/src/__mocks__/bucketing.ts @@ -1,6 +1,4 @@ -import { ProtobufTypes } from '@devcycle/bucketing-assembly-script' - -let Bucketing: unknown +import { Exports, ProtobufTypes } from '@devcycle/bucketing-assembly-script' const testVariable = { _id: 'test-id', @@ -25,31 +23,23 @@ enum VariableType { JSON, } -export const importBucketingLib = async (): Promise => { - Bucketing = await new Promise((resolve) => - resolve({ - setConfigData: jest.fn(), - setConfigDataUTF8: jest.fn(), - setPlatformData: jest.fn(), - generateBucketedConfigForUser: jest.fn().mockReturnValue( - JSON.stringify({ - variables: { 'test-key': testVariable }, - }), - ), - variableForUser: jest - .fn() - .mockReturnValue(JSON.stringify(testVariable)), - variableForUser_PB: jest.fn().mockReturnValue(buffer), - VariableType, - initEventQueue: jest.fn(), - flushEventQueue: jest.fn(), - }), - ) -} - -export const getBucketingLib = (): unknown => { - if (!Bucketing) { - throw new Error('Bucketing library not loaded') - } - return Bucketing +export const importBucketingLib = async (): Promise<[Exports, undefined]> => { + const bucketing = await Promise.resolve({ + setConfigData: jest.fn(), + setConfigDataUTF8: jest.fn(), + setPlatformData: jest.fn(), + generateBucketedConfigForUser: jest.fn().mockReturnValue( + JSON.stringify({ + variables: { 'test-key': testVariable }, + }), + ), + variableForUser: jest + .fn() + .mockReturnValue(JSON.stringify(testVariable)), + variableForUser_PB: jest.fn().mockReturnValue(buffer), + VariableType, + initEventQueue: jest.fn(), + flushEventQueue: jest.fn(), + }) + return [bucketing as unknown as Exports, undefined] } diff --git a/sdk/nodejs/src/bucketing.ts b/sdk/nodejs/src/bucketing.ts index e9495e0f6..555161d4f 100644 --- a/sdk/nodejs/src/bucketing.ts +++ b/sdk/nodejs/src/bucketing.ts @@ -5,67 +5,49 @@ import { DevCycleServerSDKOptions, } from '@devcycle/types' -let Bucketing: Exports | null -let InstantiatePromise: Promise | null - export const importBucketingLib = async ({ logger, options, }: { logger?: DVCLogger options?: DevCycleServerSDKOptions -} = {}): Promise => { - if (InstantiatePromise) { - await InstantiatePromise - return - } +} = {}): Promise<[Exports, NodeJS.Timer | undefined]> => { const debugWASM = process.env.DEVCYCLE_DEBUG_WASM === '1' - InstantiatePromise = instantiate(debugWASM).then((exports) => { - Bucketing = exports - return Bucketing - }) - await InstantiatePromise - startTrackingMemoryUsage(logger, options?.reporter) + const result = await instantiate(debugWASM) + const interval = startTrackingMemoryUsage(result, logger, options?.reporter) + return [result, interval] } export const startTrackingMemoryUsage = ( + bucketing: Exports, logger?: DVCLogger, reporter?: DVCReporter, interval: number = 30 * 1000, -): void => { +): NodeJS.Timer | undefined => { if (!reporter) return - trackMemoryUsage(reporter, logger) - setInterval(() => trackMemoryUsage(reporter, logger), interval) + trackMemoryUsage(bucketing, reporter, logger) + return setInterval( + () => trackMemoryUsage(bucketing, reporter, logger), + interval, + ) } export const trackMemoryUsage = ( + bucketing: Exports, reporter: DVCReporter, logger?: DVCLogger, ): void => { if (!reporter) return - if (!Bucketing) { - throw new Error('Bucketing lib not initialized') - } - const memoryUsageMB = Bucketing.memory.buffer.byteLength / 1e6 + const memoryUsageMB = bucketing.memory.buffer.byteLength / 1e6 logger?.debug(`WASM memory usage: ${memoryUsageMB} MB`) reporter.reportMetric('wasmMemoryMB', memoryUsageMB, {}) } -export const getBucketingLib = (): Exports => { - if (!Bucketing) { - throw new Error('Bucketing library not loaded') - } - return Bucketing -} - -export const cleanupBucketingLib = (): void => { - Bucketing = null -} - export const setConfigDataUTF8 = ( + bucketing: Exports, sdkKey: string, projectConfigStr: string, ): void => { const configBuffer = Buffer.from(projectConfigStr, 'utf8') - getBucketingLib().setConfigDataUTF8(sdkKey, configBuffer) + bucketing.setConfigDataUTF8(sdkKey, configBuffer) } diff --git a/sdk/nodejs/src/client.ts b/sdk/nodejs/src/client.ts index 02a26a854..81069fcdc 100644 --- a/sdk/nodejs/src/client.ts +++ b/sdk/nodejs/src/client.ts @@ -8,11 +8,7 @@ import { } from './utils/userBucketingHelper' import { EventQueue, EventTypes } from './eventQueue' import * as packageJson from '../package.json' -import { - importBucketingLib, - getBucketingLib, - setConfigDataUTF8, -} from './bucketing' +import { importBucketingLib, setConfigDataUTF8 } from './bucketing' import { BucketedUserConfig, DevCycleServerSDKOptions, @@ -34,6 +30,7 @@ import { } from '@devcycle/js-cloud-server-sdk' import { DVCPopulatedUserFromDevCycleUser } from './models/populatedUserHelpers' import { randomUUID } from 'crypto' +import { Exports } from '@devcycle/bucketing-assembly-script' interface IPlatformData { platform: string @@ -66,6 +63,8 @@ export class DevCycleClient { private logger: DVCLogger private _isInitialized = false private openFeatureProvider: DevCycleProvider + private bucketing: Exports + private bucketingTracker?: NodeJS.Timer get isInitialized(): boolean { return this._isInitialized @@ -85,9 +84,8 @@ export class DevCycleClient { ) } - const initializePromise = importBucketingLib({ + const initializePromise = this.initializeBucketing({ options, - logger: this.logger, }) .catch((bucketingErr) => { throw new UserError(bucketingErr) @@ -96,7 +94,12 @@ export class DevCycleClient { this.configHelper = new EnvironmentConfigManager( this.logger, sdkKey, - setConfigDataUTF8, + (sdkKey: string, projectConfig: string) => + setConfigDataUTF8( + this.bucketing, + sdkKey, + projectConfig, + ), setInterval, clearInterval, this.trackSDKConfigEvent.bind(this), @@ -106,7 +109,12 @@ export class DevCycleClient { this.clientConfigHelper = new EnvironmentConfigManager( this.logger, sdkKey, - setConfigDataUTF8, + (sdkKey: string, projectConfig: string) => + setConfigDataUTF8( + this.bucketing, + sdkKey, + projectConfig, + ), setInterval, clearInterval, this.trackSDKConfigEvent.bind(this), @@ -114,10 +122,15 @@ export class DevCycleClient { ) } - this.eventQueue = new EventQueue(sdkKey, this.clientUUID, { - ...options, - logger: this.logger, - }) + this.eventQueue = new EventQueue( + sdkKey, + this.clientUUID, + this.bucketing, + { + ...options, + logger: this.logger, + }, + ) const platformData: IPlatformData = { platform: 'NodeJS', @@ -127,7 +140,7 @@ export class DevCycleClient { hostname: this.hostname, } - getBucketingLib().setPlatformData(JSON.stringify(platformData)) + this.bucketing.setPlatformData(JSON.stringify(platformData)) return Promise.all([ this.configHelper.fetchConfigPromise, @@ -156,6 +169,17 @@ export class DevCycleClient { }) } + async initializeBucketing({ + options, + }: { + options?: DevCycleServerSDKOptions + }): Promise { + ;[this.bucketing, this.bucketingTracker] = await importBucketingLib({ + options, + logger: this.logger, + }) + } + async getOpenFeatureProvider(): Promise { let DevCycleProviderClass @@ -229,10 +253,11 @@ export class DevCycleClient { } const configVariable = variableForUser_PB( + this.bucketing, this.sdkKey, populatedUser, key, - getVariableTypeCode(type), + getVariableTypeCode(this.bucketing, type), ) const options: VariableParam = { @@ -273,7 +298,11 @@ export class DevCycleClient { } const populatedUser = DVCPopulatedUserFromDevCycleUser(incomingUser) - const bucketedConfig = bucketUserForConfig(populatedUser, this.sdkKey) + const bucketedConfig = bucketUserForConfig( + this.bucketing, + populatedUser, + this.sdkKey, + ) return bucketedConfig?.variables || {} } @@ -288,7 +317,11 @@ export class DevCycleClient { } const populatedUser = DVCPopulatedUserFromDevCycleUser(incomingUser) - const bucketedConfig = bucketUserForConfig(populatedUser, this.sdkKey) + const bucketedConfig = bucketUserForConfig( + this.bucketing, + populatedUser, + this.sdkKey, + ) return bucketedConfig?.features || {} } @@ -359,7 +392,10 @@ export class DevCycleClient { ) } - const clientSDKKey = getSDKKeyFromConfig(`${this.sdkKey}_client`) + const clientSDKKey = getSDKKeyFromConfig( + this.bucketing, + `${this.sdkKey}_client`, + ) if (!clientSDKKey) { throw new Error( @@ -376,7 +412,11 @@ export class DevCycleClient { userAgent, ) return { - ...bucketUserForConfig(populatedUser, `${this.sdkKey}_client`), + ...bucketUserForConfig( + this.bucketing, + populatedUser, + `${this.sdkKey}_client`, + ), clientSDKKey, } } catch (e) { @@ -397,5 +437,6 @@ export class DevCycleClient { await this.flushEvents() this.configHelper.cleanup() this.eventQueue.cleanup() + clearInterval(this.bucketingTracker) } } diff --git a/sdk/nodejs/src/eventQueue.ts b/sdk/nodejs/src/eventQueue.ts index fb4fcb5ab..47e919b5a 100644 --- a/sdk/nodejs/src/eventQueue.ts +++ b/sdk/nodejs/src/eventQueue.ts @@ -5,9 +5,9 @@ import { DVCReporter, FlushResults, } from '@devcycle/types' -import { getBucketingLib } from './bucketing' import { publishEvents } from './request' import { DevCycleEvent, DVCPopulatedUser } from '@devcycle/js-cloud-server-sdk' +import { Exports } from '@devcycle/bucketing-assembly-script' export const AggregateEventTypes: Record = { variableEvaluated: 'variableEvaluated', @@ -56,6 +56,7 @@ export class EventQueue { constructor( private readonly sdkKey: string, private readonly clientUUID: string, + private readonly bucketing: Exports, options: EventQueueOptions, ) { this.logger = options.logger @@ -105,7 +106,7 @@ export class EventQueue { this.eventFlushIntervalMS, ) - getBucketingLib().initEventQueue( + this.bucketing.initEventQueue( sdkKey, this.clientUUID, JSON.stringify(options), @@ -123,13 +124,13 @@ export class EventQueue { } this.reporter?.reportMetric( 'queueLength', - getBucketingLib().eventQueueSize(this.sdkKey), + this.bucketing.eventQueueSize(this.sdkKey), metricTags, ) let flushPayloadsStr try { - flushPayloadsStr = getBucketingLib().flushEventQueue(this.sdkKey) + flushPayloadsStr = this.bucketing.flushEventQueue(this.sdkKey) this.reporter?.reportMetric( 'flushPayloadSize', flushPayloadsStr?.length, @@ -185,14 +186,14 @@ export class EventQueue { ) if (res.status >= 500) { results.retries++ - getBucketingLib().onPayloadFailure( + this.bucketing.onPayloadFailure( this.sdkKey, flushPayload.payloadId, true, ) } else { results.failures++ - getBucketingLib().onPayloadFailure( + this.bucketing.onPayloadFailure( this.sdkKey, flushPayload.payloadId, false, @@ -202,7 +203,7 @@ export class EventQueue { this.logger.debug( `DevCycle Flushed ${eventCount} Events, for ${flushPayload.records.length} Users`, ) - getBucketingLib().onPayloadSuccess( + this.bucketing.onPayloadSuccess( this.sdkKey, flushPayload.payloadId, ) @@ -212,7 +213,7 @@ export class EventQueue { this.logger.debug( `DevCycle Error Flushing Events response message: ${ex.message}`, ) - getBucketingLib().onPayloadFailure( + this.bucketing.onPayloadFailure( this.sdkKey, flushPayload.payloadId, true, @@ -276,7 +277,7 @@ export class EventQueue { return } - getBucketingLib().queueEvent( + this.bucketing.queueEvent( this.sdkKey, JSON.stringify(user), JSON.stringify(event), @@ -299,7 +300,7 @@ export class EventQueue { return } - getBucketingLib().queueAggregateEvent( + this.bucketing.queueAggregateEvent( this.sdkKey, JSON.stringify(event), JSON.stringify(bucketedConfig?.variableVariationMap || {}), @@ -307,7 +308,7 @@ export class EventQueue { } private checkEventQueueSize(): boolean { - const queueSize = getBucketingLib().eventQueueSize(this.sdkKey) + const queueSize = this.bucketing.eventQueueSize(this.sdkKey) if (queueSize >= this.flushEventQueueSize) { this.flushEvents() if (queueSize >= this.maxEventQueueSize) { diff --git a/sdk/nodejs/src/utils/userBucketingHelper.ts b/sdk/nodejs/src/utils/userBucketingHelper.ts index 820ae85bf..581b6dc3b 100644 --- a/sdk/nodejs/src/utils/userBucketingHelper.ts +++ b/sdk/nodejs/src/utils/userBucketingHelper.ts @@ -1,52 +1,56 @@ import { BucketedUserConfig, SDKVariable, VariableType } from '@devcycle/types' import { DVCPopulatedUser } from '@devcycle/js-cloud-server-sdk' -import { getBucketingLib } from '../bucketing' import { VariableForUserParams_PB, SDKVariable_PB, } from '@devcycle/bucketing-assembly-script/protobuf/compiled' import { pbSDKVariableTransform } from '../pb-types/pbTypeHelpers' import { DVCPopulatedUserToPBUser } from '../models/populatedUserHelpers' +import { Exports } from '@devcycle/bucketing-assembly-script' export function bucketUserForConfig( + bucketing: Exports, user: DVCPopulatedUser, sdkKey: string, ): BucketedUserConfig { return JSON.parse( - getBucketingLib().generateBucketedConfigForUser( - sdkKey, - JSON.stringify(user), - ), + bucketing.generateBucketedConfigForUser(sdkKey, JSON.stringify(user)), ) as BucketedUserConfig } -export function getSDKKeyFromConfig(sdkKey: string): string | null { - return getBucketingLib().getSDKKeyFromConfig(sdkKey) +export function getSDKKeyFromConfig( + bucketing: Exports, + sdkKey: string, +): string | null { + return bucketing.getSDKKeyFromConfig(sdkKey) } -export function getVariableTypeCode(type: VariableType): number { - const Bucketing = getBucketingLib() +export function getVariableTypeCode( + bucketing: Exports, + type: VariableType, +): number { switch (type) { case VariableType.boolean: - return Bucketing.VariableType.Boolean + return bucketing.VariableType.Boolean case VariableType.number: - return Bucketing.VariableType.Number + return bucketing.VariableType.Number case VariableType.string: - return Bucketing.VariableType.String + return bucketing.VariableType.String case VariableType.json: - return Bucketing.VariableType.JSON + return bucketing.VariableType.JSON default: throw new Error(`Unknown variable type: ${type}`) } } export function variableForUser( + bucketing: Exports, sdkKey: string, user: DVCPopulatedUser, key: string, type: number, ): SDKVariable | null { - const bucketedVariable = getBucketingLib().variableForUser( + const bucketedVariable = bucketing.variableForUser( sdkKey, JSON.stringify(user), key, @@ -58,6 +62,7 @@ export function variableForUser( } export function variableForUser_PB( + bucketing: Exports, sdkKey: string, user: DVCPopulatedUser, key: string, @@ -78,7 +83,7 @@ export function variableForUser_PB( const buffer = VariableForUserParams_PB.encode(params).finish() - const bucketedVariable = getBucketingLib().variableForUser_PB(buffer) + const bucketedVariable = bucketing.variableForUser_PB(buffer) if (!bucketedVariable) return null return pbSDKVariableTransform(SDKVariable_PB.decode(bucketedVariable)) }