statsig-node-vercel 0.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,64 @@
1
+ import { AdapterResponse, IDataAdapter, DataAdapterKey } from 'statsig-node';
2
+ import { get } from '@vercel/edge-config';
3
+
4
+ interface Data {
5
+ dynamic_configs: Record<string, unknown>[];
6
+ feature_gates: Record<string, unknown>[];
7
+ has_updates: boolean;
8
+ id_lists: unknown;
9
+ layer_configs: unknown[];
10
+ layers: unknown;
11
+ time: number;
12
+ }
13
+
14
+ export class EdgeConfigDataAdapter implements IDataAdapter {
15
+ private key: string;
16
+ private cache: Map<string, string>;
17
+ private timeCache: Map<string, number>;
18
+
19
+ public constructor(key: string) {
20
+ this.key = key;
21
+ this.cache = new Map<string, string>();
22
+ this.timeCache = new Map<string, number>();
23
+ }
24
+
25
+ // eslint-disable-next-line @typescript-eslint/require-await
26
+ public async get(key: string): Promise<AdapterResponse> {
27
+ const value = this.cache.get(key);
28
+ if (value === undefined) {
29
+ return { error: new Error(`key (${key}) does not exist`) };
30
+ }
31
+ const time = this.timeCache.get(key);
32
+ return { result: value, time };
33
+ }
34
+
35
+ // eslint-disable-next-line @typescript-eslint/require-await
36
+ public async set(
37
+ key: string,
38
+ value: string,
39
+ time?: number | undefined,
40
+ ): Promise<void> {
41
+ // no-op. Statsig's Edge Config integration keeps config specs synced through Statsig's service
42
+ }
43
+
44
+ public async initialize(): Promise<void> {
45
+ const data = await get<Data>(this.key);
46
+
47
+ if (data) {
48
+ this.cache.set('statsig.cache', JSON.stringify(data));
49
+ this.timeCache.set('statsig.cache', data.time);
50
+ }
51
+ }
52
+
53
+ // eslint-disable-next-line @typescript-eslint/require-await
54
+ public async shutdown(): Promise<void> {
55
+ this.cache.clear();
56
+ }
57
+
58
+ public supportsPollingUpdatesFor(key: DataAdapterKey): boolean {
59
+ if (key === DataAdapterKey.Rulesets) {
60
+ return true;
61
+ }
62
+ return false;
63
+ }
64
+ }
package/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ ISC License (ISC)
2
+ Copyright (c) 2022, Statsig, Inc.
3
+
4
+ Permission to use, copy, modify, and/or distribute this software for any purpose
5
+ with or without fee is hereby granted, provided that the above copyright notice
6
+ and this permission notice appear in all copies.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
10
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
12
+ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
13
+ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
14
+ THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # Statsig Node Server SDK - Redis Integration
2
+ [![npm version](https://badge.fury.io/js/statsig-node-redis.svg)](https://badge.fury.io/js/statsig-node-redis)
3
+
4
+ A first party Redis integration with the [Statsig server-side Node.js SDK](https://github.com/statsig-io/node-js-server-sdk).
5
+
6
+ ## Quick Setup
7
+ 1. Install the Statsig Node SDK *NOTE: (For now, you will need the latest beta version 4.18.0-beta.7)*
8
+ ```
9
+ npm install statsig-node@4.18.0-beta.7
10
+ ```
11
+ 2. Install this package
12
+ ```
13
+ npm install statsig-node-redis
14
+ ```
15
+ 3. Import the package
16
+ ```
17
+ import { RedisDataAdapter } from 'statsig-node-redis'
18
+ ```
19
+ 4. Create an instance of the `RedisDataAdapter`
20
+ ```
21
+ const dataAdapter = new RedisDataAdapter();
22
+ ```
23
+ 5. When initializing the `statsig` sdk, add the adapter to options
24
+ ```
25
+ await statsig.initialize(
26
+ 'server-secret-key',
27
+ { dataAdapter: dataAdapter },
28
+ );
29
+ ```
30
+
31
+ ## Customizing the adapter
32
+ When initializing `RedisDataAdapter`, you can specify the following options:
33
+ ```
34
+ const dataAdapter = new RedisDataAdapter(
35
+ hostname,
36
+ port,
37
+ password,
38
+ db,
39
+ );
40
+ ```
41
+
42
+ | param | default | description |
43
+ | --- | --- | --- |
44
+ | hostname | 'localhost' | Redis server hostname |
45
+ | port | 6379 | Redis server port |
46
+ | password | | ACL password or the old "--requirepass" password |
47
+ | db | 0 | Redis database number (supports 16 databases) |
48
+
49
+ ## Links
50
+ [Node Redis](https://github.com/redis/node-redis)
@@ -0,0 +1,37 @@
1
+ import { EdgeConfigDataAdapter } from '../EdgeConfigDataAdapter';
2
+ import * as statsigsdk from 'statsig-node';
3
+ // @ts-ignore
4
+ const statsig = statsigsdk.default;
5
+
6
+ describe('Validate edge config adapter functionality', () => {
7
+ const dataAdapter = new EdgeConfigDataAdapter(
8
+ 'statsig-3Xl7zBzgVt7La7nzjE0m9V'
9
+ );
10
+ const statsigOptions = {
11
+ dataAdapter: dataAdapter,
12
+ environment: { tier: 'staging' },
13
+ };
14
+ const user = {
15
+ userID: '12345',
16
+ email: 'kenny@nfl.com',
17
+ custom: { level: 9 },
18
+ };
19
+
20
+ beforeEach(async () => {
21
+ statsig._instance = null;
22
+ await dataAdapter.initialize();
23
+ })
24
+
25
+ afterEach(async () => {
26
+ await dataAdapter.shutdown();
27
+ });
28
+
29
+ test('Simple get/set', async () => {
30
+ dataAdapter.set('gates', 'test123');
31
+ const { result: gates } = await dataAdapter.get('gates');
32
+ if (gates == null) {
33
+ return;
34
+ }
35
+ expect(gates).toEqual('test123');
36
+ });
37
+ })
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ presets: [
3
+ ['@babel/preset-env', { targets: { node: 'current' } }],
4
+ '@babel/preset-typescript',
5
+ ],
6
+ };
package/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ import * as EdgeConfigDataAdapter from './EdgeConfigDataAdapter';
2
+ import * as Statsig from 'statsig-node';
3
+
4
+ module.exports = {
5
+ EdgeConfigDataAdapter,
6
+ Statsig
7
+ }
package/jest.config.js ADDED
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ roots: ['./'],
3
+ testMatch: ['**/__tests__/**/*.test.(j|t)s', '**/?(*.)+test.(j|t)s'],
4
+ testPathIgnorePatterns: [
5
+ '<rootDir>/node_modules/',
6
+ '<rootDir>/dist/',
7
+ ],
8
+ };
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "statsig-node-vercel",
3
+ "version": "0.0.1-beta.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "prepare": "rm -rf dist/ && tsc",
8
+ "test": "npm run prepare && pnpm jest"
9
+ },
10
+ "types": "./index.d.ts",
11
+ "keywords": [],
12
+ "author": "",
13
+ "license": "ISC",
14
+ "dependencies": {
15
+ "@vercel/edge-config": "^0.1.0-canary.15"
16
+ },
17
+ "devDependencies": {
18
+ "@babel/core": "^7.18.13",
19
+ "@babel/preset-env": "^7.18.10",
20
+ "@babel/preset-typescript": "^7.18.6",
21
+ "@types/jest": "^28.1.8",
22
+ "jest": "^29.0.0",
23
+ "statsig-node": "5.1.0-beta.1"
24
+ }
25
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "exclude": [
3
+ "node_modules",
4
+ "__tests__/*",
5
+ "dist",
6
+ "dist/**/*",
7
+ "tsconfig.json",
8
+ ],
9
+ "compilerOptions": {
10
+ /* Visit https://aka.ms/tsconfig to read more about this file */
11
+ /* Language and Environment */
12
+ "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
13
+ "lib": [
14
+ "ES2020.Promise"
15
+ ], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16
+ /* Modules */
17
+ "module": "commonjs", /* Specify what module code is generated. */
18
+ "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
19
+ "typeRoots": [
20
+ "node_modules/@types"
21
+ ], /* Specify multiple folders that act like './node_modules/@types'. */
22
+ "resolveJsonModule": true, /* Enable importing .json files. */
23
+ /* JavaScript Support */
24
+ "allowJs": false, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
25
+ /* Emit */
26
+ "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
27
+ "outDir": "dist", /* Specify an output folder for all emitted files. */
28
+ /* Interop Constraints */
29
+ "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
30
+ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
31
+ /* Type Checking */
32
+ "strict": true, /* Enable all strict type-checking options. */
33
+ /* Completeness */
34
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */
35
+ }
36
+ }