@flags-sdk/statsig
Version:
Statsig provider for the Flags SDK
1 lines • 8.09 kB
Source Map (JSON)
{"version":3,"sources":["../src/provider/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { JsonValue, ProviderData } from 'flags';\n\n// See: https://docs.statsig.com/console-api/gates/#get-/console/v1/gates\ninterface StatsigFeatureGateResponse {\n data: {\n id: string;\n name: string;\n description: string;\n rules: {}[];\n createdTime: number;\n lastModifiedTime: number;\n }[];\n pagination?: {\n itemsPerPage: number;\n pageNumber: number;\n totalItems: number;\n nextPage: null | string;\n previousPage: null | string;\n all: string;\n };\n}\n\n// See: https://docs.statsig.com/console-api/experiments#get-/console/v1/experiments\ninterface StatsigExperimentsResponse {\n data: {\n id: string;\n name: string;\n description: string;\n groups: {\n name: string;\n parameterValues: Record<string, JsonValue>;\n }[];\n createdTime: number;\n lastModifiedTime: number;\n }[];\n pagination?: {\n itemsPerPage: number;\n pageNumber: number;\n totalItems: number;\n nextPage: null | string;\n previousPage: null | string;\n all: string;\n };\n}\n\nexport async function getProviderData(\n options: {\n /**\n * Required to set the `origin` property on the flag definitions.\n */\n projectId?: string;\n } & (\n | {\n /**\n * The Statsig Console API key.\n */\n consoleApiKey: string;\n /**\n * @deprecated Use `consoleApiKey` instead.\n */\n statsigConsoleApiKey?: never;\n }\n | {\n /**\n * @deprecated Use `consoleApiKey` instead.\n */\n statsigConsoleApiKey: string;\n /**\n * The Statsig Console API key.\n */\n consoleApiKey?: never;\n }\n ),\n): Promise<ProviderData> {\n const consoleApiKey = options.consoleApiKey || options.statsigConsoleApiKey;\n\n if (!consoleApiKey) {\n return {\n definitions: {},\n hints: [\n {\n key: 'statsig/missing-api-key',\n text: 'Missing Statsig Console API Key',\n },\n ],\n };\n }\n\n const hints: ProviderData['hints'] = [];\n\n // Abort early if called with incomplete options.\n const [gates, experiments] = await Promise.allSettled([\n getFeatureGates({ consoleApiKey }),\n getExperiments({ consoleApiKey }),\n ] as const);\n\n const definitions: ProviderData['definitions'] = {};\n\n if (gates.status === 'fulfilled') {\n gates.value.forEach((gate) => {\n definitions[gate.id] = {\n description: gate.description,\n origin: options.projectId\n ? `https://console.statsig.com/${options.projectId}/gates/${gate.id}`\n : undefined,\n options: [\n { label: 'Off', value: false },\n { label: 'On', value: true },\n ],\n createdAt: gate.createdTime,\n updatedAt: gate.lastModifiedTime,\n };\n });\n } else {\n hints.push({\n key: 'statsig/failed-to-load-feature-gates',\n text: gates.reason.message,\n });\n }\n\n if (experiments.status === 'fulfilled') {\n experiments.value.forEach((experiment) => {\n definitions[experiment.id] = {\n description: experiment.description,\n origin: options.projectId\n ? `https://console.statsig.com/${options.projectId}/experiments/${experiment.id}/setup`\n : undefined,\n options: experiment.groups.map((group) => {\n return {\n label: group.name,\n value: group.parameterValues,\n };\n }),\n createdAt: experiment.createdTime,\n updatedAt: experiment.lastModifiedTime,\n };\n });\n } else {\n hints.push({\n key: 'statsig/failed-to-load-experiments',\n text: experiments.reason.message,\n });\n }\n\n return { definitions, hints };\n}\n\n/**\n * Fetch all Feature Gates.\n */\nasync function getFeatureGates(options: { consoleApiKey: string }) {\n const data: StatsigFeatureGateResponse['data'] = [];\n\n let suffix: string | null = '/console/v1/gates';\n\n do {\n const response = await fetch(`https://statsigapi.net${suffix}`, {\n method: 'GET',\n headers: {\n 'content-type': 'application/json',\n 'STATSIG-API-KEY': options.consoleApiKey,\n },\n // @ts-expect-error some Next.js versions need this\n cache: 'no-store',\n });\n\n if (response.status !== 200) {\n // Consume the response body to free up connections.\n await response.arrayBuffer();\n\n throw new Error(\n `Failed to fetch Statsig (Received ${response.status} response)`,\n );\n }\n\n const body = (await response.json()) as StatsigFeatureGateResponse;\n suffix = body.pagination?.nextPage || null;\n data.push(...body.data);\n } while (suffix);\n\n return data;\n}\n\n/**\n * Fetch all experiments.\n */\nasync function getExperiments(options: { consoleApiKey: string }) {\n const data: StatsigExperimentsResponse['data'] = [];\n\n let suffix: string | null = '/console/v1/experiments';\n\n do {\n const response = await fetch(`https://statsigapi.net${suffix}`, {\n method: 'GET',\n headers: {\n 'content-type': 'application/json',\n 'STATSIG-API-KEY': options.consoleApiKey,\n },\n // @ts-expect-error some Next.js versions need this\n cache: 'no-store',\n });\n\n if (response.status !== 200) {\n // Consume the response body to free up connections.\n await response.arrayBuffer();\n\n throw new Error(\n `Failed to fetch Statsig (Received ${response.status} response)`,\n );\n }\n\n const body = (await response.json()) as StatsigExperimentsResponse;\n suffix = body.pagination?.nextPage || null;\n data.push(...body.data);\n } while (suffix);\n\n return data;\n}\n"]}