Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

34 changes: 25 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
# statsig
# @lovart-open/flags

[![CI](https://github.com/lovartai/flags/actions/workflows/ci.yml/badge.svg)](https://github.com/lovartai/flags/actions/workflows/ci.yml)
[![npm version](https://img.shields.io/npm/v/statsig.svg)](https://www.npmjs.com/package/statsig)
[![CI](https://github.com/lovartai/statsig/actions/workflows/ci.yml/badge.svg)](https://github.com/lovartai/statsig/actions/workflows/ci.yml)
[![npm version](https://img.shields.io/npm/v/@lovart-open/flags.svg)](https://www.npmjs.com/package/@lovart-open/flags)

Type-safe Feature Flag and Parameter Store library built on Statsig, with a fully synchronous architecture.

## Installation

```bash
npm install statsig
npm install @lovart-open/flags
# or
pnpm add statsig
pnpm add @lovart-open/flags
```

## Initialize Statsig

Initialize the Statsig client at your app entry point:

```ts
import { initStatsigClient } from 'statsig';
import { initStatsigClient } from '@lovart-open/flags/statsig';

initStatsigClient('your-statsig-client-key', { userID: 'user-123' }, {
environment: { tier: 'production' },
Expand All @@ -38,7 +38,7 @@ initStatsigClient('your-statsig-client-key', { userID: 'user-123' }, {
## Define and Create

```ts
import { createFlagStore, type FlagDefinition } from 'statsig';
import { createFlagStore, type FlagDefinition } from '@lovart-open/flags/statsig';

// 1. Define your flags
const MY_FLAGS = {
Expand Down Expand Up @@ -120,7 +120,7 @@ import {
createParamStore,
defineParam,
type ParamStoreDefinition
} from 'statsig';
} from '@lovart-open/flags/statsig';

// 1. Define your param stores
const MY_PARAMS = {
Expand Down Expand Up @@ -217,9 +217,15 @@ store.get('currency'); // 'USD' | 'CNY' | 'EUR'
## Custom Logger

```ts
import { initStatsigClient, setLogger } from '@lovart-open/flags/statsig';

// Option 1: Pass during init
initStatsigClient('client-xxx', { userID: 'user-123' }, {
logger: (message, data) => myLogger.info(message, data),
logger: (message) => myLogger.info(message),
});

// Option 2: Set globally
setLogger((message) => myLogger.info(message));
```

## E2E Test Support
Expand All @@ -237,6 +243,16 @@ await page.addInitScript(() => {
});
```

## Server-Side Bootstrap (Zero-Network Init)

```ts
initStatsigClient('client-xxx', { userID: 'user-123' }, {
bootstrap: {
data: bootstrapDataFromServer, // Pre-fetched from BFF
},
});
```

## FlagDefinition Options

| Property | Type | Description |
Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
{
"name": "@lovart-open/statsig",
"version": "1.0.0",
"name": "@lovart-open/flags",
"version": "0.0.1",
"description": "Feature flag management with multi-layer priority system (client-side)",
"main": "src/index.ts",
"types": "src/index.ts",
"exports": {
".": {
"types": "./src/index.ts",
"default": "./src/index.ts"
},
"./statsig": {
"types": "./src/statsig/index.ts",
"default": "./src/statsig/index.ts"
}
},
"files": [
Expand All @@ -27,7 +31,6 @@
"dependencies": {
"@statsig/js-client": "^3.30.0",
"@statsig/react-bindings": "^3.30.2",
"@statsig/web-analytics": "^3.30.0",
"lodash": "^4.17.21",
"zod": "^3.23.0"
},
Expand Down
17 changes: 0 additions & 17 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/__tests__/flag-store.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Mock external dependencies
const mockGetFeatureGate = vi.fn();
const mockIsTestEnv = vi.fn(() => false);
vi.mock('../statsig', () => ({
vi.mock('../statsig/client', () => ({
getStatsigClientSync: vi.fn(() => ({
getFeatureGate: mockGetFeatureGate,
})),
Expand All @@ -10,7 +10,7 @@ vi.mock('../statsig', () => ({

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import { createFlagStore, type FlagDefinition } from '../flags';
import { createFlagStore, type FlagDefinition } from '../statsig';

describe('FlagStore', () => {
const mockFlags = {
Expand Down
5 changes: 2 additions & 3 deletions src/__tests__/param-store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import { z } from 'zod';

// Mock statsig
const mockIsTestEnv = vi.fn(() => false);
vi.mock('../statsig', () => ({
vi.mock('../statsig/client', () => ({
getStatsigClientSync: vi.fn(() => ({
getParameterStore: vi.fn(),
})),
isTestEnv: () => mockIsTestEnv(),
}));

import { createParamStore, defineParam, type ParamStoreDefinition } from '../params';
import { getStatsigClientSync } from '../statsig';
import { createParamStore, defineParam, type ParamStoreDefinition, getStatsigClientSync } from '../statsig';

describe('ParamStore', () => {
const testStores = {
Expand Down
56 changes: 7 additions & 49 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,12 @@
/**
* statsig
* @lovart-open/flags
*
* Type-safe Feature Flag and Parameter Store management library.
* This package uses subpath exports. Import from:
* - @lovart-open/flags/statsig - Statsig-based feature flags and parameter stores
*
* Feature flag priority: URL > testOverride > override > remote > fallback(false)
* Parameter Store priority: URL > testOverride > override > remote > fallback
* @example
* import { createFlagStore, createParamStore } from '@lovart-open/flags/statsig';
*/

// Flag factory and types
export { createFlagStore, FlagStore, parseUrlOverrides, type ResolveOptions } from './flags';

// Param factory and types
export {
createParamStore,
defineParam,
PARAM_SCHEMA_MISMATCH_EVENT,
type ParamSchemaMismatchDetail,
parseParamStoreUrlOverrides,
ParamStore,
type ParamDefinition,
type ParamResolveOptions,
type ParamState,
type ParamStoreDefinition,
type ParamStoreHandle,
type ParamStoreValue,
} from './params';

// Logger
export { getLogger, type Logger } from './logger';

// Statsig integration
export {
getStatsigClientSync,
initStatsigClient,
isTestEnv,
type InitOptions,
type StatsigBootstrap,
} from './statsig';

// Core types
export {
type EvaluationOptions,
type FeatureGate,
type FlagDefinition,
type FlagKeyOf,
type FlagPriority,
type FlagSnapshot,
type FlagState,
type RemoteFlagValues,
} from './types';

// Statsig React bindings (re-export)
export * from '@statsig/react-bindings';
// No exports from root path - use subpath imports
export {};
2 changes: 1 addition & 1 deletion src/statsig/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { StatsigClient, type StatsigOptions, type StatsigUser } from '@statsig/js-client';

import { getLogger, type Logger, setLogger } from '../logger';
import { getLogger, type Logger, setLogger } from './logger';

let client: StatsigClient | null = null;
let testEnvDetector: (() => boolean) | null = null;
Expand Down
2 changes: 1 addition & 1 deletion src/flags.ts → src/statsig/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { useFeatureGate } from '@statsig/react-bindings';

import { getStatsigClientSync, isTestEnv } from './statsig';
import { getStatsigClientSync, isTestEnv } from './client';
import type { EvaluationOptions, FeatureGate, FlagDefinition, FlagSnapshot, FlagState } from './types';

export interface ResolveOptions extends EvaluationOptions {
Expand Down
45 changes: 44 additions & 1 deletion src/statsig/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,54 @@
/**
* Statsig module exports.
* @lovart-open/flags/statsig
*
* Type-safe Feature Flag and Parameter Store management library.
*
* Feature flag priority: URL > testOverride > override > remote > fallback(false)
* Parameter Store priority: URL > testOverride > override > remote > fallback
*/

// Flag factory and types
export { createFlagStore, FlagStore, parseUrlOverrides, type ResolveOptions } from './flags';

// Param factory and types
export {
createParamStore,
defineParam,
PARAM_SCHEMA_MISMATCH_EVENT,
type ParamSchemaMismatchDetail,
parseParamStoreUrlOverrides,
ParamStore,
type ParamDefinition,
type ParamResolveOptions,
type ParamState,
type ParamStoreDefinition,
type ParamStoreHandle,
type ParamStoreValue,
} from './params';

// Logger
export { getLogger, setLogger, type Logger } from './logger';

// Statsig client
export {
getStatsigClientSync,
initStatsigClient,
isTestEnv,
type InitOptions,
type StatsigBootstrap,
} from './client';

// Core types
export {
type EvaluationOptions,
type FeatureGate,
type FlagDefinition,
type FlagKeyOf,
type FlagPriority,
type FlagSnapshot,
type FlagState,
type RemoteFlagValues,
} from './types';

// Statsig React bindings (re-export)
export * from '@statsig/react-bindings';
File renamed without changes.
2 changes: 1 addition & 1 deletion src/params.ts → src/statsig/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { merge, set } from 'lodash';
import { useParameterStore } from '@statsig/react-bindings';
import z from 'zod';

import { getStatsigClientSync, isTestEnv } from './statsig';
import { getStatsigClientSync, isTestEnv } from './client';

/** Parameter definition */
export interface ParamDefinition<T = unknown> {
Expand Down
File renamed without changes.