Skip to content

Commit

Permalink
feat: enable generated variable types for nodejs sdk (#901)
Browse files Browse the repository at this point in the history
  • Loading branch information
elliotCamblor authored Jul 24, 2024
1 parent 3b72abf commit 252d311
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 30 deletions.
25 changes: 17 additions & 8 deletions sdk/js-cloud-server/src/cloudClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
DVCLogger,
getVariableTypeFromValue,
VariableTypeAlias,
type VariableValue,
} from '@devcycle/types'
import {
getAllFeatures,
Expand Down Expand Up @@ -67,7 +68,13 @@ const throwIfUserError = (err: unknown) => {
throw err
}

export class DevCycleCloudClient {
export interface VariableDefinitions {
[key: string]: VariableValue
}

export class DevCycleCloudClient<
Variables extends VariableDefinitions = VariableDefinitions,
> {
private sdkKey: string
protected logger: DVCLogger
private options: DevCycleServerSDKOptions
Expand All @@ -94,11 +101,10 @@ export class DevCycleCloudClient {
return true
}

async variable<T extends DVCVariableValue>(
user: DevCycleUser,
key: string,
defaultValue: T,
): Promise<DVCVariable<T>> {
async variable<
K extends string & keyof Variables,
T extends DVCVariableValue & Variables[K],
>(user: DevCycleUser, key: K, defaultValue: T): Promise<DVCVariable<T>> {
const incomingUser = castIncomingUser(user)
const populatedUser = DVCPopulatedUser.fromDVCUser(
incomingUser,
Expand Down Expand Up @@ -148,9 +154,12 @@ export class DevCycleCloudClient {
}
}

async variableValue<T extends DVCVariableValue>(
async variableValue<
K extends string & keyof Variables,
T extends DVCVariableValue & Variables[K],
>(
user: DevCycleUser,
key: string,
key: K,
defaultValue: T,
): Promise<VariableTypeAlias<T>> {
return (await this.variable(user, key, defaultValue)).value
Expand Down
1 change: 1 addition & 0 deletions sdk/js/src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
DVCFeature,
VariableDefinitions,
} from './types'

import { DVCVariable, DVCVariableOptions } from './Variable'
import { getConfigJson, saveEntity } from './Request'
import CacheStore from './CacheStore'
Expand Down
31 changes: 18 additions & 13 deletions sdk/nodejs/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
DVCLogger,
getVariableTypeFromValue,
VariableTypeAlias,
type VariableValue,
} from '@devcycle/types'
import os from 'os'
import {
Expand Down Expand Up @@ -54,14 +55,20 @@ type DevCycleProviderConstructor =
typeof import('./open-feature/DevCycleProvider').DevCycleProvider
type DevCycleProvider = InstanceType<DevCycleProviderConstructor>

export class DevCycleClient {
export interface VariableDefinitions {
[key: string]: VariableValue
}

export class DevCycleClient<
Variables extends VariableDefinitions = VariableDefinitions,
> {
private clientUUID: string
private hostname: string
private sdkKey: string
private configHelper?: EnvironmentConfigManager
private clientConfigHelper?: EnvironmentConfigManager
private eventQueue: EventQueue
private onInitialized: Promise<DevCycleClient>
private onInitialized: Promise<DevCycleClient<Variables>>
private logger: DVCLogger
private _isInitialized = false
private openFeatureProvider: DevCycleProvider
Expand Down Expand Up @@ -212,7 +219,7 @@ export class DevCycleClient {
*/
async onClientInitialized(
onInitialized?: (err?: Error) => void,
): Promise<DevCycleClient> {
): Promise<DevCycleClient<Variables>> {
if (onInitialized && typeof onInitialized === 'function') {
this.onInitialized
.then(() => onInitialized())
Expand All @@ -221,11 +228,10 @@ export class DevCycleClient {
return this.onInitialized
}

variable<T extends DVCVariableValue>(
user: DevCycleUser,
key: string,
defaultValue: T,
): DVCVariable<T> {
variable<
K extends string & keyof Variables,
T extends DVCVariableValue & Variables[K],
>(user: DevCycleUser, key: K, defaultValue: T): DVCVariable<T> {
const incomingUser = castIncomingUser(user)
// this will throw if type is invalid
const type = getVariableTypeFromValue(
Expand Down Expand Up @@ -280,11 +286,10 @@ export class DevCycleClient {
return new DVCVariable(options)
}

variableValue<T extends DVCVariableValue>(
user: DevCycleUser,
key: string,
defaultValue: T,
): VariableTypeAlias<T> {
variableValue<
K extends string & keyof Variables,
T extends DVCVariableValue & Variables[K],
>(user: DevCycleUser, key: K, defaultValue: T): VariableTypeAlias<T> {
return this.variable(user, key, defaultValue).value
}

Expand Down
29 changes: 20 additions & 9 deletions sdk/nodejs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
DVCFeatureSet,
DevCyclePlatformDetails,
} from '@devcycle/js-cloud-server-sdk'
import { VariableDefinitions } from '@devcycle/js-client-sdk'
import { DevCycleServerSDKOptions } from '@devcycle/types'
import { getNodeJSPlatformDetails } from './utils/platformDetails'

Expand All @@ -24,7 +25,9 @@ type DevCycleProviderConstructor =
typeof import('./open-feature/DevCycleProvider').DevCycleProvider
type DevCycleProvider = InstanceType<DevCycleProviderConstructor>

class DevCycleCloudClient extends InternalDevCycleCloudClient {
class DevCycleCloudClient<
Variables extends VariableDefinitions = VariableDefinitions,
> extends InternalDevCycleCloudClient {
private openFeatureProvider: DevCycleProvider

constructor(
Expand Down Expand Up @@ -117,22 +120,30 @@ export type DevCycleOptionsLocalEnabled = DevCycleServerSDKOptions & {
configSource?: ConfigSource
}

export function initializeDevCycle(
export function initializeDevCycle<
Variables extends VariableDefinitions = VariableDefinitions,
>(
sdkKey: string,
options?: DevCycleOptionsLocalEnabled,
): DevCycleClient
export function initializeDevCycle(
): DevCycleClient<Variables>
export function initializeDevCycle<
Variables extends VariableDefinitions = VariableDefinitions,
>(
sdkKey: string,
options: DevCycleOptionsCloudEnabled,
): DevCycleCloudClient
export function initializeDevCycle(
): DevCycleCloudClient<Variables>
export function initializeDevCycle<
Variables extends VariableDefinitions = VariableDefinitions,
>(
sdkKey: string,
options?: DevCycleServerSDKOptions,
): DevCycleClient | DevCycleCloudClient
export function initializeDevCycle(
): DevCycleClient<Variables> | DevCycleCloudClient<Variables>
export function initializeDevCycle<
Variables extends VariableDefinitions = VariableDefinitions,
>(
sdkKey: string,
options: DevCycleServerSDKOptions = {},
): DevCycleClient | DevCycleCloudClient {
): DevCycleClient<Variables> | DevCycleCloudClient<Variables> {
if (!sdkKey) {
throw new Error('Missing SDK key! Call initialize with a valid SDK key')
} else if (!isValidServerSDKKey(sdkKey)) {
Expand Down

0 comments on commit 252d311

Please sign in to comment.