prompt-flags 0.1.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.
package/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # prompt-flags
2
+
3
+ AI-native feature flags for prompt variants and model selection. Deterministic bucketing via murmurhash3, targeting rules with 13 operators, and 4 flag types (`prompt`, `model`, `config`, `boolean`).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install prompt-flags
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { createClient, FlagConfiguration } from 'prompt-flags'
15
+
16
+ const config: FlagConfiguration = {
17
+ flags: [
18
+ {
19
+ key: 'system-prompt',
20
+ type: 'prompt',
21
+ enabled: true,
22
+ variants: [
23
+ { key: 'v1', value: 'You are a helpful assistant.' },
24
+ { key: 'v2', value: 'You are a concise assistant.' },
25
+ ],
26
+ defaultVariant: 'v1',
27
+ rules: [
28
+ {
29
+ conditions: [{ attribute: 'plan', operator: 'equals', value: 'pro' }],
30
+ serve: { variant: 'v2' },
31
+ },
32
+ ],
33
+ },
34
+ {
35
+ key: 'model-select',
36
+ type: 'model',
37
+ enabled: true,
38
+ variants: [
39
+ { key: 'fast', value: { model: 'gpt-3.5-turbo', temperature: 0.7 } },
40
+ { key: 'smart', value: { model: 'gpt-4o', temperature: 0.3 } },
41
+ ],
42
+ defaultVariant: 'fast',
43
+ rules: [
44
+ {
45
+ serve: { rollout: [{ variant: 'smart', weight: 20 }, { variant: 'fast', weight: 80 }] },
46
+ },
47
+ ],
48
+ },
49
+ {
50
+ key: 'new-ui',
51
+ type: 'boolean',
52
+ enabled: true,
53
+ variants: [
54
+ { key: 'on', value: true },
55
+ { key: 'off', value: false },
56
+ ],
57
+ defaultVariant: 'off',
58
+ },
59
+ ],
60
+ }
61
+
62
+ const client = createClient({ config })
63
+
64
+ const ctx = { key: 'user-123', plan: 'pro' }
65
+
66
+ // Prompt flag
67
+ const prompt = client.getPrompt('system-prompt', ctx) // 'You are a concise assistant.'
68
+
69
+ // Model flag (deterministic rollout)
70
+ const model = client.getModel('model-select', ctx) // { model: 'gpt-3.5-turbo', temperature: 0.7 }
71
+
72
+ // Boolean flag
73
+ const enabled = client.isEnabled('new-ui', ctx) // false
74
+ ```
75
+
76
+ ## Flag Types
77
+
78
+ | Type | Getter | Value type |
79
+ |-----------|----------------|--------------|
80
+ | `prompt` | `getPrompt` | `string` |
81
+ | `model` | `getModel` | `ModelConfig`|
82
+ | `config` | `getConfig<T>` | `T` |
83
+ | `boolean` | `isEnabled` | `boolean` |
84
+
85
+ ## Targeting Rules
86
+
87
+ Rules are evaluated in order. The first matching rule wins. All conditions within a rule use AND logic.
88
+
89
+ ### Supported operators
90
+
91
+ | Operator | Description |
92
+ |------------------------|--------------------------------------|
93
+ | `equals` | Strict string equality |
94
+ | `notEquals` | Strict string inequality |
95
+ | `in` | Value is in `values` array |
96
+ | `notIn` | Value is not in `values` array |
97
+ | `contains` | String contains substring |
98
+ | `startsWith` | String starts with value |
99
+ | `endsWith` | String ends with value |
100
+ | `greaterThan` | Numeric `>` |
101
+ | `lessThan` | Numeric `<` |
102
+ | `greaterThanOrEqual` | Numeric `>=` |
103
+ | `lessThanOrEqual` | Numeric `<=` |
104
+ | `matches` | Regex test (value is pattern string) |
105
+ | `exists` | Attribute is not null/undefined |
106
+ | `notExists` | Attribute is null/undefined |
107
+
108
+ Set `negate: true` on any condition to invert it.
109
+
110
+ ### Context attributes
111
+
112
+ Built-in: `key`, `plan`, `region`, `email`, `role`.
113
+ Custom attributes: prefix with `custom.` (e.g., `custom.betaTester`).
114
+
115
+ ## Percentage Rollouts
116
+
117
+ ```typescript
118
+ rules: [
119
+ {
120
+ serve: {
121
+ rollout: [
122
+ { variant: 'treatment', weight: 20 },
123
+ { variant: 'control', weight: 80 },
124
+ ],
125
+ },
126
+ },
127
+ ]
128
+ ```
129
+
130
+ Weights are percentages (sum to 100). Bucketing is deterministic: the same `ctx.key` always resolves to the same variant for a given flag.
131
+
132
+ ## Test Overrides
133
+
134
+ ```typescript
135
+ client.overrideForTest('new-ui', 'on')
136
+ client.isEnabled('new-ui', ctx) // true, reason: 'override'
137
+
138
+ client.clearOverride('new-ui')
139
+ client.clearAllOverrides()
140
+ ```
141
+
142
+ ## Callbacks
143
+
144
+ ```typescript
145
+ const client = createClient({
146
+ config,
147
+ onEvaluation: (result) => console.log(result),
148
+ onError: (err) => console.error(err),
149
+ })
150
+ ```
151
+
152
+ ## License
153
+
154
+ MIT
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/client.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,313 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const client_1 = require("../client");
5
+ const errors_1 = require("../errors");
6
+ const baseCtx = { key: 'user-abc' };
7
+ const config = {
8
+ flags: [
9
+ // Boolean flag
10
+ {
11
+ key: 'feature-x',
12
+ type: 'boolean',
13
+ enabled: true,
14
+ variants: [
15
+ { key: 'on', value: true },
16
+ { key: 'off', value: false },
17
+ ],
18
+ defaultVariant: 'off',
19
+ },
20
+ // Boolean flag that is disabled at the flag level
21
+ {
22
+ key: 'feature-disabled',
23
+ type: 'boolean',
24
+ enabled: false,
25
+ variants: [
26
+ { key: 'on', value: true },
27
+ { key: 'off', value: false },
28
+ ],
29
+ defaultVariant: 'off',
30
+ },
31
+ // Prompt flag
32
+ {
33
+ key: 'system-prompt',
34
+ type: 'prompt',
35
+ enabled: true,
36
+ variants: [
37
+ { key: 'v1', value: 'You are a helpful assistant.' },
38
+ { key: 'v2', value: 'You are a concise assistant.' },
39
+ ],
40
+ defaultVariant: 'v1',
41
+ },
42
+ // Model flag
43
+ {
44
+ key: 'model-select',
45
+ type: 'model',
46
+ enabled: true,
47
+ variants: [
48
+ { key: 'fast', value: { model: 'gpt-3.5-turbo', temperature: 0.7 } },
49
+ { key: 'smart', value: { model: 'gpt-4o', temperature: 0.3 } },
50
+ ],
51
+ defaultVariant: 'fast',
52
+ },
53
+ // Config flag
54
+ {
55
+ key: 'rate-limit',
56
+ type: 'config',
57
+ enabled: true,
58
+ variants: [
59
+ { key: 'low', value: { rpm: 10 } },
60
+ { key: 'high', value: { rpm: 100 } },
61
+ ],
62
+ defaultVariant: 'low',
63
+ },
64
+ // Boolean flag with equals targeting rule
65
+ {
66
+ key: 'pro-feature',
67
+ type: 'boolean',
68
+ enabled: true,
69
+ variants: [
70
+ { key: 'on', value: true },
71
+ { key: 'off', value: false },
72
+ ],
73
+ defaultVariant: 'off',
74
+ rules: [
75
+ {
76
+ conditions: [{ attribute: 'plan', operator: 'equals', value: 'pro' }],
77
+ serve: { variant: 'on' },
78
+ },
79
+ ],
80
+ },
81
+ // Boolean flag with 'in' targeting rule
82
+ {
83
+ key: 'beta-feature',
84
+ type: 'boolean',
85
+ enabled: true,
86
+ variants: [
87
+ { key: 'on', value: true },
88
+ { key: 'off', value: false },
89
+ ],
90
+ defaultVariant: 'off',
91
+ rules: [
92
+ {
93
+ conditions: [
94
+ { attribute: 'plan', operator: 'in', values: ['beta', 'enterprise'] },
95
+ ],
96
+ serve: { variant: 'on' },
97
+ },
98
+ ],
99
+ },
100
+ // Rollout flag (50/50)
101
+ {
102
+ key: 'rollout-flag',
103
+ type: 'boolean',
104
+ enabled: true,
105
+ variants: [
106
+ { key: 'on', value: true },
107
+ { key: 'off', value: false },
108
+ ],
109
+ defaultVariant: 'off',
110
+ rules: [
111
+ {
112
+ serve: {
113
+ rollout: [
114
+ { variant: 'on', weight: 50 },
115
+ { variant: 'off', weight: 50 },
116
+ ],
117
+ },
118
+ },
119
+ ],
120
+ },
121
+ // Prompt flag with contains condition
122
+ {
123
+ key: 'email-prompt',
124
+ type: 'prompt',
125
+ enabled: true,
126
+ variants: [
127
+ { key: 'enterprise', value: 'Enterprise prompt.' },
128
+ { key: 'default', value: 'Default prompt.' },
129
+ ],
130
+ defaultVariant: 'default',
131
+ rules: [
132
+ {
133
+ conditions: [{ attribute: 'email', operator: 'endsWith', value: '@corp.com' }],
134
+ serve: { variant: 'enterprise' },
135
+ },
136
+ ],
137
+ },
138
+ ],
139
+ };
140
+ (0, vitest_1.describe)('createClient', () => {
141
+ let client;
142
+ (0, vitest_1.beforeEach)(() => {
143
+ client = (0, client_1.createClient)({ config });
144
+ });
145
+ (0, vitest_1.describe)('boolean flag: isEnabled', () => {
146
+ (0, vitest_1.it)('returns false for default off variant', () => {
147
+ (0, vitest_1.expect)(client.isEnabled('feature-x', baseCtx)).toBe(false);
148
+ });
149
+ (0, vitest_1.it)('returns false when flag is disabled (reason: disabled)', () => {
150
+ (0, vitest_1.expect)(client.isEnabled('feature-disabled', baseCtx)).toBe(false);
151
+ });
152
+ (0, vitest_1.it)('evaluate returns reason=disabled when flag.enabled=false', () => {
153
+ const result = client.evaluate('feature-disabled', baseCtx);
154
+ (0, vitest_1.expect)(result.reason).toBe('disabled');
155
+ (0, vitest_1.expect)(result.flagEnabled).toBe(false);
156
+ });
157
+ });
158
+ (0, vitest_1.describe)('prompt flag: getPrompt', () => {
159
+ (0, vitest_1.it)('returns default variant string', () => {
160
+ const prompt = client.getPrompt('system-prompt', baseCtx);
161
+ (0, vitest_1.expect)(prompt).toBe('You are a helpful assistant.');
162
+ });
163
+ (0, vitest_1.it)('throws FlagTypeMismatchError when called on a boolean flag', () => {
164
+ (0, vitest_1.expect)(() => client.getPrompt('feature-x', baseCtx)).toThrow(errors_1.FlagTypeMismatchError);
165
+ });
166
+ });
167
+ (0, vitest_1.describe)('model flag: getModel', () => {
168
+ (0, vitest_1.it)('returns default ModelConfig', () => {
169
+ const model = client.getModel('model-select', baseCtx);
170
+ (0, vitest_1.expect)(model).toEqual({ model: 'gpt-3.5-turbo', temperature: 0.7 });
171
+ });
172
+ (0, vitest_1.it)('throws FlagTypeMismatchError when called on a boolean flag', () => {
173
+ (0, vitest_1.expect)(() => client.getModel('feature-x', baseCtx)).toThrow(errors_1.FlagTypeMismatchError);
174
+ });
175
+ });
176
+ (0, vitest_1.describe)('config flag: getConfig', () => {
177
+ (0, vitest_1.it)('returns typed config value', () => {
178
+ const cfg = client.getConfig('rate-limit', baseCtx);
179
+ (0, vitest_1.expect)(cfg.rpm).toBe(10);
180
+ });
181
+ });
182
+ (0, vitest_1.describe)('targeting rules: equals condition', () => {
183
+ (0, vitest_1.it)('matches pro plan user and enables feature', () => {
184
+ const proCtx = { key: 'user-pro', plan: 'pro' };
185
+ (0, vitest_1.expect)(client.isEnabled('pro-feature', proCtx)).toBe(true);
186
+ });
187
+ (0, vitest_1.it)('does not match free plan user', () => {
188
+ const freeCtx = { key: 'user-free', plan: 'free' };
189
+ (0, vitest_1.expect)(client.isEnabled('pro-feature', freeCtx)).toBe(false);
190
+ });
191
+ (0, vitest_1.it)('evaluate returns reason=rule_match for matching rule', () => {
192
+ const proCtx = { key: 'user-pro', plan: 'pro' };
193
+ const result = client.evaluate('pro-feature', proCtx);
194
+ (0, vitest_1.expect)(result.reason).toBe('rule_match');
195
+ (0, vitest_1.expect)(result.variantKey).toBe('on');
196
+ });
197
+ });
198
+ (0, vitest_1.describe)('targeting rules: in condition', () => {
199
+ (0, vitest_1.it)('matches beta plan user', () => {
200
+ const betaCtx = { key: 'user-beta', plan: 'beta' };
201
+ (0, vitest_1.expect)(client.isEnabled('beta-feature', betaCtx)).toBe(true);
202
+ });
203
+ (0, vitest_1.it)('matches enterprise plan user', () => {
204
+ const entCtx = { key: 'user-ent', plan: 'enterprise' };
205
+ (0, vitest_1.expect)(client.isEnabled('beta-feature', entCtx)).toBe(true);
206
+ });
207
+ (0, vitest_1.it)('does not match free plan user', () => {
208
+ const freeCtx = { key: 'user-free', plan: 'free' };
209
+ (0, vitest_1.expect)(client.isEnabled('beta-feature', freeCtx)).toBe(false);
210
+ });
211
+ });
212
+ (0, vitest_1.describe)('targeting rules: endsWith condition', () => {
213
+ (0, vitest_1.it)('returns enterprise prompt for corp email', () => {
214
+ const ctx = { key: 'u1', email: 'alice@corp.com' };
215
+ (0, vitest_1.expect)(client.getPrompt('email-prompt', ctx)).toBe('Enterprise prompt.');
216
+ });
217
+ (0, vitest_1.it)('returns default prompt for non-corp email', () => {
218
+ const ctx = { key: 'u2', email: 'bob@gmail.com' };
219
+ (0, vitest_1.expect)(client.getPrompt('email-prompt', ctx)).toBe('Default prompt.');
220
+ });
221
+ });
222
+ (0, vitest_1.describe)('rollout: deterministic bucketing', () => {
223
+ (0, vitest_1.it)('same context key always returns the same variant', () => {
224
+ const ctx = { key: 'stable-user' };
225
+ const first = client.evaluate('rollout-flag', ctx);
226
+ const second = client.evaluate('rollout-flag', ctx);
227
+ (0, vitest_1.expect)(first.variantKey).toBe(second.variantKey);
228
+ });
229
+ (0, vitest_1.it)('distributes roughly 50/50 across many users', () => {
230
+ let onCount = 0;
231
+ const total = 1000;
232
+ for (let i = 0; i < total; i++) {
233
+ const ctx = { key: `user-${i}` };
234
+ const result = client.evaluate('rollout-flag', ctx);
235
+ if (result.variantKey === 'on')
236
+ onCount++;
237
+ }
238
+ // Expect between 40% and 60% (deterministic hash, not truly random)
239
+ (0, vitest_1.expect)(onCount).toBeGreaterThan(350);
240
+ (0, vitest_1.expect)(onCount).toBeLessThan(650);
241
+ });
242
+ });
243
+ (0, vitest_1.describe)('test overrides', () => {
244
+ (0, vitest_1.it)('overrideForTest forces a specific variant', () => {
245
+ client.overrideForTest('feature-x', 'on');
246
+ (0, vitest_1.expect)(client.isEnabled('feature-x', baseCtx)).toBe(true);
247
+ const result = client.evaluate('feature-x', baseCtx);
248
+ (0, vitest_1.expect)(result.reason).toBe('override');
249
+ });
250
+ (0, vitest_1.it)('clearOverride removes the override', () => {
251
+ client.overrideForTest('feature-x', 'on');
252
+ client.clearOverride('feature-x');
253
+ (0, vitest_1.expect)(client.isEnabled('feature-x', baseCtx)).toBe(false);
254
+ });
255
+ (0, vitest_1.it)('clearAllOverrides removes all overrides', () => {
256
+ client.overrideForTest('feature-x', 'on');
257
+ client.overrideForTest('feature-disabled', 'on');
258
+ client.clearAllOverrides();
259
+ (0, vitest_1.expect)(client.isEnabled('feature-x', baseCtx)).toBe(false);
260
+ });
261
+ });
262
+ (0, vitest_1.describe)('error cases', () => {
263
+ (0, vitest_1.it)('throws FlagNotFoundError for unknown flag key', () => {
264
+ (0, vitest_1.expect)(() => client.evaluate('nonexistent', baseCtx)).toThrow(errors_1.FlagNotFoundError);
265
+ });
266
+ (0, vitest_1.it)('FlagNotFoundError has the correct flagKey', () => {
267
+ try {
268
+ client.evaluate('nonexistent', baseCtx);
269
+ vitest_1.expect.fail('should have thrown');
270
+ }
271
+ catch (err) {
272
+ (0, vitest_1.expect)(err).toBeInstanceOf(errors_1.FlagNotFoundError);
273
+ (0, vitest_1.expect)(err.flagKey).toBe('nonexistent');
274
+ }
275
+ });
276
+ (0, vitest_1.it)('FlagTypeMismatchError has the correct code', () => {
277
+ try {
278
+ client.getPrompt('feature-x', baseCtx);
279
+ vitest_1.expect.fail('should have thrown');
280
+ }
281
+ catch (err) {
282
+ (0, vitest_1.expect)(err).toBeInstanceOf(errors_1.FlagTypeMismatchError);
283
+ (0, vitest_1.expect)(err.code).toBe('FLAG_TYPE_MISMATCH');
284
+ }
285
+ });
286
+ });
287
+ (0, vitest_1.describe)('utility methods', () => {
288
+ (0, vitest_1.it)('getFlagKeys returns all flag keys', () => {
289
+ const keys = client.getFlagKeys();
290
+ (0, vitest_1.expect)(keys).toContain('feature-x');
291
+ (0, vitest_1.expect)(keys).toContain('system-prompt');
292
+ (0, vitest_1.expect)(keys.length).toBe(config.flags.length);
293
+ });
294
+ (0, vitest_1.it)('getFlag returns FlagDefinition for known key', () => {
295
+ const flag = client.getFlag('feature-x');
296
+ (0, vitest_1.expect)(flag).not.toBeNull();
297
+ (0, vitest_1.expect)(flag.type).toBe('boolean');
298
+ });
299
+ (0, vitest_1.it)('getFlag returns null for unknown key', () => {
300
+ (0, vitest_1.expect)(client.getFlag('nope')).toBeNull();
301
+ });
302
+ });
303
+ (0, vitest_1.describe)('onEvaluation callback', () => {
304
+ (0, vitest_1.it)('calls onEvaluation with the result', () => {
305
+ const cb = vitest_1.vi.fn();
306
+ const c = (0, client_1.createClient)({ config, onEvaluation: cb });
307
+ c.isEnabled('feature-x', baseCtx);
308
+ (0, vitest_1.expect)(cb).toHaveBeenCalledOnce();
309
+ (0, vitest_1.expect)(cb.mock.calls[0][0].flagKey).toBe('feature-x');
310
+ });
311
+ });
312
+ });
313
+ //# sourceMappingURL=client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.test.js","sourceRoot":"","sources":["../../src/__tests__/client.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function getBucket(contextKey: string, flagKey: string): number;
2
+ export declare function selectVariantByRollout(rollout: Array<{
3
+ variant: string;
4
+ weight: number;
5
+ }>, bucket: number): string;
6
+ //# sourceMappingURL=bucket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bucket.d.ts","sourceRoot":"","sources":["../src/bucket.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGrE;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EACnD,MAAM,EAAE,MAAM,GACb,MAAM,CAQR"}
package/dist/bucket.js ADDED
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getBucket = getBucket;
7
+ exports.selectVariantByRollout = selectVariantByRollout;
8
+ const murmurhash3js_1 = __importDefault(require("murmurhash3js"));
9
+ function getBucket(contextKey, flagKey) {
10
+ const hash = murmurhash3js_1.default.x86.hash32(`${contextKey}:${flagKey}`, 0);
11
+ return Math.abs(hash) % 10000;
12
+ }
13
+ function selectVariantByRollout(rollout, bucket) {
14
+ const total = rollout.reduce((s, r) => s + r.weight, 0);
15
+ let cumulative = 0;
16
+ for (const r of rollout) {
17
+ cumulative += (r.weight / total) * 10000;
18
+ if (bucket < cumulative)
19
+ return r.variant;
20
+ }
21
+ return rollout[rollout.length - 1].variant;
22
+ }
23
+ //# sourceMappingURL=bucket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bucket.js","sourceRoot":"","sources":["../src/bucket.ts"],"names":[],"mappings":";;;;;AAEA,8BAGC;AAED,wDAWC;AAlBD,kEAAkC;AAElC,SAAgB,SAAS,CAAC,UAAkB,EAAE,OAAe;IAC3D,MAAM,IAAI,GAAG,uBAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,UAAU,IAAI,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;IAC7D,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;AAC/B,CAAC;AAED,SAAgB,sBAAsB,CACpC,OAAmD,EACnD,MAAc;IAEd,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IACvD,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,UAAU,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,KAAK,CAAC,GAAG,KAAK,CAAA;QACxC,IAAI,MAAM,GAAG,UAAU;YAAE,OAAO,CAAC,CAAC,OAAO,CAAA;IAC3C,CAAC;IACD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,OAAO,CAAA;AAC5C,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { FlagClient, FlagClientConfig } from './types';
2
+ export declare function createClient(config: FlagClientConfig): FlagClient;
3
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,gBAAgB,EAKjB,MAAM,SAAS,CAAA;AAIhB,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CAwFjE"}
package/dist/client.js ADDED
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createClient = createClient;
4
+ const errors_1 = require("./errors");
5
+ const evaluate_1 = require("./evaluate");
6
+ function createClient(config) {
7
+ const flagMap = new Map();
8
+ const overrides = new Map();
9
+ for (const flag of config.config.flags) {
10
+ flagMap.set(flag.key, flag);
11
+ }
12
+ function resolveFlag(key) {
13
+ const flag = flagMap.get(key);
14
+ if (!flag)
15
+ throw new errors_1.FlagNotFoundError(key);
16
+ return flag;
17
+ }
18
+ function runEvaluate(key, ctx) {
19
+ const flag = resolveFlag(key);
20
+ const mergedCtx = { ...config.defaultContext, ...ctx };
21
+ const result = (0, evaluate_1.evaluate)(flag, mergedCtx, overrides);
22
+ config.onEvaluation?.(result);
23
+ return result;
24
+ }
25
+ return {
26
+ evaluate(key, ctx) {
27
+ try {
28
+ return runEvaluate(key, ctx);
29
+ }
30
+ catch (err) {
31
+ config.onError?.(err);
32
+ throw err;
33
+ }
34
+ },
35
+ getPrompt(key, ctx) {
36
+ const flag = resolveFlag(key);
37
+ if (flag.type !== 'prompt') {
38
+ throw new errors_1.FlagTypeMismatchError(key, 'prompt', flag.type);
39
+ }
40
+ const result = runEvaluate(key, ctx);
41
+ return result.value;
42
+ },
43
+ getModel(key, ctx) {
44
+ const flag = resolveFlag(key);
45
+ if (flag.type !== 'model') {
46
+ throw new errors_1.FlagTypeMismatchError(key, 'model', flag.type);
47
+ }
48
+ const result = runEvaluate(key, ctx);
49
+ return result.value;
50
+ },
51
+ getConfig(key, ctx) {
52
+ const flag = resolveFlag(key);
53
+ if (flag.type !== 'config') {
54
+ throw new errors_1.FlagTypeMismatchError(key, 'config', flag.type);
55
+ }
56
+ const result = runEvaluate(key, ctx);
57
+ return result.value;
58
+ },
59
+ isEnabled(key, ctx) {
60
+ const flag = resolveFlag(key);
61
+ if (flag.type !== 'boolean') {
62
+ throw new errors_1.FlagTypeMismatchError(key, 'boolean', flag.type);
63
+ }
64
+ const result = runEvaluate(key, ctx);
65
+ return result.value;
66
+ },
67
+ getFlagKeys() {
68
+ return Array.from(flagMap.keys());
69
+ },
70
+ getFlag(key) {
71
+ return flagMap.get(key) ?? null;
72
+ },
73
+ overrideForTest(key, variantKey) {
74
+ overrides.set(key, variantKey);
75
+ },
76
+ clearOverride(key) {
77
+ overrides.delete(key);
78
+ },
79
+ clearAllOverrides() {
80
+ overrides.clear();
81
+ },
82
+ };
83
+ }
84
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { EvaluationContext, RuleCondition, TargetingRule } from './types';
2
+ export declare function getAttributeValue(ctx: EvaluationContext, attribute: string): unknown;
3
+ export declare function evaluateCondition(ctx: EvaluationContext, condition: RuleCondition): boolean;
4
+ export declare function evaluateRule(ctx: EvaluationContext, rule: TargetingRule): boolean;
5
+ //# sourceMappingURL=conditions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditions.d.ts","sourceRoot":"","sources":["../src/conditions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAEzE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAapF;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,GAAG,OAAO,CAsD3F;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,iBAAiB,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAGjF"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAttributeValue = getAttributeValue;
4
+ exports.evaluateCondition = evaluateCondition;
5
+ exports.evaluateRule = evaluateRule;
6
+ function getAttributeValue(ctx, attribute) {
7
+ if (attribute.startsWith('custom.')) {
8
+ const subKey = attribute.slice('custom.'.length);
9
+ return ctx.custom?.[subKey];
10
+ }
11
+ switch (attribute) {
12
+ case 'key': return ctx.key;
13
+ case 'plan': return ctx.plan;
14
+ case 'region': return ctx.region;
15
+ case 'email': return ctx.email;
16
+ case 'role': return ctx.role;
17
+ default: return undefined;
18
+ }
19
+ }
20
+ function evaluateCondition(ctx, condition) {
21
+ const attrValue = getAttributeValue(ctx, condition.attribute);
22
+ const { operator, value, values, negate } = condition;
23
+ let result;
24
+ switch (operator) {
25
+ case 'equals':
26
+ result = String(attrValue) === String(value);
27
+ break;
28
+ case 'notEquals':
29
+ result = String(attrValue) !== String(value);
30
+ break;
31
+ case 'in':
32
+ result = (values ?? []).map(String).includes(String(attrValue));
33
+ break;
34
+ case 'notIn':
35
+ result = !(values ?? []).map(String).includes(String(attrValue));
36
+ break;
37
+ case 'contains':
38
+ result = typeof attrValue === 'string' && attrValue.includes(String(value));
39
+ break;
40
+ case 'startsWith':
41
+ result = typeof attrValue === 'string' && attrValue.startsWith(String(value));
42
+ break;
43
+ case 'endsWith':
44
+ result = typeof attrValue === 'string' && attrValue.endsWith(String(value));
45
+ break;
46
+ case 'greaterThan':
47
+ result = Number(attrValue) > Number(value);
48
+ break;
49
+ case 'lessThan':
50
+ result = Number(attrValue) < Number(value);
51
+ break;
52
+ case 'greaterThanOrEqual':
53
+ result = Number(attrValue) >= Number(value);
54
+ break;
55
+ case 'lessThanOrEqual':
56
+ result = Number(attrValue) <= Number(value);
57
+ break;
58
+ case 'matches':
59
+ result = typeof attrValue === 'string' && new RegExp(String(value)).test(attrValue);
60
+ break;
61
+ case 'exists':
62
+ result = attrValue !== undefined && attrValue !== null;
63
+ break;
64
+ case 'notExists':
65
+ result = attrValue === undefined || attrValue === null;
66
+ break;
67
+ default:
68
+ result = false;
69
+ }
70
+ return negate === true ? !result : result;
71
+ }
72
+ function evaluateRule(ctx, rule) {
73
+ if (!rule.conditions || rule.conditions.length === 0)
74
+ return true;
75
+ return rule.conditions.every((cond) => evaluateCondition(ctx, cond));
76
+ }
77
+ //# sourceMappingURL=conditions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditions.js","sourceRoot":"","sources":["../src/conditions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export declare class FlagError extends Error {
2
+ readonly code: string;
3
+ constructor(msg: string, code: string);
4
+ }
5
+ export declare class FlagNotFoundError extends FlagError {
6
+ readonly flagKey: string;
7
+ constructor(flagKey: string);
8
+ }
9
+ export declare class FlagTypeMismatchError extends FlagError {
10
+ readonly flagKey: string;
11
+ constructor(flagKey: string, expected: string, actual: string);
12
+ }
13
+ export declare class VariantNotFoundError extends FlagError {
14
+ readonly flagKey: string;
15
+ constructor(flagKey: string, variantKey: string);
16
+ }
17
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAU,SAAQ,KAAK;IACT,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAAlC,GAAG,EAAE,MAAM,EAAW,IAAI,EAAE,MAAM;CAI/C;AAED,qBAAa,iBAAkB,SAAQ,SAAS;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM;gBAAf,OAAO,EAAE,MAAM;CAIrC;AAED,qBAAa,qBAAsB,SAAQ,SAAS;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM;gBAAf,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAIvE;AAED,qBAAa,oBAAqB,SAAQ,SAAS;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM;gBAAf,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAIzD"}
package/dist/errors.js ADDED
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VariantNotFoundError = exports.FlagTypeMismatchError = exports.FlagNotFoundError = exports.FlagError = void 0;
4
+ class FlagError extends Error {
5
+ code;
6
+ constructor(msg, code) {
7
+ super(msg);
8
+ this.code = code;
9
+ this.name = 'FlagError';
10
+ }
11
+ }
12
+ exports.FlagError = FlagError;
13
+ class FlagNotFoundError extends FlagError {
14
+ flagKey;
15
+ constructor(flagKey) {
16
+ super(`Flag not found: "${flagKey}"`, 'FLAG_NOT_FOUND');
17
+ this.flagKey = flagKey;
18
+ this.name = 'FlagNotFoundError';
19
+ }
20
+ }
21
+ exports.FlagNotFoundError = FlagNotFoundError;
22
+ class FlagTypeMismatchError extends FlagError {
23
+ flagKey;
24
+ constructor(flagKey, expected, actual) {
25
+ super(`Type mismatch for "${flagKey}": expected ${expected}, got ${actual}`, 'FLAG_TYPE_MISMATCH');
26
+ this.flagKey = flagKey;
27
+ this.name = 'FlagTypeMismatchError';
28
+ }
29
+ }
30
+ exports.FlagTypeMismatchError = FlagTypeMismatchError;
31
+ class VariantNotFoundError extends FlagError {
32
+ flagKey;
33
+ constructor(flagKey, variantKey) {
34
+ super(`Variant "${variantKey}" not found in flag "${flagKey}"`, 'VARIANT_NOT_FOUND');
35
+ this.flagKey = flagKey;
36
+ this.name = 'VariantNotFoundError';
37
+ }
38
+ }
39
+ exports.VariantNotFoundError = VariantNotFoundError;
40
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAAA,MAAa,SAAU,SAAQ,KAAK;IACA;IAAlC,YAAY,GAAW,EAAW,IAAY;QAC5C,KAAK,CAAC,GAAG,CAAC,CAAA;QADsB,SAAI,GAAJ,IAAI,CAAQ;QAE5C,IAAI,CAAC,IAAI,GAAG,WAAW,CAAA;IACzB,CAAC;CACF;AALD,8BAKC;AAED,MAAa,iBAAkB,SAAQ,SAAS;IACzB;IAArB,YAAqB,OAAe;QAClC,KAAK,CAAC,oBAAoB,OAAO,GAAG,EAAE,gBAAgB,CAAC,CAAA;QADpC,YAAO,GAAP,OAAO,CAAQ;QAElC,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAA;IACjC,CAAC;CACF;AALD,8CAKC;AAED,MAAa,qBAAsB,SAAQ,SAAS;IAC7B;IAArB,YAAqB,OAAe,EAAE,QAAgB,EAAE,MAAc;QACpE,KAAK,CAAC,sBAAsB,OAAO,eAAe,QAAQ,SAAS,MAAM,EAAE,EAAE,oBAAoB,CAAC,CAAA;QAD/E,YAAO,GAAP,OAAO,CAAQ;QAElC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAA;IACrC,CAAC;CACF;AALD,sDAKC;AAED,MAAa,oBAAqB,SAAQ,SAAS;IAC5B;IAArB,YAAqB,OAAe,EAAE,UAAkB;QACtD,KAAK,CAAC,YAAY,UAAU,wBAAwB,OAAO,GAAG,EAAE,mBAAmB,CAAC,CAAA;QADjE,YAAO,GAAP,OAAO,CAAQ;QAElC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;IACpC,CAAC;CACF;AALD,oDAKC"}
@@ -0,0 +1,4 @@
1
+ import { FlagDefinition, EvaluationContext, EvaluationResult } from './types';
2
+ export declare function getVariantValue(flag: FlagDefinition, variantKey: string): unknown;
3
+ export declare function evaluate<T>(flag: FlagDefinition, ctx: EvaluationContext, overrides: Map<string, string>): EvaluationResult<T>;
4
+ //# sourceMappingURL=evaluate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../src/evaluate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAK7E,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAMjF;AAED,wBAAgB,QAAQ,CAAC,CAAC,EACxB,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,iBAAiB,EACtB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,gBAAgB,CAAC,CAAC,CAAC,CA+DrB"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getVariantValue = getVariantValue;
4
+ exports.evaluate = evaluate;
5
+ const errors_1 = require("./errors");
6
+ const bucket_1 = require("./bucket");
7
+ const conditions_1 = require("./conditions");
8
+ function getVariantValue(flag, variantKey) {
9
+ const variant = flag.variants.find((v) => v.key === variantKey);
10
+ if (!variant) {
11
+ throw new errors_1.VariantNotFoundError(flag.key, variantKey);
12
+ }
13
+ return variant.value;
14
+ }
15
+ function evaluate(flag, ctx, overrides) {
16
+ const flagEnabled = flag.enabled !== false;
17
+ // 1. Check overrides
18
+ const overrideVariantKey = overrides.get(flag.key);
19
+ if (overrideVariantKey !== undefined) {
20
+ const value = getVariantValue(flag, overrideVariantKey);
21
+ return {
22
+ flagKey: flag.key,
23
+ variantKey: overrideVariantKey,
24
+ value,
25
+ reason: 'override',
26
+ flagEnabled,
27
+ };
28
+ }
29
+ // 2. If disabled, return default variant
30
+ if (!flagEnabled) {
31
+ const value = getVariantValue(flag, flag.defaultVariant);
32
+ return {
33
+ flagKey: flag.key,
34
+ variantKey: flag.defaultVariant,
35
+ value,
36
+ reason: 'disabled',
37
+ flagEnabled: false,
38
+ };
39
+ }
40
+ // 3. Evaluate targeting rules
41
+ for (const rule of flag.rules ?? []) {
42
+ if ((0, conditions_1.evaluateRule)(ctx, rule)) {
43
+ const serve = rule.serve;
44
+ let resolvedVariantKey;
45
+ if ('variant' in serve) {
46
+ resolvedVariantKey = serve.variant;
47
+ }
48
+ else {
49
+ const bucket = (0, bucket_1.getBucket)(ctx.key, flag.key);
50
+ resolvedVariantKey = (0, bucket_1.selectVariantByRollout)(serve.rollout, bucket);
51
+ }
52
+ const value = getVariantValue(flag, resolvedVariantKey);
53
+ return {
54
+ flagKey: flag.key,
55
+ variantKey: resolvedVariantKey,
56
+ value,
57
+ reason: 'rule_match',
58
+ flagEnabled: true,
59
+ };
60
+ }
61
+ }
62
+ // 4. No rule matched — return default
63
+ const value = getVariantValue(flag, flag.defaultVariant);
64
+ return {
65
+ flagKey: flag.key,
66
+ variantKey: flag.defaultVariant,
67
+ value,
68
+ reason: 'default',
69
+ flagEnabled: true,
70
+ };
71
+ }
72
+ //# sourceMappingURL=evaluate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../src/evaluate.ts"],"names":[],"mappings":";;AAKA,0CAMC;AAED,4BAmEC;AA/ED,qCAA+C;AAC/C,qCAA4D;AAC5D,6CAA2C;AAE3C,SAAgB,eAAe,CAAC,IAAoB,EAAE,UAAkB;IACtE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,UAAU,CAAC,CAAA;IAC/D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,6BAAoB,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;IACtD,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,CAAA;AACtB,CAAC;AAED,SAAgB,QAAQ,CACtB,IAAoB,EACpB,GAAsB,EACtB,SAA8B;IAE9B,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,KAAK,KAAK,CAAA;IAE1C,qBAAqB;IACrB,MAAM,kBAAkB,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAClD,IAAI,kBAAkB,KAAK,SAAS,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,kBAAkB,CAAM,CAAA;QAC5D,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,GAAG;YACjB,UAAU,EAAE,kBAAkB;YAC9B,KAAK;YACL,MAAM,EAAE,UAAU;YAClB,WAAW;SACZ,CAAA;IACH,CAAC;IAED,yCAAyC;IACzC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,CAAM,CAAA;QAC7D,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,GAAG;YACjB,UAAU,EAAE,IAAI,CAAC,cAAc;YAC/B,KAAK;YACL,MAAM,EAAE,UAAU;YAClB,WAAW,EAAE,KAAK;SACnB,CAAA;IACH,CAAC;IAED,8BAA8B;IAC9B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;QACpC,IAAI,IAAA,yBAAY,EAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAEwC,CAAA;YAE3D,IAAI,kBAA0B,CAAA;YAC9B,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;gBACvB,kBAAkB,GAAG,KAAK,CAAC,OAAO,CAAA;YACpC,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,GAAG,IAAA,kBAAS,EAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;gBAC3C,kBAAkB,GAAG,IAAA,+BAAsB,EAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;YACpE,CAAC;YAED,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,kBAAkB,CAAM,CAAA;YAC5D,OAAO;gBACL,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,UAAU,EAAE,kBAAkB;gBAC9B,KAAK;gBACL,MAAM,EAAE,YAAY;gBACpB,WAAW,EAAE,IAAI;aAClB,CAAA;QACH,CAAC;IACH,CAAC;IAED,sCAAsC;IACtC,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,CAAM,CAAA;IAC7D,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,GAAG;QACjB,UAAU,EAAE,IAAI,CAAC,cAAc;QAC/B,KAAK;QACL,MAAM,EAAE,SAAS;QACjB,WAAW,EAAE,IAAI;KAClB,CAAA;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { createClient } from './client';
2
+ export type { FlagType, EvaluationReason, ComparisonOperator, EvaluationContext, ModelConfig, RuleCondition, TargetingRule, FlagVariant, FlagDefinition, FlagConfiguration, EvaluationResult, FlagClientConfig, FlagClient, } from './types';
3
+ export { FlagError, FlagNotFoundError, FlagTypeMismatchError, VariantNotFoundError, } from './errors';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,YAAY,EACV,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,aAAa,EACb,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,GACX,MAAM,SAAS,CAAA;AAChB,OAAO,EACL,SAAS,EACT,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,UAAU,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VariantNotFoundError = exports.FlagTypeMismatchError = exports.FlagNotFoundError = exports.FlagError = exports.createClient = void 0;
4
+ // prompt-flags - AI-native feature flags for prompt variants and model selection
5
+ var client_1 = require("./client");
6
+ Object.defineProperty(exports, "createClient", { enumerable: true, get: function () { return client_1.createClient; } });
7
+ var errors_1 = require("./errors");
8
+ Object.defineProperty(exports, "FlagError", { enumerable: true, get: function () { return errors_1.FlagError; } });
9
+ Object.defineProperty(exports, "FlagNotFoundError", { enumerable: true, get: function () { return errors_1.FlagNotFoundError; } });
10
+ Object.defineProperty(exports, "FlagTypeMismatchError", { enumerable: true, get: function () { return errors_1.FlagTypeMismatchError; } });
11
+ Object.defineProperty(exports, "VariantNotFoundError", { enumerable: true, get: function () { return errors_1.VariantNotFoundError; } });
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iFAAiF;AACjF,mCAAuC;AAA9B,sGAAA,YAAY,OAAA;AAgBrB,mCAKiB;AAJf,mGAAA,SAAS,OAAA;AACT,2GAAA,iBAAiB,OAAA;AACjB,+GAAA,qBAAqB,OAAA;AACrB,8GAAA,oBAAoB,OAAA"}
@@ -0,0 +1,80 @@
1
+ export type FlagType = 'prompt' | 'model' | 'config' | 'boolean';
2
+ export type EvaluationReason = 'rule_match' | 'default' | 'disabled' | 'error' | 'override';
3
+ export type ComparisonOperator = 'equals' | 'notEquals' | 'in' | 'notIn' | 'contains' | 'startsWith' | 'endsWith' | 'greaterThan' | 'lessThan' | 'greaterThanOrEqual' | 'lessThanOrEqual' | 'matches' | 'exists' | 'notExists';
4
+ export interface EvaluationContext {
5
+ key: string;
6
+ plan?: string;
7
+ region?: string;
8
+ email?: string;
9
+ role?: string;
10
+ custom?: Record<string, string | number | boolean | string[]>;
11
+ }
12
+ export interface ModelConfig {
13
+ model: string;
14
+ temperature?: number;
15
+ maxTokens?: number;
16
+ [k: string]: unknown;
17
+ }
18
+ export interface RuleCondition {
19
+ attribute: string;
20
+ operator: ComparisonOperator;
21
+ value?: string | number | boolean;
22
+ values?: (string | number)[];
23
+ negate?: boolean;
24
+ }
25
+ export interface TargetingRule {
26
+ description?: string;
27
+ conditions?: RuleCondition[];
28
+ serve: {
29
+ variant: string;
30
+ } | {
31
+ rollout: Array<{
32
+ variant: string;
33
+ weight: number;
34
+ }>;
35
+ };
36
+ }
37
+ export interface FlagVariant {
38
+ key: string;
39
+ value: unknown;
40
+ }
41
+ export interface FlagDefinition {
42
+ key: string;
43
+ type: FlagType;
44
+ enabled?: boolean;
45
+ variants: FlagVariant[];
46
+ defaultVariant: string;
47
+ rules?: TargetingRule[];
48
+ }
49
+ export interface FlagConfiguration {
50
+ flags: FlagDefinition[];
51
+ segments?: Record<string, {
52
+ conditions: RuleCondition[];
53
+ }>;
54
+ }
55
+ export interface EvaluationResult<T = unknown> {
56
+ flagKey: string;
57
+ variantKey: string;
58
+ value: T;
59
+ reason: EvaluationReason;
60
+ flagEnabled: boolean;
61
+ }
62
+ export interface FlagClientConfig {
63
+ config: FlagConfiguration;
64
+ defaultContext?: Partial<EvaluationContext>;
65
+ onEvaluation?: (e: EvaluationResult<unknown>) => void;
66
+ onError?: (e: Error) => void;
67
+ }
68
+ export interface FlagClient {
69
+ getPrompt(key: string, ctx: EvaluationContext): string;
70
+ getModel(key: string, ctx: EvaluationContext): ModelConfig;
71
+ getConfig<T>(key: string, ctx: EvaluationContext): T;
72
+ isEnabled(key: string, ctx: EvaluationContext): boolean;
73
+ evaluate<T>(key: string, ctx: EvaluationContext): EvaluationResult<T>;
74
+ getFlagKeys(): string[];
75
+ getFlag(key: string): FlagDefinition | null;
76
+ overrideForTest(key: string, variantKey: string): void;
77
+ clearOverride(key: string): void;
78
+ clearAllOverrides(): void;
79
+ }
80
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "prompt-flags",
3
+ "version": "0.1.0",
4
+ "description": "AI-native feature flags for prompt variants and model selection",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "test": "vitest run",
13
+ "lint": "eslint src/",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "keywords": [],
17
+ "author": "",
18
+ "license": "MIT",
19
+ "engines": {
20
+ "node": ">=18"
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "dependencies": {
26
+ "murmurhash3js": "^3.0.1"
27
+ },
28
+ "devDependencies": {
29
+ "@types/murmurhash3js": "^3.0.3",
30
+ "@types/node": "^20.0.0",
31
+ "@typescript-eslint/eslint-plugin": "^7.0.0",
32
+ "@typescript-eslint/parser": "^7.0.0",
33
+ "eslint": "^8.57.0",
34
+ "typescript": "^5.4.0",
35
+ "vitest": "^1.5.0"
36
+ }
37
+ }