mirror of
https://github.com/vercel/flags.git
synced 2026-09-19 03:49:23 +08:00
accept consoleApiKey from getProviderData (#77)
This commit is contained in:
@@ -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: {},
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user