@gradual-so/sdk 0.0.1
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/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +112 -0
- package/dist/index.d.ts +112 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
'use strict';function d(a,t){let{attributeKey:i,operator:r,value:n}=a,e=t[i];switch(r){case "equals":return e===n;case "not_equals":return e!==n;case "contains":return typeof e=="string"&&typeof n=="string"||Array.isArray(e)?e.includes(n):false;case "not_contains":return typeof e=="string"&&typeof n=="string"||Array.isArray(e)?!e.includes(n):true;case "starts_with":return typeof e=="string"&&typeof n=="string"?e.startsWith(n):false;case "ends_with":return typeof e=="string"&&typeof n=="string"?e.endsWith(n):false;case "greater_than":return typeof e=="number"&&typeof n=="number"?e>n:false;case "less_than":return typeof e=="number"&&typeof n=="number"?e<n:false;case "greater_than_or_equal":return typeof e=="number"&&typeof n=="number"?e>=n:false;case "less_than_or_equal":return typeof e=="number"&&typeof n=="number"?e<=n:false;case "in":return Array.isArray(n)?n.includes(e):false;case "not_in":return Array.isArray(n)?!n.includes(e):true;case "exists":return e!=null;case "not_exists":return e==null;default:return false}}function l(a,t){return a.every(i=>d(i,t))}function p(a,t){return l(a.conditions,t)}function h(a,t,i){switch(a.type){case "individual":return a.attributeKey&&a.attributeValue!==void 0?t[a.attributeKey]===a.attributeValue:false;case "rule":return a.conditions?l(a.conditions,t):false;case "segment":if(a.segmentKey){let r=i[a.segmentKey];if(r)return p(r,t)}return false;default:return false}}function s(a,t,i){if(!a.enabled)return a.variations[a.offVariationKey]?.value;let r=[...a.targets].sort((e,o)=>e.sortOrder-o.sortOrder);for(let e of r)if(h(e,t,i)){let o=a.variations[e.variationKey];if(o)return o.value}return a.variations[a.defaultVariationKey]?.value}var f="https://worker.gradual.so/api/v1",u=class{apiKey;environment;baseUrl;initPromise;snapshot=null;identifiedContext={};sync;constructor(t){this.apiKey=t.apiKey,this.environment=t.environment,this.baseUrl=t.baseUrl??f,this.initPromise=this.init(),this.sync={isEnabled:this.isEnabledSync.bind(this),get:this.getSync.bind(this)};}async init(){let t=await fetch(`${this.baseUrl}/sdk/init`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:this.apiKey})});if(!t.ok){let n=await t.json().catch(()=>({}));throw new Error(`Gradual: Failed to initialize - ${n.error??t.statusText}`)}let i=await t.json();if(!i.valid)throw new Error(`Gradual: Invalid API key - ${i.error??"Unknown error"}`);let r=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!r.ok){let n=await r.json().catch(()=>({}));throw new Error(`Gradual: Failed to fetch snapshot - ${n.error??r.statusText}`)}this.snapshot=await r.json();}ensureReady(){if(!this.snapshot)throw new Error("Gradual: SDK not ready. Use await ready() or async methods.");return this.snapshot}mergeContext(t){return {...this.identifiedContext,...t?.context}}evaluate(t,i){let r=this.ensureReady(),n=r.flags[t];if(n)return s(n,i,r.segments)}async ready(){await this.initPromise;}isReady(){return this.snapshot!==null}async isEnabled(t,i){await this.initPromise;let r=this.evaluate(t,this.mergeContext(i));return typeof r=="boolean"?r:false}async get(t,i){await this.initPromise;let r=this.evaluate(t,this.mergeContext(i));return r??i.fallback}isEnabledSync(t,i){let r=this.evaluate(t,this.mergeContext(i));return typeof r=="boolean"?r:false}getSync(t,i){let r=this.evaluate(t,this.mergeContext(i));return r??i.fallback}identify(t){this.identifiedContext={...t};}reset(){this.identifiedContext={};}async refresh(){let t=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!t.ok){let i=await t.json().catch(()=>({}));throw new Error(`Gradual: Failed to refresh - ${i.error??t.statusText}`)}this.snapshot=await t.json();}getSnapshot(){return this.snapshot}};function c(a){return new u(a)}
|
|
2
|
+
exports.createGradual=c;exports.evaluateFlag=s;//# sourceMappingURL=index.cjs.map
|
|
3
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/evaluator.ts","../src/client.ts"],"names":["evaluateCondition","condition","context","attributeKey","operator","value","contextValue","evaluateConditions","conditions","evaluateSegment","segment","evaluateTarget","target","segments","evaluateFlag","flag","sortedTargets","a","b","variation","DEFAULT_BASE_URL","GradualClient","options","initResponse","error","initData","snapshotResponse","key","snapshot","response","createGradual"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n EvaluationContext,\n SnapshotFlag,\n SnapshotRuleCondition,\n SnapshotSegment,\n SnapshotTarget,\n} from \"./types\";\n\nfunction evaluateCondition(\n condition: SnapshotRuleCondition,\n context: EvaluationContext\n): boolean {\n const { attributeKey, operator, value } = condition;\n const contextValue = context[attributeKey];\n\n switch (operator) {\n case \"equals\":\n return contextValue === value;\n\n case \"not_equals\":\n return contextValue !== value;\n\n case \"contains\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.includes(value);\n }\n if (Array.isArray(contextValue)) {\n return contextValue.includes(value);\n }\n return false;\n\n case \"not_contains\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return !contextValue.includes(value);\n }\n if (Array.isArray(contextValue)) {\n return !contextValue.includes(value);\n }\n return true;\n\n case \"starts_with\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.startsWith(value);\n }\n return false;\n\n case \"ends_with\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.endsWith(value);\n }\n return false;\n\n case \"greater_than\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue > value;\n }\n return false;\n\n case \"less_than\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue < value;\n }\n return false;\n\n case \"greater_than_or_equal\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue >= value;\n }\n return false;\n\n case \"less_than_or_equal\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue <= value;\n }\n return false;\n\n case \"in\":\n if (Array.isArray(value)) {\n return value.includes(contextValue);\n }\n return false;\n\n case \"not_in\":\n if (Array.isArray(value)) {\n return !value.includes(contextValue);\n }\n return true;\n\n case \"exists\":\n return contextValue !== undefined && contextValue !== null;\n\n case \"not_exists\":\n return contextValue === undefined || contextValue === null;\n\n default:\n return false;\n }\n}\n\nfunction evaluateConditions(\n conditions: SnapshotRuleCondition[],\n context: EvaluationContext\n): boolean {\n return conditions.every((condition) => evaluateCondition(condition, context));\n}\n\nfunction evaluateSegment(\n segment: SnapshotSegment,\n context: EvaluationContext\n): boolean {\n return evaluateConditions(segment.conditions, context);\n}\n\nfunction evaluateTarget(\n target: SnapshotTarget,\n context: EvaluationContext,\n segments: Record<string, SnapshotSegment>\n): boolean {\n switch (target.type) {\n case \"individual\":\n if (target.attributeKey && target.attributeValue !== undefined) {\n return context[target.attributeKey] === target.attributeValue;\n }\n return false;\n\n case \"rule\":\n if (target.conditions) {\n return evaluateConditions(target.conditions, context);\n }\n return false;\n\n case \"segment\":\n if (target.segmentKey) {\n const segment = segments[target.segmentKey];\n if (segment) {\n return evaluateSegment(segment, context);\n }\n }\n return false;\n\n default:\n return false;\n }\n}\n\nexport function evaluateFlag(\n flag: SnapshotFlag,\n context: EvaluationContext,\n segments: Record<string, SnapshotSegment>\n): unknown {\n if (!flag.enabled) {\n const offVariation = flag.variations[flag.offVariationKey];\n return offVariation?.value;\n }\n\n const sortedTargets = [...flag.targets].sort(\n (a, b) => a.sortOrder - b.sortOrder\n );\n\n for (const target of sortedTargets) {\n if (evaluateTarget(target, context, segments)) {\n const variation = flag.variations[target.variationKey];\n if (variation) {\n return variation.value;\n }\n }\n }\n\n const defaultVariation = flag.variations[flag.defaultVariationKey];\n return defaultVariation?.value;\n}\n","import { evaluateFlag } from \"./evaluator\";\nimport type {\n EnvironmentSnapshot,\n EvaluationContext,\n FlagOptions,\n GradualOptions,\n IsEnabledOptions,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://worker.gradual.so/api/v1\";\n\nexport interface Gradual {\n /** Wait for the SDK to be ready (snapshot fetched) */\n ready(): Promise<void>;\n\n /** Check if the SDK is ready for sync access */\n isReady(): boolean;\n\n /** Check if a boolean flag is enabled */\n isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean>;\n\n /** Get a flag value with type inference from fallback */\n get<T>(key: string, options: FlagOptions<T>): Promise<T>;\n\n /** Set persistent user context for all evaluations */\n identify(context: EvaluationContext): void;\n\n /** Clear the identified user context */\n reset(): void;\n\n /** Refresh the snapshot from the server */\n refresh(): Promise<void>;\n\n /** Get the current snapshot (for debugging) */\n getSnapshot(): EnvironmentSnapshot | null;\n\n /** Sync methods (throw if not ready) */\n sync: GradualSync;\n}\n\nexport interface GradualSync {\n /** Sync version of isEnabled (throws if not ready) */\n isEnabled(key: string, options?: IsEnabledOptions): boolean;\n\n /** Sync version of get (throws if not ready) */\n get<T>(key: string, options: FlagOptions<T>): T;\n}\n\nclass GradualClient implements Gradual {\n private readonly apiKey: string;\n private readonly environment: string;\n private readonly baseUrl: string;\n private readonly initPromise: Promise<void>;\n private snapshot: EnvironmentSnapshot | null = null;\n private identifiedContext: EvaluationContext = {};\n\n readonly sync: GradualSync;\n\n constructor(options: GradualOptions) {\n this.apiKey = options.apiKey;\n this.environment = options.environment;\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.initPromise = this.init();\n\n this.sync = {\n isEnabled: this.isEnabledSync.bind(this),\n get: this.getSync.bind(this),\n };\n }\n\n private async init(): Promise<void> {\n const initResponse = await fetch(`${this.baseUrl}/sdk/init`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ apiKey: this.apiKey }),\n });\n\n if (!initResponse.ok) {\n const error = await initResponse.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to initialize - ${(error as { error?: string }).error ?? initResponse.statusText}`\n );\n }\n\n const initData = (await initResponse.json()) as {\n valid: boolean;\n error?: string;\n };\n\n if (!initData.valid) {\n throw new Error(\n `Gradual: Invalid API key - ${initData.error ?? \"Unknown error\"}`\n );\n }\n\n const snapshotResponse = await fetch(\n `${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,\n { headers: { Authorization: `Bearer ${this.apiKey}` } }\n );\n\n if (!snapshotResponse.ok) {\n const error = await snapshotResponse.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to fetch snapshot - ${(error as { error?: string }).error ?? snapshotResponse.statusText}`\n );\n }\n\n this.snapshot = (await snapshotResponse.json()) as EnvironmentSnapshot;\n }\n\n private ensureReady(): EnvironmentSnapshot {\n if (!this.snapshot) {\n throw new Error(\n \"Gradual: SDK not ready. Use await ready() or async methods.\"\n );\n }\n return this.snapshot;\n }\n\n private mergeContext(options?: {\n context?: EvaluationContext;\n }): EvaluationContext {\n return { ...this.identifiedContext, ...options?.context };\n }\n\n private evaluate(key: string, context: EvaluationContext): unknown {\n const snapshot = this.ensureReady();\n const flag = snapshot.flags[key];\n if (!flag) {\n return undefined;\n }\n return evaluateFlag(flag, context, snapshot.segments);\n }\n\n async ready(): Promise<void> {\n await this.initPromise;\n }\n\n isReady(): boolean {\n return this.snapshot !== null;\n }\n\n async isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean> {\n await this.initPromise;\n const value = this.evaluate(key, this.mergeContext(options));\n return typeof value === \"boolean\" ? value : false;\n }\n\n async get<T>(key: string, options: FlagOptions<T>): Promise<T> {\n await this.initPromise;\n const value = this.evaluate(key, this.mergeContext(options));\n return value !== undefined && value !== null\n ? (value as T)\n : options.fallback;\n }\n\n private isEnabledSync(key: string, options?: IsEnabledOptions): boolean {\n const value = this.evaluate(key, this.mergeContext(options));\n return typeof value === \"boolean\" ? value : false;\n }\n\n private getSync<T>(key: string, options: FlagOptions<T>): T {\n const value = this.evaluate(key, this.mergeContext(options));\n return value !== undefined && value !== null\n ? (value as T)\n : options.fallback;\n }\n\n identify(context: EvaluationContext): void {\n this.identifiedContext = { ...context };\n }\n\n reset(): void {\n this.identifiedContext = {};\n }\n\n async refresh(): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,\n { headers: { Authorization: `Bearer ${this.apiKey}` } }\n );\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to refresh - ${(error as { error?: string }).error ?? response.statusText}`\n );\n }\n\n this.snapshot = (await response.json()) as EnvironmentSnapshot;\n }\n\n getSnapshot(): EnvironmentSnapshot | null {\n return this.snapshot;\n }\n}\n\n/**\n * Create a Gradual feature flag client\n *\n * @example\n * ```ts\n * const gradual = createGradual({\n * apiKey: 'gra_xxx',\n * environment: 'production'\n * })\n *\n * // Boolean flags\n * const enabled = await gradual.isEnabled('new-feature')\n *\n * // Typed values (inferred from fallback)\n * const theme = await gradual.get('theme', { fallback: 'dark' })\n *\n * // With user context\n * gradual.identify({ userId: '123', plan: 'pro' })\n * const proFeature = await gradual.isEnabled('pro-feature')\n * ```\n */\nexport function createGradual(options: GradualOptions): Gradual {\n return new GradualClient(options);\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
type TargetingOperator = "equals" | "not_equals" | "contains" | "not_contains" | "starts_with" | "ends_with" | "greater_than" | "less_than" | "greater_than_or_equal" | "less_than_or_equal" | "in" | "not_in" | "exists" | "not_exists";
|
|
2
|
+
interface SnapshotRuleCondition {
|
|
3
|
+
attributeKey: string;
|
|
4
|
+
operator: TargetingOperator;
|
|
5
|
+
value: unknown;
|
|
6
|
+
}
|
|
7
|
+
interface SnapshotSegment {
|
|
8
|
+
key: string;
|
|
9
|
+
conditions: SnapshotRuleCondition[];
|
|
10
|
+
}
|
|
11
|
+
interface SnapshotTarget {
|
|
12
|
+
type: "rule" | "individual" | "segment";
|
|
13
|
+
variationKey: string;
|
|
14
|
+
sortOrder: number;
|
|
15
|
+
conditions?: SnapshotRuleCondition[];
|
|
16
|
+
attributeKey?: string;
|
|
17
|
+
attributeValue?: string;
|
|
18
|
+
segmentKey?: string;
|
|
19
|
+
}
|
|
20
|
+
interface SnapshotVariation {
|
|
21
|
+
key: string;
|
|
22
|
+
value: unknown;
|
|
23
|
+
}
|
|
24
|
+
interface SnapshotFlag {
|
|
25
|
+
key: string;
|
|
26
|
+
type: "boolean" | "string" | "number" | "json";
|
|
27
|
+
enabled: boolean;
|
|
28
|
+
variations: Record<string, SnapshotVariation>;
|
|
29
|
+
defaultVariationKey: string;
|
|
30
|
+
offVariationKey: string;
|
|
31
|
+
targets: SnapshotTarget[];
|
|
32
|
+
}
|
|
33
|
+
interface EnvironmentSnapshot {
|
|
34
|
+
version: number;
|
|
35
|
+
generatedAt: string;
|
|
36
|
+
meta: {
|
|
37
|
+
projectId: string;
|
|
38
|
+
organizationId: string;
|
|
39
|
+
environmentSlug: string;
|
|
40
|
+
environmentId: string;
|
|
41
|
+
};
|
|
42
|
+
flags: Record<string, SnapshotFlag>;
|
|
43
|
+
segments: Record<string, SnapshotSegment>;
|
|
44
|
+
}
|
|
45
|
+
interface EvaluationContext {
|
|
46
|
+
[key: string]: unknown;
|
|
47
|
+
}
|
|
48
|
+
interface GradualOptions {
|
|
49
|
+
apiKey: string;
|
|
50
|
+
environment: string;
|
|
51
|
+
baseUrl?: string;
|
|
52
|
+
}
|
|
53
|
+
interface FlagOptions<T> {
|
|
54
|
+
fallback: T;
|
|
55
|
+
context?: EvaluationContext;
|
|
56
|
+
}
|
|
57
|
+
interface IsEnabledOptions {
|
|
58
|
+
context?: EvaluationContext;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface Gradual {
|
|
62
|
+
/** Wait for the SDK to be ready (snapshot fetched) */
|
|
63
|
+
ready(): Promise<void>;
|
|
64
|
+
/** Check if the SDK is ready for sync access */
|
|
65
|
+
isReady(): boolean;
|
|
66
|
+
/** Check if a boolean flag is enabled */
|
|
67
|
+
isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean>;
|
|
68
|
+
/** Get a flag value with type inference from fallback */
|
|
69
|
+
get<T>(key: string, options: FlagOptions<T>): Promise<T>;
|
|
70
|
+
/** Set persistent user context for all evaluations */
|
|
71
|
+
identify(context: EvaluationContext): void;
|
|
72
|
+
/** Clear the identified user context */
|
|
73
|
+
reset(): void;
|
|
74
|
+
/** Refresh the snapshot from the server */
|
|
75
|
+
refresh(): Promise<void>;
|
|
76
|
+
/** Get the current snapshot (for debugging) */
|
|
77
|
+
getSnapshot(): EnvironmentSnapshot | null;
|
|
78
|
+
/** Sync methods (throw if not ready) */
|
|
79
|
+
sync: GradualSync;
|
|
80
|
+
}
|
|
81
|
+
interface GradualSync {
|
|
82
|
+
/** Sync version of isEnabled (throws if not ready) */
|
|
83
|
+
isEnabled(key: string, options?: IsEnabledOptions): boolean;
|
|
84
|
+
/** Sync version of get (throws if not ready) */
|
|
85
|
+
get<T>(key: string, options: FlagOptions<T>): T;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Create a Gradual feature flag client
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* const gradual = createGradual({
|
|
93
|
+
* apiKey: 'gra_xxx',
|
|
94
|
+
* environment: 'production'
|
|
95
|
+
* })
|
|
96
|
+
*
|
|
97
|
+
* // Boolean flags
|
|
98
|
+
* const enabled = await gradual.isEnabled('new-feature')
|
|
99
|
+
*
|
|
100
|
+
* // Typed values (inferred from fallback)
|
|
101
|
+
* const theme = await gradual.get('theme', { fallback: 'dark' })
|
|
102
|
+
*
|
|
103
|
+
* // With user context
|
|
104
|
+
* gradual.identify({ userId: '123', plan: 'pro' })
|
|
105
|
+
* const proFeature = await gradual.isEnabled('pro-feature')
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
declare function createGradual(options: GradualOptions): Gradual;
|
|
109
|
+
|
|
110
|
+
declare function evaluateFlag(flag: SnapshotFlag, context: EvaluationContext, segments: Record<string, SnapshotSegment>): unknown;
|
|
111
|
+
|
|
112
|
+
export { type EnvironmentSnapshot, type EvaluationContext, type FlagOptions, type Gradual, type GradualOptions, type GradualSync, type IsEnabledOptions, type SnapshotFlag, type SnapshotRuleCondition, type SnapshotSegment, type SnapshotTarget, type SnapshotVariation, type TargetingOperator, createGradual, evaluateFlag };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
type TargetingOperator = "equals" | "not_equals" | "contains" | "not_contains" | "starts_with" | "ends_with" | "greater_than" | "less_than" | "greater_than_or_equal" | "less_than_or_equal" | "in" | "not_in" | "exists" | "not_exists";
|
|
2
|
+
interface SnapshotRuleCondition {
|
|
3
|
+
attributeKey: string;
|
|
4
|
+
operator: TargetingOperator;
|
|
5
|
+
value: unknown;
|
|
6
|
+
}
|
|
7
|
+
interface SnapshotSegment {
|
|
8
|
+
key: string;
|
|
9
|
+
conditions: SnapshotRuleCondition[];
|
|
10
|
+
}
|
|
11
|
+
interface SnapshotTarget {
|
|
12
|
+
type: "rule" | "individual" | "segment";
|
|
13
|
+
variationKey: string;
|
|
14
|
+
sortOrder: number;
|
|
15
|
+
conditions?: SnapshotRuleCondition[];
|
|
16
|
+
attributeKey?: string;
|
|
17
|
+
attributeValue?: string;
|
|
18
|
+
segmentKey?: string;
|
|
19
|
+
}
|
|
20
|
+
interface SnapshotVariation {
|
|
21
|
+
key: string;
|
|
22
|
+
value: unknown;
|
|
23
|
+
}
|
|
24
|
+
interface SnapshotFlag {
|
|
25
|
+
key: string;
|
|
26
|
+
type: "boolean" | "string" | "number" | "json";
|
|
27
|
+
enabled: boolean;
|
|
28
|
+
variations: Record<string, SnapshotVariation>;
|
|
29
|
+
defaultVariationKey: string;
|
|
30
|
+
offVariationKey: string;
|
|
31
|
+
targets: SnapshotTarget[];
|
|
32
|
+
}
|
|
33
|
+
interface EnvironmentSnapshot {
|
|
34
|
+
version: number;
|
|
35
|
+
generatedAt: string;
|
|
36
|
+
meta: {
|
|
37
|
+
projectId: string;
|
|
38
|
+
organizationId: string;
|
|
39
|
+
environmentSlug: string;
|
|
40
|
+
environmentId: string;
|
|
41
|
+
};
|
|
42
|
+
flags: Record<string, SnapshotFlag>;
|
|
43
|
+
segments: Record<string, SnapshotSegment>;
|
|
44
|
+
}
|
|
45
|
+
interface EvaluationContext {
|
|
46
|
+
[key: string]: unknown;
|
|
47
|
+
}
|
|
48
|
+
interface GradualOptions {
|
|
49
|
+
apiKey: string;
|
|
50
|
+
environment: string;
|
|
51
|
+
baseUrl?: string;
|
|
52
|
+
}
|
|
53
|
+
interface FlagOptions<T> {
|
|
54
|
+
fallback: T;
|
|
55
|
+
context?: EvaluationContext;
|
|
56
|
+
}
|
|
57
|
+
interface IsEnabledOptions {
|
|
58
|
+
context?: EvaluationContext;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface Gradual {
|
|
62
|
+
/** Wait for the SDK to be ready (snapshot fetched) */
|
|
63
|
+
ready(): Promise<void>;
|
|
64
|
+
/** Check if the SDK is ready for sync access */
|
|
65
|
+
isReady(): boolean;
|
|
66
|
+
/** Check if a boolean flag is enabled */
|
|
67
|
+
isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean>;
|
|
68
|
+
/** Get a flag value with type inference from fallback */
|
|
69
|
+
get<T>(key: string, options: FlagOptions<T>): Promise<T>;
|
|
70
|
+
/** Set persistent user context for all evaluations */
|
|
71
|
+
identify(context: EvaluationContext): void;
|
|
72
|
+
/** Clear the identified user context */
|
|
73
|
+
reset(): void;
|
|
74
|
+
/** Refresh the snapshot from the server */
|
|
75
|
+
refresh(): Promise<void>;
|
|
76
|
+
/** Get the current snapshot (for debugging) */
|
|
77
|
+
getSnapshot(): EnvironmentSnapshot | null;
|
|
78
|
+
/** Sync methods (throw if not ready) */
|
|
79
|
+
sync: GradualSync;
|
|
80
|
+
}
|
|
81
|
+
interface GradualSync {
|
|
82
|
+
/** Sync version of isEnabled (throws if not ready) */
|
|
83
|
+
isEnabled(key: string, options?: IsEnabledOptions): boolean;
|
|
84
|
+
/** Sync version of get (throws if not ready) */
|
|
85
|
+
get<T>(key: string, options: FlagOptions<T>): T;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Create a Gradual feature flag client
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* const gradual = createGradual({
|
|
93
|
+
* apiKey: 'gra_xxx',
|
|
94
|
+
* environment: 'production'
|
|
95
|
+
* })
|
|
96
|
+
*
|
|
97
|
+
* // Boolean flags
|
|
98
|
+
* const enabled = await gradual.isEnabled('new-feature')
|
|
99
|
+
*
|
|
100
|
+
* // Typed values (inferred from fallback)
|
|
101
|
+
* const theme = await gradual.get('theme', { fallback: 'dark' })
|
|
102
|
+
*
|
|
103
|
+
* // With user context
|
|
104
|
+
* gradual.identify({ userId: '123', plan: 'pro' })
|
|
105
|
+
* const proFeature = await gradual.isEnabled('pro-feature')
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
declare function createGradual(options: GradualOptions): Gradual;
|
|
109
|
+
|
|
110
|
+
declare function evaluateFlag(flag: SnapshotFlag, context: EvaluationContext, segments: Record<string, SnapshotSegment>): unknown;
|
|
111
|
+
|
|
112
|
+
export { type EnvironmentSnapshot, type EvaluationContext, type FlagOptions, type Gradual, type GradualOptions, type GradualSync, type IsEnabledOptions, type SnapshotFlag, type SnapshotRuleCondition, type SnapshotSegment, type SnapshotTarget, type SnapshotVariation, type TargetingOperator, createGradual, evaluateFlag };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
function d(a,t){let{attributeKey:i,operator:r,value:n}=a,e=t[i];switch(r){case "equals":return e===n;case "not_equals":return e!==n;case "contains":return typeof e=="string"&&typeof n=="string"||Array.isArray(e)?e.includes(n):false;case "not_contains":return typeof e=="string"&&typeof n=="string"||Array.isArray(e)?!e.includes(n):true;case "starts_with":return typeof e=="string"&&typeof n=="string"?e.startsWith(n):false;case "ends_with":return typeof e=="string"&&typeof n=="string"?e.endsWith(n):false;case "greater_than":return typeof e=="number"&&typeof n=="number"?e>n:false;case "less_than":return typeof e=="number"&&typeof n=="number"?e<n:false;case "greater_than_or_equal":return typeof e=="number"&&typeof n=="number"?e>=n:false;case "less_than_or_equal":return typeof e=="number"&&typeof n=="number"?e<=n:false;case "in":return Array.isArray(n)?n.includes(e):false;case "not_in":return Array.isArray(n)?!n.includes(e):true;case "exists":return e!=null;case "not_exists":return e==null;default:return false}}function l(a,t){return a.every(i=>d(i,t))}function p(a,t){return l(a.conditions,t)}function h(a,t,i){switch(a.type){case "individual":return a.attributeKey&&a.attributeValue!==void 0?t[a.attributeKey]===a.attributeValue:false;case "rule":return a.conditions?l(a.conditions,t):false;case "segment":if(a.segmentKey){let r=i[a.segmentKey];if(r)return p(r,t)}return false;default:return false}}function s(a,t,i){if(!a.enabled)return a.variations[a.offVariationKey]?.value;let r=[...a.targets].sort((e,o)=>e.sortOrder-o.sortOrder);for(let e of r)if(h(e,t,i)){let o=a.variations[e.variationKey];if(o)return o.value}return a.variations[a.defaultVariationKey]?.value}var f="https://worker.gradual.so/api/v1",u=class{apiKey;environment;baseUrl;initPromise;snapshot=null;identifiedContext={};sync;constructor(t){this.apiKey=t.apiKey,this.environment=t.environment,this.baseUrl=t.baseUrl??f,this.initPromise=this.init(),this.sync={isEnabled:this.isEnabledSync.bind(this),get:this.getSync.bind(this)};}async init(){let t=await fetch(`${this.baseUrl}/sdk/init`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:this.apiKey})});if(!t.ok){let n=await t.json().catch(()=>({}));throw new Error(`Gradual: Failed to initialize - ${n.error??t.statusText}`)}let i=await t.json();if(!i.valid)throw new Error(`Gradual: Invalid API key - ${i.error??"Unknown error"}`);let r=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!r.ok){let n=await r.json().catch(()=>({}));throw new Error(`Gradual: Failed to fetch snapshot - ${n.error??r.statusText}`)}this.snapshot=await r.json();}ensureReady(){if(!this.snapshot)throw new Error("Gradual: SDK not ready. Use await ready() or async methods.");return this.snapshot}mergeContext(t){return {...this.identifiedContext,...t?.context}}evaluate(t,i){let r=this.ensureReady(),n=r.flags[t];if(n)return s(n,i,r.segments)}async ready(){await this.initPromise;}isReady(){return this.snapshot!==null}async isEnabled(t,i){await this.initPromise;let r=this.evaluate(t,this.mergeContext(i));return typeof r=="boolean"?r:false}async get(t,i){await this.initPromise;let r=this.evaluate(t,this.mergeContext(i));return r??i.fallback}isEnabledSync(t,i){let r=this.evaluate(t,this.mergeContext(i));return typeof r=="boolean"?r:false}getSync(t,i){let r=this.evaluate(t,this.mergeContext(i));return r??i.fallback}identify(t){this.identifiedContext={...t};}reset(){this.identifiedContext={};}async refresh(){let t=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!t.ok){let i=await t.json().catch(()=>({}));throw new Error(`Gradual: Failed to refresh - ${i.error??t.statusText}`)}this.snapshot=await t.json();}getSnapshot(){return this.snapshot}};function c(a){return new u(a)}
|
|
2
|
+
export{c as createGradual,s as evaluateFlag};//# sourceMappingURL=index.js.map
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/evaluator.ts","../src/client.ts"],"names":["evaluateCondition","condition","context","attributeKey","operator","value","contextValue","evaluateConditions","conditions","evaluateSegment","segment","evaluateTarget","target","segments","evaluateFlag","flag","sortedTargets","a","b","variation","DEFAULT_BASE_URL","GradualClient","options","initResponse","error","initData","snapshotResponse","key","snapshot","response","createGradual"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n EvaluationContext,\n SnapshotFlag,\n SnapshotRuleCondition,\n SnapshotSegment,\n SnapshotTarget,\n} from \"./types\";\n\nfunction evaluateCondition(\n condition: SnapshotRuleCondition,\n context: EvaluationContext\n): boolean {\n const { attributeKey, operator, value } = condition;\n const contextValue = context[attributeKey];\n\n switch (operator) {\n case \"equals\":\n return contextValue === value;\n\n case \"not_equals\":\n return contextValue !== value;\n\n case \"contains\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.includes(value);\n }\n if (Array.isArray(contextValue)) {\n return contextValue.includes(value);\n }\n return false;\n\n case \"not_contains\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return !contextValue.includes(value);\n }\n if (Array.isArray(contextValue)) {\n return !contextValue.includes(value);\n }\n return true;\n\n case \"starts_with\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.startsWith(value);\n }\n return false;\n\n case \"ends_with\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.endsWith(value);\n }\n return false;\n\n case \"greater_than\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue > value;\n }\n return false;\n\n case \"less_than\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue < value;\n }\n return false;\n\n case \"greater_than_or_equal\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue >= value;\n }\n return false;\n\n case \"less_than_or_equal\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue <= value;\n }\n return false;\n\n case \"in\":\n if (Array.isArray(value)) {\n return value.includes(contextValue);\n }\n return false;\n\n case \"not_in\":\n if (Array.isArray(value)) {\n return !value.includes(contextValue);\n }\n return true;\n\n case \"exists\":\n return contextValue !== undefined && contextValue !== null;\n\n case \"not_exists\":\n return contextValue === undefined || contextValue === null;\n\n default:\n return false;\n }\n}\n\nfunction evaluateConditions(\n conditions: SnapshotRuleCondition[],\n context: EvaluationContext\n): boolean {\n return conditions.every((condition) => evaluateCondition(condition, context));\n}\n\nfunction evaluateSegment(\n segment: SnapshotSegment,\n context: EvaluationContext\n): boolean {\n return evaluateConditions(segment.conditions, context);\n}\n\nfunction evaluateTarget(\n target: SnapshotTarget,\n context: EvaluationContext,\n segments: Record<string, SnapshotSegment>\n): boolean {\n switch (target.type) {\n case \"individual\":\n if (target.attributeKey && target.attributeValue !== undefined) {\n return context[target.attributeKey] === target.attributeValue;\n }\n return false;\n\n case \"rule\":\n if (target.conditions) {\n return evaluateConditions(target.conditions, context);\n }\n return false;\n\n case \"segment\":\n if (target.segmentKey) {\n const segment = segments[target.segmentKey];\n if (segment) {\n return evaluateSegment(segment, context);\n }\n }\n return false;\n\n default:\n return false;\n }\n}\n\nexport function evaluateFlag(\n flag: SnapshotFlag,\n context: EvaluationContext,\n segments: Record<string, SnapshotSegment>\n): unknown {\n if (!flag.enabled) {\n const offVariation = flag.variations[flag.offVariationKey];\n return offVariation?.value;\n }\n\n const sortedTargets = [...flag.targets].sort(\n (a, b) => a.sortOrder - b.sortOrder\n );\n\n for (const target of sortedTargets) {\n if (evaluateTarget(target, context, segments)) {\n const variation = flag.variations[target.variationKey];\n if (variation) {\n return variation.value;\n }\n }\n }\n\n const defaultVariation = flag.variations[flag.defaultVariationKey];\n return defaultVariation?.value;\n}\n","import { evaluateFlag } from \"./evaluator\";\nimport type {\n EnvironmentSnapshot,\n EvaluationContext,\n FlagOptions,\n GradualOptions,\n IsEnabledOptions,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://worker.gradual.so/api/v1\";\n\nexport interface Gradual {\n /** Wait for the SDK to be ready (snapshot fetched) */\n ready(): Promise<void>;\n\n /** Check if the SDK is ready for sync access */\n isReady(): boolean;\n\n /** Check if a boolean flag is enabled */\n isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean>;\n\n /** Get a flag value with type inference from fallback */\n get<T>(key: string, options: FlagOptions<T>): Promise<T>;\n\n /** Set persistent user context for all evaluations */\n identify(context: EvaluationContext): void;\n\n /** Clear the identified user context */\n reset(): void;\n\n /** Refresh the snapshot from the server */\n refresh(): Promise<void>;\n\n /** Get the current snapshot (for debugging) */\n getSnapshot(): EnvironmentSnapshot | null;\n\n /** Sync methods (throw if not ready) */\n sync: GradualSync;\n}\n\nexport interface GradualSync {\n /** Sync version of isEnabled (throws if not ready) */\n isEnabled(key: string, options?: IsEnabledOptions): boolean;\n\n /** Sync version of get (throws if not ready) */\n get<T>(key: string, options: FlagOptions<T>): T;\n}\n\nclass GradualClient implements Gradual {\n private readonly apiKey: string;\n private readonly environment: string;\n private readonly baseUrl: string;\n private readonly initPromise: Promise<void>;\n private snapshot: EnvironmentSnapshot | null = null;\n private identifiedContext: EvaluationContext = {};\n\n readonly sync: GradualSync;\n\n constructor(options: GradualOptions) {\n this.apiKey = options.apiKey;\n this.environment = options.environment;\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.initPromise = this.init();\n\n this.sync = {\n isEnabled: this.isEnabledSync.bind(this),\n get: this.getSync.bind(this),\n };\n }\n\n private async init(): Promise<void> {\n const initResponse = await fetch(`${this.baseUrl}/sdk/init`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ apiKey: this.apiKey }),\n });\n\n if (!initResponse.ok) {\n const error = await initResponse.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to initialize - ${(error as { error?: string }).error ?? initResponse.statusText}`\n );\n }\n\n const initData = (await initResponse.json()) as {\n valid: boolean;\n error?: string;\n };\n\n if (!initData.valid) {\n throw new Error(\n `Gradual: Invalid API key - ${initData.error ?? \"Unknown error\"}`\n );\n }\n\n const snapshotResponse = await fetch(\n `${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,\n { headers: { Authorization: `Bearer ${this.apiKey}` } }\n );\n\n if (!snapshotResponse.ok) {\n const error = await snapshotResponse.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to fetch snapshot - ${(error as { error?: string }).error ?? snapshotResponse.statusText}`\n );\n }\n\n this.snapshot = (await snapshotResponse.json()) as EnvironmentSnapshot;\n }\n\n private ensureReady(): EnvironmentSnapshot {\n if (!this.snapshot) {\n throw new Error(\n \"Gradual: SDK not ready. Use await ready() or async methods.\"\n );\n }\n return this.snapshot;\n }\n\n private mergeContext(options?: {\n context?: EvaluationContext;\n }): EvaluationContext {\n return { ...this.identifiedContext, ...options?.context };\n }\n\n private evaluate(key: string, context: EvaluationContext): unknown {\n const snapshot = this.ensureReady();\n const flag = snapshot.flags[key];\n if (!flag) {\n return undefined;\n }\n return evaluateFlag(flag, context, snapshot.segments);\n }\n\n async ready(): Promise<void> {\n await this.initPromise;\n }\n\n isReady(): boolean {\n return this.snapshot !== null;\n }\n\n async isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean> {\n await this.initPromise;\n const value = this.evaluate(key, this.mergeContext(options));\n return typeof value === \"boolean\" ? value : false;\n }\n\n async get<T>(key: string, options: FlagOptions<T>): Promise<T> {\n await this.initPromise;\n const value = this.evaluate(key, this.mergeContext(options));\n return value !== undefined && value !== null\n ? (value as T)\n : options.fallback;\n }\n\n private isEnabledSync(key: string, options?: IsEnabledOptions): boolean {\n const value = this.evaluate(key, this.mergeContext(options));\n return typeof value === \"boolean\" ? value : false;\n }\n\n private getSync<T>(key: string, options: FlagOptions<T>): T {\n const value = this.evaluate(key, this.mergeContext(options));\n return value !== undefined && value !== null\n ? (value as T)\n : options.fallback;\n }\n\n identify(context: EvaluationContext): void {\n this.identifiedContext = { ...context };\n }\n\n reset(): void {\n this.identifiedContext = {};\n }\n\n async refresh(): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,\n { headers: { Authorization: `Bearer ${this.apiKey}` } }\n );\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to refresh - ${(error as { error?: string }).error ?? response.statusText}`\n );\n }\n\n this.snapshot = (await response.json()) as EnvironmentSnapshot;\n }\n\n getSnapshot(): EnvironmentSnapshot | null {\n return this.snapshot;\n }\n}\n\n/**\n * Create a Gradual feature flag client\n *\n * @example\n * ```ts\n * const gradual = createGradual({\n * apiKey: 'gra_xxx',\n * environment: 'production'\n * })\n *\n * // Boolean flags\n * const enabled = await gradual.isEnabled('new-feature')\n *\n * // Typed values (inferred from fallback)\n * const theme = await gradual.get('theme', { fallback: 'dark' })\n *\n * // With user context\n * gradual.identify({ userId: '123', plan: 'pro' })\n * const proFeature = await gradual.isEnabled('pro-feature')\n * ```\n */\nexport function createGradual(options: GradualOptions): Gradual {\n return new GradualClient(options);\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gradual-so/sdk",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Gradual feature flag SDK for TypeScript and JavaScript",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"keywords": [
|
|
27
|
+
"feature-flags",
|
|
28
|
+
"feature-toggles",
|
|
29
|
+
"gradual",
|
|
30
|
+
"sdk"
|
|
31
|
+
],
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/gradual-io/gradual",
|
|
35
|
+
"directory": "packages/sdk"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsup",
|
|
39
|
+
"clean": "git clean -xdf .cache .turbo dist node_modules",
|
|
40
|
+
"dev": "tsup --watch",
|
|
41
|
+
"typecheck": "tsc --noEmit --emitDeclarationOnly false"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@gradual/tsconfig": "workspace:*",
|
|
45
|
+
"tsup": "^8.5.1",
|
|
46
|
+
"typescript": "catalog:"
|
|
47
|
+
}
|
|
48
|
+
}
|