accept consoleApiKey from getProviderData (#77)

This commit is contained in:
Dominik Ferber
2025-02-27 17:44:01 +02:00
committed by GitHub
parent f6cb1ef244
commit 9a687cba09
3 changed files with 159 additions and 114 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@flags-sdk/statsig': patch
---
accept consoleApiKey from getProviderData
@@ -195,106 +195,119 @@ beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
afterAll(() => server.close());
afterEach(() => server.resetHandlers());
const responseFixture = {
hints: [],
definitions: {
show_high_definition_images: {
options: [
{ label: 'Off', value: false },
{ label: 'On', value: true },
],
description: 'Show high definition product images',
origin:
'https://console.statsig.com/project-id-placeholder/gates/show_high_definition_images',
createdAt: 1708981092158,
updatedAt: 1708981874677,
},
show_new_product_details: {
options: [
{ label: 'Off', value: false },
{ label: 'On', value: true },
],
description: 'Shows the new product details.',
origin:
'https://console.statsig.com/project-id-placeholder/gates/show_new_product_details',
createdAt: 1708975725889,
updatedAt: 1708975899169,
},
classroom: {
description: '',
origin:
'https://console.statsig.com/project-id-placeholder/experiments/classroom/setup',
options: [
{
label: 'Class D',
value: {
idealism: 75,
fitness: 'weak',
skilful: false,
proficiency: {
math: 10,
literature: 10,
sport: 10,
},
standouts: [],
},
},
{
label: 'Class C',
value: {
idealism: 40,
fitness: 'lazy',
skilful: false,
proficiency: {
math: 30,
literature: 30,
sport: 40,
},
standouts: ['Craftsmanship', 'Basketball'],
},
},
{
label: 'Class B',
value: {
idealism: 20,
fitness: 'fit',
skilful: true,
proficiency: {
math: 60,
literature: 70,
sport: 80,
},
standouts: ['Chess', 'Aikido'],
},
},
{
label: 'Class A',
value: {
idealism: 0,
fitness: 'strong',
skilful: true,
proficiency: {
math: 100,
literature: 100,
sport: 100,
},
standouts: ['Martial Arts', 'Poetry', 'Politics'],
},
},
],
createdAt: 1707427634717,
updatedAt: 1707427635442,
},
},
} as const;
describe('getProviderData', () => {
describe('when called with valid params', () => {
it('should fetch and return', async () => {
await expect(
getProviderData({
consoleApiKey: 'console-this-is-a-test-token',
projectId: 'project-id-placeholder',
}),
).resolves.toEqual(responseFixture);
});
});
describe('when called with deprecated valid params', () => {
it('should fetch and return', async () => {
await expect(
getProviderData({
statsigConsoleApiKey: 'console-this-is-a-test-token',
projectId: 'project-id-placeholder',
}),
).resolves.toEqual({
hints: [],
definitions: {
show_high_definition_images: {
options: [
{ label: 'Off', value: false },
{ label: 'On', value: true },
],
description: 'Show high definition product images',
origin:
'https://console.statsig.com/project-id-placeholder/gates/show_high_definition_images',
createdAt: 1708981092158,
updatedAt: 1708981874677,
},
show_new_product_details: {
options: [
{ label: 'Off', value: false },
{ label: 'On', value: true },
],
description: 'Shows the new product details.',
origin:
'https://console.statsig.com/project-id-placeholder/gates/show_new_product_details',
createdAt: 1708975725889,
updatedAt: 1708975899169,
},
classroom: {
description: '',
origin:
'https://console.statsig.com/project-id-placeholder/experiments/classroom/setup',
options: [
{
label: 'Class D',
value: {
idealism: 75,
fitness: 'weak',
skilful: false,
proficiency: {
math: 10,
literature: 10,
sport: 10,
},
standouts: [],
},
},
{
label: 'Class C',
value: {
idealism: 40,
fitness: 'lazy',
skilful: false,
proficiency: {
math: 30,
literature: 30,
sport: 40,
},
standouts: ['Craftsmanship', 'Basketball'],
},
},
{
label: 'Class B',
value: {
idealism: 20,
fitness: 'fit',
skilful: true,
proficiency: {
math: 60,
literature: 70,
sport: 80,
},
standouts: ['Chess', 'Aikido'],
},
},
{
label: 'Class A',
value: {
idealism: 0,
fitness: 'strong',
skilful: true,
proficiency: {
math: 100,
literature: 100,
sport: 100,
},
standouts: ['Martial Arts', 'Poetry', 'Politics'],
},
},
],
createdAt: 1707427634717,
updatedAt: 1707427635442,
},
},
});
).resolves.toEqual(responseFixture);
});
});
@@ -302,7 +315,7 @@ describe('getProviderData', () => {
it('should return appropriate hints', async () => {
await expect(
getProviderData({
statsigConsoleApiKey: '',
consoleApiKey: '',
}),
).resolves.toEqual({
definitions: {},
+48 -21
View File
@@ -43,28 +43,55 @@ interface StatsigExperimentsResponse {
};
}
export async function getProviderData(options: {
statsigConsoleApiKey: string;
/**
* Required to set the `origin` property on the flag definitions.
*/
projectId?: string;
}): Promise<ProviderData> {
const hints = [];
export async function getProviderData(
options: {
/**
* Required to set the `origin` property on the flag definitions.
*/
projectId?: string;
} & (
| {
/**
* The Statsig Console API key.
*/
consoleApiKey: string;
/**
* @deprecated Use `consoleApiKey` instead.
*/
statsigConsoleApiKey?: never;
}
| {
/**
* @deprecated Use `consoleApiKey` instead.
*/
statsigConsoleApiKey: string;
/**
* The Statsig Console API key.
*/
consoleApiKey?: never;
}
),
): Promise<ProviderData> {
const consoleApiKey = options.consoleApiKey || options.statsigConsoleApiKey;
if (!options.statsigConsoleApiKey) {
hints.push({
key: 'statsig/missing-api-key',
text: 'Missing Statsig Console API Key',
});
if (!consoleApiKey) {
return {
definitions: {},
hints: [
{
key: 'statsig/missing-api-key',
text: 'Missing Statsig Console API Key',
},
],
};
}
// Abort early if called with incomplete options.
if (hints.length > 0) return { definitions: {}, hints };
const hints: ProviderData['hints'] = [];
// Abort early if called with incomplete options.
const [gates, experiments] = await Promise.allSettled([
getFeatureGates(options),
getExperiments(options),
getFeatureGates({ consoleApiKey }),
getExperiments({ consoleApiKey }),
] as const);
const definitions: ProviderData['definitions'] = {};
@@ -121,7 +148,7 @@ export async function getProviderData(options: {
/**
* Fetch all Feature Gates.
*/
async function getFeatureGates(options: { statsigConsoleApiKey: string }) {
async function getFeatureGates(options: { consoleApiKey: string }) {
const data: StatsigFeatureGateResponse['data'] = [];
let suffix: string | null = '/console/v1/gates';
@@ -131,7 +158,7 @@ async function getFeatureGates(options: { statsigConsoleApiKey: string }) {
method: 'GET',
headers: {
'content-type': 'application/json',
'STATSIG-API-KEY': options.statsigConsoleApiKey,
'STATSIG-API-KEY': options.consoleApiKey,
},
// @ts-expect-error some Next.js versions need this
cache: 'no-store',
@@ -157,7 +184,7 @@ async function getFeatureGates(options: { statsigConsoleApiKey: string }) {
/**
* Fetch all experiments.
*/
async function getExperiments(options: { statsigConsoleApiKey: string }) {
async function getExperiments(options: { consoleApiKey: string }) {
const data: StatsigExperimentsResponse['data'] = [];
let suffix: string | null = '/console/v1/experiments';
@@ -167,7 +194,7 @@ async function getExperiments(options: { statsigConsoleApiKey: string }) {
method: 'GET',
headers: {
'content-type': 'application/json',
'STATSIG-API-KEY': options.statsigConsoleApiKey,
'STATSIG-API-KEY': options.consoleApiKey,
},
// @ts-expect-error some Next.js versions need this
cache: 'no-store',