@flags-sdk/statsig
Version:
Statsig provider for the Flags SDK
202 lines (190 loc) • 8.98 kB
JavaScript
;Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
var _chunkVSGLINUCcjs = require('./chunk-VSGLINUC.cjs');
// src/index.ts
var _statsignodelite = require('statsig-node-lite'); var _statsignodelite2 = _interopRequireDefault(_statsignodelite);
// src/edge-runtime-hooks.ts
async function createEdgeConfigDataAdapter(options) {
const { EdgeConfigDataAdapter } = await Promise.resolve().then(() => _interopRequireWildcard(require("statsig-node-vercel")));
const { createClient } = await Promise.resolve().then(() => _interopRequireWildcard(require("@vercel/edge-config")));
return new EdgeConfigDataAdapter({
edgeConfigItemKey: options.edgeConfigItemKey,
edgeConfigClient: createClient(options.edgeConfigConnectionString, {
// We disable the development cache as Statsig caches for 10 seconds internally,
// and we want to avoid situations where Statsig tries to read the latest value,
// but hits the development cache and then caches the outdated value for another 10 seconds,
// as this would lead to the developer having to wait 20 seconds to see the latest value.
disableDevelopmentCache: true
})
});
}
var createSyncingHandler = (minSyncDelayMs) => {
let isSyncingConfigSpecs = false;
let nextConfigSpecSyncTime = Date.now() + minSyncDelayMs;
return () => {
if (Date.now() >= nextConfigSpecSyncTime && !isSyncingConfigSpecs) {
try {
isSyncingConfigSpecs = true;
const sync = _statsignodelite2.default.syncConfigSpecs().finally(() => {
isSyncingConfigSpecs = false;
nextConfigSpecSyncTime = Date.now() + minSyncDelayMs;
});
Promise.resolve().then(() => _interopRequireWildcard(require("@vercel/functions"))).then(({ waitUntil }) => {
waitUntil(sync);
});
} catch (e) {
}
}
};
};
// src/index.ts
function createStatsigAdapter(options) {
const initializeStatsig = async () => {
let dataAdapter;
if (options.edgeConfig) {
dataAdapter = await createEdgeConfigDataAdapter({
edgeConfigItemKey: options.edgeConfig.itemKey,
edgeConfigConnectionString: options.edgeConfig.connectionString
});
}
await _statsignodelite2.default.initialize(options.statsigServerApiKey, {
dataAdapter,
// ID list syncing is disabled by default
// Can be opted in using `options.statsigOptions`
initStrategyForIDLists: "none",
disableIdListsSync: true,
// Set a shorter interval during development so developers see changes earlier
rulesetsSyncIntervalMs: process.env.NODE_ENV === "development" ? 5e3 : void 0,
...options.statsigOptions
});
};
let _initializePromise;
const initialize = async () => {
if (!_initializePromise) {
_initializePromise = initializeStatsig();
}
await _initializePromise;
return _statsignodelite2.default;
};
const isStatsigUser = (user) => {
return user != null && typeof user === "object";
};
const minSyncDelayMs = options.edgeConfig ? 1e3 : 5e3;
const syncHandler = createSyncingHandler(minSyncDelayMs);
async function predecide(user) {
await initialize();
_optionalChain([syncHandler, 'optionalCall', _ => _()]);
if (!isStatsigUser(user)) {
throw new Error(
"@flags-sdk/statsig: Invalid or missing statsigUser from identify. See https://flags-sdk.dev/concepts/identify"
);
}
return user;
}
function origin(prefix) {
if (!options.statsigProjectId) {
return () => void 0;
}
return (key) => {
const keyPart = _nullishCoalesce(key.split(".")[0], () => ( ""));
return `https://console.statsig.com/${options.statsigProjectId}/${prefix}/${keyPart}`;
};
}
function featureGate(getValue, opts) {
return {
origin: origin("gates"),
decide: async ({ key, entities }) => {
const user = await predecide(entities);
const gate = _optionalChain([opts, 'optionalAccess', _2 => _2.exposureLogging]) ? _statsignodelite2.default.getFeatureGateSync(user, key) : _statsignodelite2.default.getFeatureGateWithExposureLoggingDisabledSync(user, key);
return getValue(gate);
}
};
}
function dynamicConfig(getValue, opts) {
return {
origin: origin("dynamic_configs"),
decide: async ({ key, entities }) => {
const user = await predecide(entities);
const configKey = _nullishCoalesce(key.split(".")[0], () => ( ""));
const config = _optionalChain([opts, 'optionalAccess', _3 => _3.exposureLogging]) ? _statsignodelite2.default.getConfigSync(user, configKey) : _statsignodelite2.default.getConfigWithExposureLoggingDisabledSync(user, configKey);
return getValue(config);
}
};
}
function experiment(getValue, opts) {
return {
origin: origin("experiments"),
decide: async ({ key, entities }) => {
const user = await predecide(entities);
const experiment2 = _optionalChain([opts, 'optionalAccess', _4 => _4.exposureLogging]) ? _statsignodelite2.default.getExperimentSync(user, key) : _statsignodelite2.default.getExperimentWithExposureLoggingDisabledSync(user, key);
return getValue(experiment2);
}
};
}
function autotune(getValue, opts) {
return {
origin: origin("autotune"),
decide: async ({ key, entities }) => {
const user = await predecide(entities);
const autotune2 = _optionalChain([opts, 'optionalAccess', _5 => _5.exposureLogging]) ? _statsignodelite2.default.getConfigSync(user, key) : _statsignodelite2.default.getConfigWithExposureLoggingDisabledSync(user, key);
return getValue(autotune2);
}
};
}
function layer(getValue, opts) {
return {
origin: origin("layers"),
decide: async ({ key, entities }) => {
const user = await predecide(entities);
const layer2 = _optionalChain([opts, 'optionalAccess', _6 => _6.exposureLogging]) ? _statsignodelite2.default.getLayerSync(user, key) : _statsignodelite2.default.getLayerWithExposureLoggingDisabledSync(user, key);
return getValue(layer2);
}
};
}
return {
featureGate,
dynamicConfig,
experiment,
autotune,
layer,
initialize
};
}
var defaultStatsigAdapter;
function resetDefaultStatsigAdapter() {
defaultStatsigAdapter = void 0;
}
function createDefaultStatsigAdapter() {
if (defaultStatsigAdapter) {
return defaultStatsigAdapter;
}
const statsigServerApiKey = process.env.STATSIG_SERVER_API_KEY;
const statsigProjectId = process.env.STATSIG_PROJECT_ID;
const edgeConfig = process.env.EXPERIMENTATION_CONFIG;
const edgeConfigItemKey = process.env.EXPERIMENTATION_CONFIG_ITEM_KEY;
if (!(edgeConfig && edgeConfigItemKey)) {
defaultStatsigAdapter = createStatsigAdapter({
statsigServerApiKey,
statsigProjectId
});
} else {
defaultStatsigAdapter = createStatsigAdapter({
statsigServerApiKey,
edgeConfig: {
connectionString: edgeConfig,
itemKey: edgeConfigItemKey
},
statsigProjectId
});
}
return defaultStatsigAdapter;
}
var statsigAdapter = {
featureGate: (...args) => createDefaultStatsigAdapter().featureGate(...args),
dynamicConfig: (...args) => createDefaultStatsigAdapter().dynamicConfig(...args),
experiment: (...args) => createDefaultStatsigAdapter().experiment(...args),
autotune: (...args) => createDefaultStatsigAdapter().autotune(...args),
layer: (...args) => createDefaultStatsigAdapter().layer(...args),
initialize: () => createDefaultStatsigAdapter().initialize()
};
exports.Statsig = _statsignodelite2.default; exports.createDefaultStatsigAdapter = createDefaultStatsigAdapter; exports.createStatsigAdapter = createStatsigAdapter; exports.getProviderData = _chunkVSGLINUCcjs.getProviderData; exports.resetDefaultStatsigAdapter = resetDefaultStatsigAdapter; exports.statsigAdapter = statsigAdapter;
//# sourceMappingURL=index.cjs.map