Skip to content

Commit 7c5ba98

Browse files
NONE: add launchdarkly feature flagging support (#258)
* Add launchdarkly client * update eslint plugin * minor fixes
1 parent 4d35197 commit 7c5ba98

4 files changed

Lines changed: 266 additions & 7 deletions

File tree

package-lock.json

Lines changed: 176 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"core-js": "^3.36.0",
4141
"dd-trace": "^4.17.0",
4242
"express": "^4.18.2",
43+
"launchdarkly-node-server-sdk": "^7.0.4",
4344
"pino": "^8.15.0",
4445
"pino-http": "^8.4.0",
4546
"prisma": "^5.1.1",
@@ -55,7 +56,7 @@
5556
"@types/supertest": "^2.0.12",
5657
"@types/uuid": "^9.0.2",
5758
"@typescript-eslint/eslint-plugin": "^6.4.0",
58-
"@typescript-eslint/parser": "^6.4.0",
59+
"@typescript-eslint/parser": "^6.21.0",
5960
"commander": "^11.1.0",
6061
"dotenv": "^16.3.1",
6162
"dotenv-cli": "^7.3.0",

src/config/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export type Config = {
2020
readonly domain: string;
2121
readonly webBaseUrl: URL;
2222
readonly apiBaseUrl: URL;
23+
readonly clusterName: string;
2324
readonly oauth2: {
2425
readonly authorizationServerBaseUrl: URL;
2526
readonly clientId: string;
@@ -57,6 +58,7 @@ export const getConfig = (): Config => {
5758
domain: readEnvVarString('FIGMA_DOMAIN', 'figma.com'),
5859
webBaseUrl: new URL(readEnvVarString('FIGMA_WEB_BASE_URL')),
5960
apiBaseUrl: new URL(readEnvVarString('FIGMA_API_BASE_URL')),
61+
clusterName: readEnvVarString('CLUSTER_NAME', 'unknown'),
6062
oauth2: {
6163
authorizationServerBaseUrl: new URL(
6264
readEnvVarString('FIGMA_OAUTH2_AUTHORIZATION_SERVER_BASE_URL'),

src/config/launch_darkly.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import type { LDClient, LDOptions } from 'launchdarkly-node-server-sdk';
2+
import { init } from 'launchdarkly-node-server-sdk';
3+
4+
import { getLogger } from '../infrastructure';
5+
6+
import { getConfig } from '.';
7+
8+
export async function getLDClient(): Promise<LDClient | null> {
9+
const ldSecretKey = getLaunchDarklySecretKey();
10+
11+
if (!ldSecretKey) {
12+
getLogger().error(`No LaunchDarkly secret available.`);
13+
return null;
14+
}
15+
16+
const options: LDOptions = {
17+
logger: {
18+
error: (message) => getLogger().error(message),
19+
warn: (message) => getLogger().warn(message),
20+
info: () => {},
21+
debug: () => {},
22+
},
23+
};
24+
const client = init(ldSecretKey, options);
25+
await client.waitForInitialization();
26+
return client;
27+
}
28+
29+
export async function getFeatureFlag<T>(
30+
client: LDClient | null,
31+
flag: string,
32+
defaultValue: T,
33+
): Promise<T> {
34+
if (!client) {
35+
getLogger().error(
36+
`No LaunchDarkly client provided, using default value for flag ${flag}: ${JSON.stringify(
37+
defaultValue,
38+
)}`,
39+
);
40+
return defaultValue;
41+
}
42+
43+
const featureFlag = (await client.variation(
44+
flag,
45+
{ key: 'figma-for-jira' },
46+
defaultValue,
47+
)) as T;
48+
return featureFlag;
49+
}
50+
51+
function getLaunchDarklySecretKey(): string | undefined {
52+
const env = getConfig().figma.clusterName;
53+
54+
let secretKey: string | undefined = undefined;
55+
56+
switch (env) {
57+
case 'gov':
58+
case 'production':
59+
case 'staging':
60+
secretKey = process.env['LAUNCH_DARKLY_SECRET_KEY'];
61+
break;
62+
63+
default: {
64+
const rawMap = process.env['LAUNCH_DARKLY_SECRET_KEY_MAP'];
65+
if (!rawMap) {
66+
secretKey = undefined;
67+
} else {
68+
const map = JSON.parse(rawMap) as unknown;
69+
if (map && typeof map === 'object' && env in map) {
70+
const value = map[env] as unknown;
71+
if (typeof value === 'string') {
72+
secretKey = value;
73+
}
74+
}
75+
}
76+
}
77+
}
78+
79+
if (secretKey === undefined) {
80+
getLogger().error('LaunchDarkly secret is undefined');
81+
} else {
82+
getLogger().info('LaunchDarkly secret is defined');
83+
}
84+
85+
return secretKey;
86+
}

0 commit comments

Comments
 (0)