@featureflare/sdk-js 0.0.2 → 0.0.4
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.
- package/README.md +31 -22
- package/dist/index.cjs +20 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -6
- package/dist/index.d.ts +7 -6
- package/dist/index.js +20 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @featureflare/sdk-js
|
|
2
2
|
|
|
3
|
-
JavaScript/TypeScript SDK for
|
|
3
|
+
JavaScript/TypeScript SDK for FeatureFlare feature flags.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -17,15 +17,15 @@ yarn add @featureflare/sdk-js
|
|
|
17
17
|
### Basic Example
|
|
18
18
|
|
|
19
19
|
```typescript
|
|
20
|
-
import {
|
|
20
|
+
import { FeatureFlareClient } from '@featureflare/sdk-js';
|
|
21
21
|
|
|
22
22
|
// SDK automatically uses production API URL
|
|
23
|
-
// Set
|
|
24
|
-
const
|
|
23
|
+
// Set FEATUREFLARE_CLIENT_KEY or FEATUREFLARE_SERVER_KEY env var, or pass sdkKey explicitly
|
|
24
|
+
const featureflare = new FeatureFlareClient({
|
|
25
25
|
sdkKey: 'your-sdk-key-here'
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
const enabled = await
|
|
28
|
+
const enabled = await featureflare.bool('new-nav', { id: 'user-123' }, false);
|
|
29
29
|
console.log(enabled);
|
|
30
30
|
```
|
|
31
31
|
|
|
@@ -33,29 +33,37 @@ console.log(enabled);
|
|
|
33
33
|
|
|
34
34
|
The SDK automatically reads from environment variables if `sdkKey` is not provided:
|
|
35
35
|
|
|
36
|
-
- `
|
|
37
|
-
- `
|
|
36
|
+
- `FEATUREFLARE_CLIENT_KEY` - Client SDK key (for browser/mobile)
|
|
37
|
+
- `FEATUREFLARE_SERVER_KEY` - Server SDK key (for backend)
|
|
38
38
|
|
|
39
39
|
```typescript
|
|
40
|
-
// In Node.js, this will use
|
|
41
|
-
const
|
|
40
|
+
// In Node.js, this will use FEATUREFLARE_CLIENT_KEY or FEATUREFLARE_SERVER_KEY from env
|
|
41
|
+
const featureflare = new FeatureFlareClient();
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
### API Base URL
|
|
45
45
|
|
|
46
46
|
The SDK automatically determines the API base URL:
|
|
47
47
|
|
|
48
|
-
-
|
|
49
|
-
- **
|
|
48
|
+
- **`options.apiBaseUrl`**: Highest priority if provided.
|
|
49
|
+
- **Environment variables**: `FEATUREFLARE_API_BASE_URL`, then `SHIPIT_API_BASE_URL`.
|
|
50
|
+
- **Default fallback**: `https://shipit-api-392444455847.us-central1.run.app`.
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
Example override:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
const featureflare = new FeatureFlareClient({
|
|
56
|
+
apiBaseUrl: 'https://shipit-api-392444455847.us-central1.run.app',
|
|
57
|
+
sdkKey: 'featureflare_cli_...'
|
|
58
|
+
});
|
|
59
|
+
```
|
|
52
60
|
|
|
53
61
|
### User Payload
|
|
54
62
|
|
|
55
63
|
```typescript
|
|
56
|
-
import {
|
|
64
|
+
import { FeatureFlareClient, type FeatureFlareUserPayload } from '@featureflare/sdk-js';
|
|
57
65
|
|
|
58
|
-
const user:
|
|
66
|
+
const user: FeatureFlareUserPayload = {
|
|
59
67
|
id: 'user-123', // Required: unique user identifier
|
|
60
68
|
email: 'user@example.com',
|
|
61
69
|
name: 'John Doe',
|
|
@@ -66,28 +74,29 @@ const user: ShipItUserPayload = {
|
|
|
66
74
|
}
|
|
67
75
|
};
|
|
68
76
|
|
|
69
|
-
const enabled = await
|
|
77
|
+
const enabled = await featureflare.bool('feature-flag', user, false);
|
|
70
78
|
```
|
|
71
79
|
|
|
72
80
|
## API Reference
|
|
73
81
|
|
|
74
|
-
### `
|
|
82
|
+
### `FeatureFlareClient`
|
|
75
83
|
|
|
76
84
|
#### Constructor
|
|
77
85
|
|
|
78
86
|
```typescript
|
|
79
|
-
new
|
|
87
|
+
new FeatureFlareClient(options?: FeatureFlareClientOptions)
|
|
80
88
|
```
|
|
81
89
|
|
|
82
90
|
**Options:**
|
|
83
91
|
|
|
84
|
-
- `
|
|
92
|
+
- `apiBaseUrl?: string` - Explicit FeatureFlare API base URL.
|
|
93
|
+
- `sdkKey?: string` - SDK key (client or server). If not provided, reads from `FEATUREFLARE_CLIENT_KEY` or `FEATUREFLARE_SERVER_KEY` env vars.
|
|
85
94
|
- `projectKey?: string` - Legacy: project key (requires `envKey`). Not recommended.
|
|
86
95
|
- `envKey?: string` - Environment key (default: `'production'`). Only used with `projectKey`.
|
|
87
96
|
|
|
88
97
|
#### Methods
|
|
89
98
|
|
|
90
|
-
##### `bool(flagKey: string, user:
|
|
99
|
+
##### `bool(flagKey: string, user: FeatureFlareUserPayload, defaultValue?: boolean): Promise<boolean>`
|
|
91
100
|
|
|
92
101
|
Evaluates a boolean feature flag for a user.
|
|
93
102
|
|
|
@@ -100,7 +109,7 @@ Returns `Promise<boolean>` - The flag value for the user.
|
|
|
100
109
|
**Example:**
|
|
101
110
|
|
|
102
111
|
```typescript
|
|
103
|
-
const enabled = await
|
|
112
|
+
const enabled = await featureflare.bool('new-nav', { id: 'user-123' }, false);
|
|
104
113
|
```
|
|
105
114
|
|
|
106
115
|
## Error Handling
|
|
@@ -109,7 +118,7 @@ If the API request fails (network error, non-2xx status), the SDK returns the `d
|
|
|
109
118
|
|
|
110
119
|
```typescript
|
|
111
120
|
try {
|
|
112
|
-
const enabled = await
|
|
121
|
+
const enabled = await featureflare.bool('flag', user, false);
|
|
113
122
|
} catch (error) {
|
|
114
123
|
// Handle network errors
|
|
115
124
|
console.error('Failed to evaluate flag:', error);
|
|
@@ -123,7 +132,7 @@ Each environment has two SDK keys:
|
|
|
123
132
|
- **Server key**: Secret. Use only in trusted server environments.
|
|
124
133
|
- **Client key**: Not a secret. Intended for browser/mobile SDKs.
|
|
125
134
|
|
|
126
|
-
Get your SDK keys from your
|
|
135
|
+
Get your SDK keys from your FeatureFlare Console → Environments.
|
|
127
136
|
|
|
128
137
|
## License
|
|
129
138
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,35 +1,45 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
var DEFAULT_FEATUREFLARE_API_BASE_URL = "https://shipit-api-392444455847.us-central1.run.app";
|
|
5
|
+
function getApiBaseUrlFromEnv() {
|
|
6
|
+
if (typeof process !== "undefined" && process.env) {
|
|
7
|
+
return process.env.FEATUREFLARE_API_BASE_URL?.trim() || process.env.SHIPIT_API_BASE_URL?.trim() || null;
|
|
7
8
|
}
|
|
8
|
-
return
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
function getApiBaseUrl(explicit) {
|
|
12
|
+
const fromOptions = explicit?.trim();
|
|
13
|
+
if (fromOptions) return fromOptions;
|
|
14
|
+
const fromEnv = getApiBaseUrlFromEnv();
|
|
15
|
+
if (fromEnv) return fromEnv;
|
|
16
|
+
return DEFAULT_FEATUREFLARE_API_BASE_URL;
|
|
9
17
|
}
|
|
10
18
|
function getSdkKeyFromEnv() {
|
|
11
19
|
if (typeof process !== "undefined" && process.env) {
|
|
12
|
-
return process.env.SHIPIT_CLIENT_KEY?.trim() || process.env.SHIPIT_SERVER_KEY?.trim() || null;
|
|
20
|
+
return process.env.FEATUREFLARE_CLIENT_KEY?.trim() || process.env.FEATUREFLARE_SERVER_KEY?.trim() || process.env.SHIPIT_CLIENT_KEY?.trim() || process.env.SHIPIT_SERVER_KEY?.trim() || null;
|
|
13
21
|
}
|
|
14
22
|
return null;
|
|
15
23
|
}
|
|
16
|
-
var
|
|
24
|
+
var FeatureFlareClient = class {
|
|
17
25
|
apiBaseUrl;
|
|
18
26
|
sdkKey;
|
|
19
27
|
projectKey;
|
|
20
28
|
envKey;
|
|
21
29
|
constructor(options = {}) {
|
|
22
|
-
this.apiBaseUrl = getApiBaseUrl().replace(/\/$/, "");
|
|
30
|
+
this.apiBaseUrl = getApiBaseUrl(options.apiBaseUrl).replace(/\/$/, "");
|
|
23
31
|
this.sdkKey = options.sdkKey?.trim() || getSdkKeyFromEnv();
|
|
24
32
|
this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;
|
|
25
33
|
this.envKey = options.envKey ?? "production";
|
|
26
34
|
if (!this.sdkKey && !this.projectKey) {
|
|
27
|
-
throw new Error(
|
|
35
|
+
throw new Error(
|
|
36
|
+
"FeatureFlareClient requires either sdkKey (recommended) or projectKey (legacy). Set FEATUREFLARE_CLIENT_KEY or FEATUREFLARE_SERVER_KEY env var, or pass sdkKey in options."
|
|
37
|
+
);
|
|
28
38
|
}
|
|
29
39
|
}
|
|
30
40
|
normalizeUser(input) {
|
|
31
41
|
const key = (input.id ?? input.key ?? "").trim();
|
|
32
|
-
if (!key) throw new Error("
|
|
42
|
+
if (!key) throw new Error("FeatureFlareClient requires user.id (or legacy user.key).");
|
|
33
43
|
return {
|
|
34
44
|
key,
|
|
35
45
|
email: input.email,
|
|
@@ -68,6 +78,6 @@ var ShipItClient = class {
|
|
|
68
78
|
}
|
|
69
79
|
};
|
|
70
80
|
|
|
71
|
-
exports.
|
|
81
|
+
exports.FeatureFlareClient = FeatureFlareClient;
|
|
72
82
|
//# sourceMappingURL=index.cjs.map
|
|
73
83
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;AAsBA,SAAS,
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export type FeatureFlareUserPayload = {\n /** Unique user identifier (preferred). */\n id?: string;\n /** Legacy alias for id. */\n key?: string;\n email?: string;\n name?: string;\n country?: string;\n /** Queryable attributes. */\n meta?: Record<string, string | number | boolean | null>;\n /** Legacy alias for meta. */\n custom?: Record<string, string | number | boolean | null>;\n};\n\ntype FeatureFlareUser = {\n key: string;\n email?: string;\n name?: string;\n country?: string;\n custom?: Record<string, string | number | boolean | null>;\n};\n\nconst DEFAULT_FEATUREFLARE_API_BASE_URL =\n 'https://shipit-api-392444455847.us-central1.run.app';\n\nfunction getApiBaseUrlFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_API_BASE_URL?.trim() ||\n process.env.SHIPIT_API_BASE_URL?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction getApiBaseUrl(explicit?: string): string {\n const fromOptions = explicit?.trim();\n if (fromOptions) return fromOptions;\n\n const fromEnv = getApiBaseUrlFromEnv();\n if (fromEnv) return fromEnv;\n\n return DEFAULT_FEATUREFLARE_API_BASE_URL;\n}\n\nexport type FeatureFlareClientOptions = {\n apiBaseUrl?: string;\n sdkKey?: string;\n projectKey?: string;\n envKey?: string;\n};\n\nfunction getSdkKeyFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_CLIENT_KEY?.trim() ||\n process.env.FEATUREFLARE_SERVER_KEY?.trim() ||\n process.env.SHIPIT_CLIENT_KEY?.trim() ||\n process.env.SHIPIT_SERVER_KEY?.trim() ||\n null\n );\n }\n return null;\n}\n\nexport class FeatureFlareClient {\n private readonly apiBaseUrl: string;\n private readonly sdkKey: string | null;\n private readonly projectKey: string | null;\n private readonly envKey: string;\n\n constructor(options: FeatureFlareClientOptions = {}) {\n this.apiBaseUrl = getApiBaseUrl(options.apiBaseUrl).replace(/\\/$/, '');\n this.sdkKey = options.sdkKey?.trim() || getSdkKeyFromEnv();\n this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;\n this.envKey = options.envKey ?? 'production';\n\n if (!this.sdkKey && !this.projectKey) {\n throw new Error(\n 'FeatureFlareClient requires either sdkKey (recommended) or projectKey (legacy). Set FEATUREFLARE_CLIENT_KEY or FEATUREFLARE_SERVER_KEY env var, or pass sdkKey in options.'\n );\n }\n }\n\n private normalizeUser(input: FeatureFlareUserPayload): FeatureFlareUser {\n const key = (input.id ?? input.key ?? '').trim();\n if (!key) throw new Error('FeatureFlareClient requires user.id (or legacy user.key).');\n return {\n key,\n email: input.email,\n name: input.name,\n country: input.country,\n custom: input.meta ?? input.custom\n };\n }\n\n async bool(flagKey: string, user: FeatureFlareUserPayload, defaultValue = false): Promise<boolean> {\n const normalizedUser = this.normalizeUser(user);\n const res = this.sdkKey\n ? await fetch(`${this.apiBaseUrl}/api/v1/sdk/eval`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-featureflare-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n })\n : await fetch(`${this.apiBaseUrl}/api/v1/eval`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n projectKey: this.projectKey,\n envKey: this.envKey,\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n });\n\n if (!res.ok) return defaultValue;\n const json = (await res.json()) as { value: boolean };\n return json.value;\n }\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type
|
|
1
|
+
type FeatureFlareUserPayload = {
|
|
2
2
|
/** Unique user identifier (preferred). */
|
|
3
3
|
id?: string;
|
|
4
4
|
/** Legacy alias for id. */
|
|
@@ -11,19 +11,20 @@ type ShipItUserPayload = {
|
|
|
11
11
|
/** Legacy alias for meta. */
|
|
12
12
|
custom?: Record<string, string | number | boolean | null>;
|
|
13
13
|
};
|
|
14
|
-
type
|
|
14
|
+
type FeatureFlareClientOptions = {
|
|
15
|
+
apiBaseUrl?: string;
|
|
15
16
|
sdkKey?: string;
|
|
16
17
|
projectKey?: string;
|
|
17
18
|
envKey?: string;
|
|
18
19
|
};
|
|
19
|
-
declare class
|
|
20
|
+
declare class FeatureFlareClient {
|
|
20
21
|
private readonly apiBaseUrl;
|
|
21
22
|
private readonly sdkKey;
|
|
22
23
|
private readonly projectKey;
|
|
23
24
|
private readonly envKey;
|
|
24
|
-
constructor(options?:
|
|
25
|
+
constructor(options?: FeatureFlareClientOptions);
|
|
25
26
|
private normalizeUser;
|
|
26
|
-
bool(flagKey: string, user:
|
|
27
|
+
bool(flagKey: string, user: FeatureFlareUserPayload, defaultValue?: boolean): Promise<boolean>;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
export {
|
|
30
|
+
export { FeatureFlareClient, type FeatureFlareClientOptions, type FeatureFlareUserPayload };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type
|
|
1
|
+
type FeatureFlareUserPayload = {
|
|
2
2
|
/** Unique user identifier (preferred). */
|
|
3
3
|
id?: string;
|
|
4
4
|
/** Legacy alias for id. */
|
|
@@ -11,19 +11,20 @@ type ShipItUserPayload = {
|
|
|
11
11
|
/** Legacy alias for meta. */
|
|
12
12
|
custom?: Record<string, string | number | boolean | null>;
|
|
13
13
|
};
|
|
14
|
-
type
|
|
14
|
+
type FeatureFlareClientOptions = {
|
|
15
|
+
apiBaseUrl?: string;
|
|
15
16
|
sdkKey?: string;
|
|
16
17
|
projectKey?: string;
|
|
17
18
|
envKey?: string;
|
|
18
19
|
};
|
|
19
|
-
declare class
|
|
20
|
+
declare class FeatureFlareClient {
|
|
20
21
|
private readonly apiBaseUrl;
|
|
21
22
|
private readonly sdkKey;
|
|
22
23
|
private readonly projectKey;
|
|
23
24
|
private readonly envKey;
|
|
24
|
-
constructor(options?:
|
|
25
|
+
constructor(options?: FeatureFlareClientOptions);
|
|
25
26
|
private normalizeUser;
|
|
26
|
-
bool(flagKey: string, user:
|
|
27
|
+
bool(flagKey: string, user: FeatureFlareUserPayload, defaultValue?: boolean): Promise<boolean>;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
export {
|
|
30
|
+
export { FeatureFlareClient, type FeatureFlareClientOptions, type FeatureFlareUserPayload };
|
package/dist/index.js
CHANGED
|
@@ -1,33 +1,43 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
var DEFAULT_FEATUREFLARE_API_BASE_URL = "https://shipit-api-392444455847.us-central1.run.app";
|
|
3
|
+
function getApiBaseUrlFromEnv() {
|
|
4
|
+
if (typeof process !== "undefined" && process.env) {
|
|
5
|
+
return process.env.FEATUREFLARE_API_BASE_URL?.trim() || process.env.SHIPIT_API_BASE_URL?.trim() || null;
|
|
5
6
|
}
|
|
6
|
-
return
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
function getApiBaseUrl(explicit) {
|
|
10
|
+
const fromOptions = explicit?.trim();
|
|
11
|
+
if (fromOptions) return fromOptions;
|
|
12
|
+
const fromEnv = getApiBaseUrlFromEnv();
|
|
13
|
+
if (fromEnv) return fromEnv;
|
|
14
|
+
return DEFAULT_FEATUREFLARE_API_BASE_URL;
|
|
7
15
|
}
|
|
8
16
|
function getSdkKeyFromEnv() {
|
|
9
17
|
if (typeof process !== "undefined" && process.env) {
|
|
10
|
-
return process.env.SHIPIT_CLIENT_KEY?.trim() || process.env.SHIPIT_SERVER_KEY?.trim() || null;
|
|
18
|
+
return process.env.FEATUREFLARE_CLIENT_KEY?.trim() || process.env.FEATUREFLARE_SERVER_KEY?.trim() || process.env.SHIPIT_CLIENT_KEY?.trim() || process.env.SHIPIT_SERVER_KEY?.trim() || null;
|
|
11
19
|
}
|
|
12
20
|
return null;
|
|
13
21
|
}
|
|
14
|
-
var
|
|
22
|
+
var FeatureFlareClient = class {
|
|
15
23
|
apiBaseUrl;
|
|
16
24
|
sdkKey;
|
|
17
25
|
projectKey;
|
|
18
26
|
envKey;
|
|
19
27
|
constructor(options = {}) {
|
|
20
|
-
this.apiBaseUrl = getApiBaseUrl().replace(/\/$/, "");
|
|
28
|
+
this.apiBaseUrl = getApiBaseUrl(options.apiBaseUrl).replace(/\/$/, "");
|
|
21
29
|
this.sdkKey = options.sdkKey?.trim() || getSdkKeyFromEnv();
|
|
22
30
|
this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;
|
|
23
31
|
this.envKey = options.envKey ?? "production";
|
|
24
32
|
if (!this.sdkKey && !this.projectKey) {
|
|
25
|
-
throw new Error(
|
|
33
|
+
throw new Error(
|
|
34
|
+
"FeatureFlareClient requires either sdkKey (recommended) or projectKey (legacy). Set FEATUREFLARE_CLIENT_KEY or FEATUREFLARE_SERVER_KEY env var, or pass sdkKey in options."
|
|
35
|
+
);
|
|
26
36
|
}
|
|
27
37
|
}
|
|
28
38
|
normalizeUser(input) {
|
|
29
39
|
const key = (input.id ?? input.key ?? "").trim();
|
|
30
|
-
if (!key) throw new Error("
|
|
40
|
+
if (!key) throw new Error("FeatureFlareClient requires user.id (or legacy user.key).");
|
|
31
41
|
return {
|
|
32
42
|
key,
|
|
33
43
|
email: input.email,
|
|
@@ -66,6 +76,6 @@ var ShipItClient = class {
|
|
|
66
76
|
}
|
|
67
77
|
};
|
|
68
78
|
|
|
69
|
-
export {
|
|
79
|
+
export { FeatureFlareClient };
|
|
70
80
|
//# sourceMappingURL=index.js.map
|
|
71
81
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";AAsBA,SAAS,
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export type FeatureFlareUserPayload = {\n /** Unique user identifier (preferred). */\n id?: string;\n /** Legacy alias for id. */\n key?: string;\n email?: string;\n name?: string;\n country?: string;\n /** Queryable attributes. */\n meta?: Record<string, string | number | boolean | null>;\n /** Legacy alias for meta. */\n custom?: Record<string, string | number | boolean | null>;\n};\n\ntype FeatureFlareUser = {\n key: string;\n email?: string;\n name?: string;\n country?: string;\n custom?: Record<string, string | number | boolean | null>;\n};\n\nconst DEFAULT_FEATUREFLARE_API_BASE_URL =\n 'https://shipit-api-392444455847.us-central1.run.app';\n\nfunction getApiBaseUrlFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_API_BASE_URL?.trim() ||\n process.env.SHIPIT_API_BASE_URL?.trim() ||\n null\n );\n }\n return null;\n}\n\nfunction getApiBaseUrl(explicit?: string): string {\n const fromOptions = explicit?.trim();\n if (fromOptions) return fromOptions;\n\n const fromEnv = getApiBaseUrlFromEnv();\n if (fromEnv) return fromEnv;\n\n return DEFAULT_FEATUREFLARE_API_BASE_URL;\n}\n\nexport type FeatureFlareClientOptions = {\n apiBaseUrl?: string;\n sdkKey?: string;\n projectKey?: string;\n envKey?: string;\n};\n\nfunction getSdkKeyFromEnv(): string | null {\n if (typeof process !== 'undefined' && process.env) {\n return (\n process.env.FEATUREFLARE_CLIENT_KEY?.trim() ||\n process.env.FEATUREFLARE_SERVER_KEY?.trim() ||\n process.env.SHIPIT_CLIENT_KEY?.trim() ||\n process.env.SHIPIT_SERVER_KEY?.trim() ||\n null\n );\n }\n return null;\n}\n\nexport class FeatureFlareClient {\n private readonly apiBaseUrl: string;\n private readonly sdkKey: string | null;\n private readonly projectKey: string | null;\n private readonly envKey: string;\n\n constructor(options: FeatureFlareClientOptions = {}) {\n this.apiBaseUrl = getApiBaseUrl(options.apiBaseUrl).replace(/\\/$/, '');\n this.sdkKey = options.sdkKey?.trim() || getSdkKeyFromEnv();\n this.projectKey = options.projectKey?.trim() ? options.projectKey.trim() : null;\n this.envKey = options.envKey ?? 'production';\n\n if (!this.sdkKey && !this.projectKey) {\n throw new Error(\n 'FeatureFlareClient requires either sdkKey (recommended) or projectKey (legacy). Set FEATUREFLARE_CLIENT_KEY or FEATUREFLARE_SERVER_KEY env var, or pass sdkKey in options.'\n );\n }\n }\n\n private normalizeUser(input: FeatureFlareUserPayload): FeatureFlareUser {\n const key = (input.id ?? input.key ?? '').trim();\n if (!key) throw new Error('FeatureFlareClient requires user.id (or legacy user.key).');\n return {\n key,\n email: input.email,\n name: input.name,\n country: input.country,\n custom: input.meta ?? input.custom\n };\n }\n\n async bool(flagKey: string, user: FeatureFlareUserPayload, defaultValue = false): Promise<boolean> {\n const normalizedUser = this.normalizeUser(user);\n const res = this.sdkKey\n ? await fetch(`${this.apiBaseUrl}/api/v1/sdk/eval`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-featureflare-sdk-key': this.sdkKey\n },\n body: JSON.stringify({\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n })\n : await fetch(`${this.apiBaseUrl}/api/v1/eval`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n projectKey: this.projectKey,\n envKey: this.envKey,\n flagKey,\n user: normalizedUser,\n defaultValue\n })\n });\n\n if (!res.ok) return defaultValue;\n const json = (await res.json()) as { value: boolean };\n return json.value;\n }\n}\n"]}
|