@devcycle/nextjs-sdk
Version:
The Next.js SDK for DevCycle!
92 lines • 4.05 kB
JavaScript
import { fetchCDNConfig, hasOptInEnabled, sdkConfigAPI } from './requests';
import { generateBucketedConfig } from '@devcycle/bucketing';
import { cache } from 'react';
import { DVCPopulatedUser } from '@devcycle/js-client-sdk';
import { ConfigSource } from '@devcycle/types';
export const getPopulatedUser = cache((user, userAgent) => {
return new DVCPopulatedUser(user, {}, undefined, undefined, userAgent !== null && userAgent !== void 0 ? userAgent : undefined);
});
const checkOptInEnabled = async (config, user, clientSDKKey) => {
var _a;
if (!((_a = config.project.settings.optIn) === null || _a === void 0 ? void 0 : _a.enabled)) {
return false;
}
return await hasOptInEnabled(user.user_id, clientSDKKey);
};
// wrap this function in react cache to avoid redoing work for the same user and config
const generateBucketedConfigCached = cache(async (user, config, obfuscated, enableEdgeDB, userAgent) => {
var _a, _b;
const populatedUser = getPopulatedUser(user, userAgent);
// clientSDKKey is always defined for bootstrap config
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const clientSDKKey = config.clientSDKKey;
if (enableEdgeDB && !config.project.settings.edgeDB.enabled) {
console.warn('EdgeDB is not enabled for this project. Only using local user data.');
}
const useEdgeDB = config.project.settings.edgeDB.enabled && enableEdgeDB;
const useOptIn = await checkOptInEnabled(config, populatedUser, clientSDKKey);
if (((_a = config.debugUsers) === null || _a === void 0 ? void 0 : _a.includes((_b = user.user_id) !== null && _b !== void 0 ? _b : '')) ||
useEdgeDB ||
useOptIn) {
const bucketedConfigResponse = await sdkConfigAPI(clientSDKKey, populatedUser, obfuscated, useEdgeDB);
return {
bucketedConfig: {
...bucketedConfigResponse,
clientSDKKey,
},
};
}
return {
bucketedConfig: {
...generateBucketedConfig({
user: populatedUser,
config,
}),
clientSDKKey,
sse: {
url: config.sse
? `${config.sse.hostname}${config.sse.path}`
: undefined,
inactivityDelay: 1000 * 60 * 2,
},
},
};
});
class CDNConfigSource extends ConfigSource {
constructor(clientSDKKey) {
super();
this.clientSDKKey = clientSDKKey;
}
async getConfig(sdkKey, kind, obfuscated) {
// this request will be cached by Next
const { config, headers } = await fetchCDNConfig(sdkKey, this.clientSDKKey, obfuscated);
return {
config,
lastModified: headers.get('last-modified'),
metaData: {},
};
}
// dummy implementation to make types happy, this method isn't used in Next
getConfigURL() {
return '';
}
}
export const getConfigFromSource = async (sdkKey, clientSDKKey, options) => {
var _a;
const cdnConfigSource = new CDNConfigSource(clientSDKKey);
const configSource = (_a = options.configSource) !== null && _a !== void 0 ? _a : cdnConfigSource;
const { config, lastModified } = await configSource.getConfig(sdkKey, 'bootstrap', !!options.enableObfuscation, '', true);
return { config, lastModified };
};
/**
* Compute the bucketed config for the current request's user using raw config data, with local bucketing library
* Cache the bucketed config for this request so that repeated calls to this function are memoized
*/
export const getBucketedConfig = async (config, lastModified, user, options, userAgent) => {
const { bucketedConfig } = await generateBucketedConfigCached(user, config, !!options.enableObfuscation, !!options.enableEdgeDB, userAgent);
return {
...bucketedConfig,
lastModified: lastModified !== null && lastModified !== void 0 ? lastModified : undefined,
};
};
//# sourceMappingURL=bucketing.js.map