@dr-sentry/sdk 1.0.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 +285 -0
- package/dist/cjs/cache.d.ts +33 -0
- package/dist/cjs/cache.d.ts.map +1 -0
- package/dist/cjs/cache.js +84 -0
- package/dist/cjs/cache.js.map +1 -0
- package/dist/cjs/client.d.ts +81 -0
- package/dist/cjs/client.d.ts.map +1 -0
- package/dist/cjs/client.js +362 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/file-loader.d.ts +3 -0
- package/dist/cjs/file-loader.d.ts.map +1 -0
- package/dist/cjs/file-loader.js +53 -0
- package/dist/cjs/file-loader.js.map +1 -0
- package/dist/cjs/index.d.ts +29 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +36 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/local-evaluator.d.ts +6 -0
- package/dist/cjs/local-evaluator.d.ts.map +1 -0
- package/dist/cjs/local-evaluator.js +40 -0
- package/dist/cjs/local-evaluator.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/streaming.d.ts +42 -0
- package/dist/cjs/streaming.d.ts.map +1 -0
- package/dist/cjs/streaming.js +140 -0
- package/dist/cjs/streaming.js.map +1 -0
- package/dist/cjs/types.d.ts +126 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +6 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/cache.d.ts +33 -0
- package/dist/esm/cache.d.ts.map +1 -0
- package/dist/esm/cache.js +80 -0
- package/dist/esm/cache.js.map +1 -0
- package/dist/esm/client.d.ts +81 -0
- package/dist/esm/client.d.ts.map +1 -0
- package/dist/esm/client.js +358 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/file-loader.d.ts +3 -0
- package/dist/esm/file-loader.d.ts.map +1 -0
- package/dist/esm/file-loader.js +17 -0
- package/dist/esm/file-loader.js.map +1 -0
- package/dist/esm/index.d.ts +29 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +28 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/local-evaluator.d.ts +6 -0
- package/dist/esm/local-evaluator.d.ts.map +1 -0
- package/dist/esm/local-evaluator.js +37 -0
- package/dist/esm/local-evaluator.js.map +1 -0
- package/dist/esm/streaming.d.ts +42 -0
- package/dist/esm/streaming.d.ts.map +1 -0
- package/dist/esm/streaming.js +136 -0
- package/dist/esm/streaming.js.map +1 -0
- package/dist/esm/types.d.ts +126 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +5 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import { FlagCache } from './cache';
|
|
2
|
+
import { FlagStreamClient } from './streaming';
|
|
3
|
+
import { loadFlagConfig } from './file-loader';
|
|
4
|
+
import { evaluateLocal } from './local-evaluator';
|
|
5
|
+
const DEFAULT_BASE_URL = 'https://api.dr-sentry.com';
|
|
6
|
+
const DEFAULT_CACHE_TIMEOUT_MS = 60_000;
|
|
7
|
+
/**
|
|
8
|
+
* DeploySentry feature-flag client.
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* const client = new DeploySentryClient({
|
|
12
|
+
* apiKey: 'ds_live_xxx',
|
|
13
|
+
* environment: 'production',
|
|
14
|
+
* project: 'my-app',
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* await client.initialize();
|
|
18
|
+
*
|
|
19
|
+
* const darkMode = client.boolValue('dark-mode', false, { userId: 'u1' });
|
|
20
|
+
*
|
|
21
|
+
* client.close();
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export class DeploySentryClient {
|
|
25
|
+
apiKey;
|
|
26
|
+
baseURL;
|
|
27
|
+
environment;
|
|
28
|
+
project;
|
|
29
|
+
application;
|
|
30
|
+
offlineMode;
|
|
31
|
+
sessionId;
|
|
32
|
+
mode;
|
|
33
|
+
flagFilePath;
|
|
34
|
+
cache;
|
|
35
|
+
streamClient = null;
|
|
36
|
+
_initialized = false;
|
|
37
|
+
flagConfig = null;
|
|
38
|
+
registry = new Map();
|
|
39
|
+
constructor(options) {
|
|
40
|
+
if (!options.apiKey)
|
|
41
|
+
throw new Error('apiKey is required');
|
|
42
|
+
if (!options.environment)
|
|
43
|
+
throw new Error('environment is required');
|
|
44
|
+
if (!options.project)
|
|
45
|
+
throw new Error('project is required');
|
|
46
|
+
if (!options.application)
|
|
47
|
+
throw new Error('application is required');
|
|
48
|
+
this.apiKey = options.apiKey;
|
|
49
|
+
this.baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\/+$/, '');
|
|
50
|
+
this.environment = options.environment;
|
|
51
|
+
this.project = options.project;
|
|
52
|
+
this.application = options.application;
|
|
53
|
+
this.offlineMode = options.offlineMode ?? false;
|
|
54
|
+
this.sessionId = options.sessionId;
|
|
55
|
+
this.mode = options.mode ?? 'server';
|
|
56
|
+
this.flagFilePath = options.flagFilePath;
|
|
57
|
+
this.cache = new FlagCache(options.cacheTimeout ?? DEFAULT_CACHE_TIMEOUT_MS);
|
|
58
|
+
}
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Lifecycle
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
/**
|
|
63
|
+
* Fetch the initial flag set and open an SSE connection for real-time
|
|
64
|
+
* updates. Must be called before evaluating flags.
|
|
65
|
+
*/
|
|
66
|
+
async initialize() {
|
|
67
|
+
if (this.mode === 'file') {
|
|
68
|
+
this.flagConfig = loadFlagConfig(this.flagFilePath);
|
|
69
|
+
this._initialized = true;
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (this.offlineMode) {
|
|
73
|
+
this._initialized = true;
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
// Fetch all flags for the project so the cache is warm.
|
|
78
|
+
const flags = await this.fetchAllFlags();
|
|
79
|
+
this.cache.setMany(flags);
|
|
80
|
+
// Start streaming updates.
|
|
81
|
+
this.streamClient = new FlagStreamClient({
|
|
82
|
+
url: `${this.baseURL}/api/v1/flags/stream?project_id=${enc(this.project)}&environment_id=${enc(this.environment)}&application=${enc(this.application)}`,
|
|
83
|
+
headers: this.authHeaders(),
|
|
84
|
+
onUpdate: (updated) => this.cache.setMany(updated),
|
|
85
|
+
onError: (err) => {
|
|
86
|
+
// Surface errors but do not crash – the cache still serves stale data.
|
|
87
|
+
console.error('[DeploySentry] stream error:', err.message);
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
// Fire-and-forget; the stream reconnects automatically.
|
|
91
|
+
this.streamClient.connect();
|
|
92
|
+
this._initialized = true;
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
if (this.mode === 'server-with-fallback') {
|
|
96
|
+
console.warn('[DeploySentry] Server unavailable, falling back to flag config file');
|
|
97
|
+
this.flagConfig = loadFlagConfig(this.flagFilePath);
|
|
98
|
+
this._initialized = true;
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** Tear down the SSE connection and release resources. */
|
|
105
|
+
close() {
|
|
106
|
+
this.streamClient?.close();
|
|
107
|
+
this.streamClient = null;
|
|
108
|
+
this.cache.clear();
|
|
109
|
+
this._initialized = false;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Clear the local cache and re-fetch all flags from the server.
|
|
113
|
+
* Useful when session state may have changed and the client needs
|
|
114
|
+
* fresh evaluations.
|
|
115
|
+
*/
|
|
116
|
+
async refreshSession() {
|
|
117
|
+
if (this.offlineMode)
|
|
118
|
+
return;
|
|
119
|
+
this.cache.clear();
|
|
120
|
+
const flags = await this.fetchAllFlags();
|
|
121
|
+
this.cache.setMany(flags);
|
|
122
|
+
}
|
|
123
|
+
/** Whether {@link initialize} has been called successfully. */
|
|
124
|
+
get isInitialized() {
|
|
125
|
+
return this._initialized;
|
|
126
|
+
}
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
// Typed value helpers
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
/** Evaluate a flag as a boolean. */
|
|
131
|
+
async boolValue(key, defaultValue, context) {
|
|
132
|
+
const result = await this.evaluate(key, defaultValue, context);
|
|
133
|
+
if (typeof result === 'boolean')
|
|
134
|
+
return result;
|
|
135
|
+
// The backend stores `default_value` as a string, so the evaluation
|
|
136
|
+
// endpoint commonly returns "true"/"false". Coerce so SDK callers see
|
|
137
|
+
// a real boolean instead of falling back to the literal default.
|
|
138
|
+
if (typeof result === 'string') {
|
|
139
|
+
const lowered = result.toLowerCase();
|
|
140
|
+
if (lowered === 'true')
|
|
141
|
+
return true;
|
|
142
|
+
if (lowered === 'false')
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
return defaultValue;
|
|
146
|
+
}
|
|
147
|
+
/** Evaluate a flag as a string. */
|
|
148
|
+
async stringValue(key, defaultValue, context) {
|
|
149
|
+
const result = await this.evaluate(key, defaultValue, context);
|
|
150
|
+
return typeof result === 'string' ? result : defaultValue;
|
|
151
|
+
}
|
|
152
|
+
/** Evaluate a flag as an integer. */
|
|
153
|
+
async intValue(key, defaultValue, context) {
|
|
154
|
+
const result = await this.evaluate(key, defaultValue, context);
|
|
155
|
+
return typeof result === 'number' && Number.isInteger(result)
|
|
156
|
+
? result
|
|
157
|
+
: defaultValue;
|
|
158
|
+
}
|
|
159
|
+
/** Evaluate a flag and return the value as a parsed JSON object. */
|
|
160
|
+
async jsonValue(key, defaultValue, context) {
|
|
161
|
+
const result = await this.evaluate(key, defaultValue, context);
|
|
162
|
+
return result ?? defaultValue;
|
|
163
|
+
}
|
|
164
|
+
// ---------------------------------------------------------------------------
|
|
165
|
+
// Detail evaluation
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
/**
|
|
168
|
+
* Return the full {@link EvaluationResult} for a flag including metadata,
|
|
169
|
+
* reason, and resolved value.
|
|
170
|
+
*/
|
|
171
|
+
async detail(key, context) {
|
|
172
|
+
if (this.offlineMode) {
|
|
173
|
+
return this.offlineResult(key);
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
const body = await this.post('/api/v1/flags/evaluate', {
|
|
177
|
+
project_id: this.project,
|
|
178
|
+
environment_id: this.environment,
|
|
179
|
+
application: this.application,
|
|
180
|
+
flag_key: key,
|
|
181
|
+
context: context ?? {},
|
|
182
|
+
...(this.sessionId ? { session_id: this.sessionId } : {}),
|
|
183
|
+
});
|
|
184
|
+
return body;
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return this.cachedResult(key);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
// Metadata helpers
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
/** Return all cached flags belonging to a given category. */
|
|
194
|
+
flagsByCategory(category) {
|
|
195
|
+
return this.cache.getAll().filter((f) => f.metadata.category === category);
|
|
196
|
+
}
|
|
197
|
+
/** Return all cached flags whose `expiresAt` is in the past. */
|
|
198
|
+
expiredFlags() {
|
|
199
|
+
const now = new Date().toISOString();
|
|
200
|
+
return this.cache.getAll().filter((f) => {
|
|
201
|
+
return f.metadata.expiresAt && f.metadata.expiresAt < now;
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
/** Return the owners array for a given flag key. */
|
|
205
|
+
flagOwners(key) {
|
|
206
|
+
const flag = this.cache.get(key);
|
|
207
|
+
return flag?.metadata.owners ?? [];
|
|
208
|
+
}
|
|
209
|
+
/** Return every flag currently held in the local cache. */
|
|
210
|
+
allFlags() {
|
|
211
|
+
return this.cache.getAll();
|
|
212
|
+
}
|
|
213
|
+
// ---------------------------------------------------------------------------
|
|
214
|
+
// Register / Dispatch
|
|
215
|
+
// ---------------------------------------------------------------------------
|
|
216
|
+
register(operation, handler, flagKey) {
|
|
217
|
+
let list = this.registry.get(operation);
|
|
218
|
+
if (!list) {
|
|
219
|
+
list = [];
|
|
220
|
+
this.registry.set(operation, list);
|
|
221
|
+
}
|
|
222
|
+
if (flagKey === undefined) {
|
|
223
|
+
const idx = list.findIndex((r) => r.flagKey === undefined);
|
|
224
|
+
if (idx !== -1)
|
|
225
|
+
list[idx] = { handler };
|
|
226
|
+
else
|
|
227
|
+
list.push({ handler });
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
list.push({ handler, flagKey });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
dispatch(operation, _context) {
|
|
234
|
+
const list = this.registry.get(operation);
|
|
235
|
+
if (!list || list.length === 0) {
|
|
236
|
+
throw new Error(`No handlers registered for operation '${operation}'. Call register() before dispatch().`);
|
|
237
|
+
}
|
|
238
|
+
for (const reg of list) {
|
|
239
|
+
if (reg.flagKey !== undefined) {
|
|
240
|
+
const flag = this.cache.get(reg.flagKey);
|
|
241
|
+
if (flag && flag.enabled)
|
|
242
|
+
return reg.handler;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const defaultReg = list.find((r) => r.flagKey === undefined);
|
|
246
|
+
if (!defaultReg) {
|
|
247
|
+
throw new Error(`No matching handler for operation '${operation}' and no default registered. Register a default handler (no flagKey) as the last registration.`);
|
|
248
|
+
}
|
|
249
|
+
return defaultReg.handler;
|
|
250
|
+
}
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
// Private helpers
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
async evaluate(key, defaultValue, context) {
|
|
255
|
+
if (this.flagConfig) {
|
|
256
|
+
const result = evaluateLocal(this.flagConfig, this.environment, key, context);
|
|
257
|
+
if (result.reason === 'flag_not_found')
|
|
258
|
+
return defaultValue;
|
|
259
|
+
return result.value;
|
|
260
|
+
}
|
|
261
|
+
if (this.offlineMode)
|
|
262
|
+
return defaultValue;
|
|
263
|
+
// Prefer server-side evaluation so targeting rules are applied.
|
|
264
|
+
try {
|
|
265
|
+
const result = await this.post('/api/v1/flags/evaluate', {
|
|
266
|
+
project_id: this.project,
|
|
267
|
+
environment_id: this.environment,
|
|
268
|
+
application: this.application,
|
|
269
|
+
flag_key: key,
|
|
270
|
+
context: context ?? {},
|
|
271
|
+
...(this.sessionId ? { session_id: this.sessionId } : {}),
|
|
272
|
+
});
|
|
273
|
+
return result.value;
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
// Fall back to the cached flag value.
|
|
277
|
+
const cached = this.cache.get(key);
|
|
278
|
+
return cached?.value ?? defaultValue;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
async fetchAllFlags() {
|
|
282
|
+
const response = await this.request('GET', `/api/v1/flags?project_id=${enc(this.project)}&application=${enc(this.application)}`);
|
|
283
|
+
return response.flags ?? [];
|
|
284
|
+
}
|
|
285
|
+
async post(path, body) {
|
|
286
|
+
return this.request('POST', path, body);
|
|
287
|
+
}
|
|
288
|
+
async request(method, path, body) {
|
|
289
|
+
const url = `${this.baseURL}${path}`;
|
|
290
|
+
const init = {
|
|
291
|
+
method,
|
|
292
|
+
headers: {
|
|
293
|
+
...this.authHeaders(),
|
|
294
|
+
'Content-Type': 'application/json',
|
|
295
|
+
Accept: 'application/json',
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
if (body !== undefined) {
|
|
299
|
+
init.body = JSON.stringify(body);
|
|
300
|
+
}
|
|
301
|
+
const response = await fetch(url, init);
|
|
302
|
+
if (!response.ok) {
|
|
303
|
+
const text = await response.text().catch(() => '');
|
|
304
|
+
throw new Error(`DeploySentry API error: ${response.status} ${response.statusText} – ${text}`);
|
|
305
|
+
}
|
|
306
|
+
return response.json();
|
|
307
|
+
}
|
|
308
|
+
authHeaders() {
|
|
309
|
+
const headers = {
|
|
310
|
+
Authorization: `ApiKey ${this.apiKey}`,
|
|
311
|
+
};
|
|
312
|
+
if (this.sessionId) {
|
|
313
|
+
headers['X-DeploySentry-Session'] = this.sessionId;
|
|
314
|
+
}
|
|
315
|
+
return headers;
|
|
316
|
+
}
|
|
317
|
+
offlineResult(key) {
|
|
318
|
+
const flag = this.cache.get(key);
|
|
319
|
+
const metadata = flag?.metadata ?? {
|
|
320
|
+
category: 'feature',
|
|
321
|
+
purpose: '',
|
|
322
|
+
owners: [],
|
|
323
|
+
isPermanent: false,
|
|
324
|
+
tags: [],
|
|
325
|
+
};
|
|
326
|
+
return {
|
|
327
|
+
key,
|
|
328
|
+
value: flag?.value ?? null,
|
|
329
|
+
enabled: flag?.enabled ?? false,
|
|
330
|
+
reason: 'OFFLINE',
|
|
331
|
+
metadata,
|
|
332
|
+
evaluatedAt: new Date().toISOString(),
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
cachedResult(key) {
|
|
336
|
+
const flag = this.cache.get(key);
|
|
337
|
+
const metadata = flag?.metadata ?? {
|
|
338
|
+
category: 'feature',
|
|
339
|
+
purpose: '',
|
|
340
|
+
owners: [],
|
|
341
|
+
isPermanent: false,
|
|
342
|
+
tags: [],
|
|
343
|
+
};
|
|
344
|
+
return {
|
|
345
|
+
key,
|
|
346
|
+
value: flag?.value ?? null,
|
|
347
|
+
enabled: flag?.enabled ?? false,
|
|
348
|
+
reason: flag ? 'CACHE' : 'ERROR',
|
|
349
|
+
metadata,
|
|
350
|
+
evaluatedAt: new Date().toISOString(),
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/** Percent-encode a value for use in a URL query parameter. */
|
|
355
|
+
function enc(value) {
|
|
356
|
+
return encodeURIComponent(value);
|
|
357
|
+
}
|
|
358
|
+
//# 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 @@
|
|
|
1
|
+
{"version":3,"file":"file-loader.d.ts","sourceRoot":"","sources":["../../src/file-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAI1C,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,UAAU,CAW5D"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as yaml from 'js-yaml';
|
|
4
|
+
const DEFAULT_PATH = '.deploysentry/flags.yaml';
|
|
5
|
+
export function loadFlagConfig(filePath) {
|
|
6
|
+
const resolved = path.resolve(filePath ?? DEFAULT_PATH);
|
|
7
|
+
if (!fs.existsSync(resolved)) {
|
|
8
|
+
throw new Error(`Flag config file not found: ${resolved}`);
|
|
9
|
+
}
|
|
10
|
+
const content = fs.readFileSync(resolved, 'utf-8');
|
|
11
|
+
const parsed = yaml.load(content);
|
|
12
|
+
if (!parsed || typeof parsed !== 'object' || !parsed.version || !parsed.flags) {
|
|
13
|
+
throw new Error(`Invalid flag config file: ${resolved}`);
|
|
14
|
+
}
|
|
15
|
+
return parsed;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=file-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-loader.js","sourceRoot":"","sources":["../../src/file-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAGhC,MAAM,YAAY,GAAG,0BAA0B,CAAC;AAEhD,MAAM,UAAU,cAAc,CAAC,QAAiB;IAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,YAAY,CAAC,CAAC;IACxD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAe,CAAC;IAChD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC9E,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,EAAE,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deploysentry/sdk – Official Node.js/TypeScript SDK for DeploySentry.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { DeploySentryClient } from '@deploysentry/sdk';
|
|
7
|
+
*
|
|
8
|
+
* const client = new DeploySentryClient({
|
|
9
|
+
* apiKey: 'ds_live_xxx',
|
|
10
|
+
* environment: 'production',
|
|
11
|
+
* project: 'my-app',
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* await client.initialize();
|
|
15
|
+
*
|
|
16
|
+
* const enabled = await client.boolValue('new-checkout', false, {
|
|
17
|
+
* userId: 'user-42',
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @packageDocumentation
|
|
22
|
+
*/
|
|
23
|
+
export { DeploySentryClient } from './client';
|
|
24
|
+
export { FlagCache } from './cache';
|
|
25
|
+
export { FlagStreamClient } from './streaming';
|
|
26
|
+
export { loadFlagConfig } from './file-loader';
|
|
27
|
+
export { evaluateLocal } from './local-evaluator';
|
|
28
|
+
export type { ClientOptions, EvaluationContext, EvaluationResult, Flag, FlagCategory, FlagMetadata, FlagConfig, FlagConfigFlag, FlagConfigRule, FlagConfigEnvironment, ApiError, } from './types';
|
|
29
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,IAAI,EACJ,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,QAAQ,GACT,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deploysentry/sdk – Official Node.js/TypeScript SDK for DeploySentry.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { DeploySentryClient } from '@deploysentry/sdk';
|
|
7
|
+
*
|
|
8
|
+
* const client = new DeploySentryClient({
|
|
9
|
+
* apiKey: 'ds_live_xxx',
|
|
10
|
+
* environment: 'production',
|
|
11
|
+
* project: 'my-app',
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* await client.initialize();
|
|
15
|
+
*
|
|
16
|
+
* const enabled = await client.boolValue('new-checkout', false, {
|
|
17
|
+
* userId: 'user-42',
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @packageDocumentation
|
|
22
|
+
*/
|
|
23
|
+
export { DeploySentryClient } from './client';
|
|
24
|
+
export { FlagCache } from './cache';
|
|
25
|
+
export { FlagStreamClient } from './streaming';
|
|
26
|
+
export { loadFlagConfig } from './file-loader';
|
|
27
|
+
export { evaluateLocal } from './local-evaluator';
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { EvaluationContext, FlagConfig } from './types';
|
|
2
|
+
export declare function evaluateLocal(config: FlagConfig, environment: string, key: string, context?: EvaluationContext): {
|
|
3
|
+
value: string;
|
|
4
|
+
reason: string;
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=local-evaluator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-evaluator.d.ts","sourceRoot":"","sources":["../../src/local-evaluator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAkB,MAAM,SAAS,CAAC;AAE7E,wBAAgB,aAAa,CAC3B,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,iBAAiB,GAC1B;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAoBnC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export function evaluateLocal(config, environment, key, context) {
|
|
2
|
+
const flag = config.flags.find((f) => f.key === key);
|
|
3
|
+
if (!flag)
|
|
4
|
+
return { value: '', reason: 'flag_not_found' };
|
|
5
|
+
const envState = flag.environments[environment];
|
|
6
|
+
if (!envState || !envState.enabled) {
|
|
7
|
+
return { value: flag.default_value, reason: 'env_disabled' };
|
|
8
|
+
}
|
|
9
|
+
if (flag.rules && context) {
|
|
10
|
+
const sorted = [...flag.rules].sort((a, b) => a.priority - b.priority);
|
|
11
|
+
for (const rule of sorted) {
|
|
12
|
+
if (!rule.environments[environment])
|
|
13
|
+
continue;
|
|
14
|
+
if (matchRule(rule, context)) {
|
|
15
|
+
return { value: rule.value, reason: 'rule_match' };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return { value: envState.value || flag.default_value, reason: 'default' };
|
|
20
|
+
}
|
|
21
|
+
function matchRule(rule, context) {
|
|
22
|
+
const val = context.attributes?.[rule.attribute] ?? '';
|
|
23
|
+
const targets = rule.target_values ?? [];
|
|
24
|
+
switch (rule.operator) {
|
|
25
|
+
case 'equals': return targets.length > 0 && val === targets[0];
|
|
26
|
+
case 'not_equals': return targets.length > 0 && val !== targets[0];
|
|
27
|
+
case 'in': return targets.includes(val);
|
|
28
|
+
case 'not_in': return !targets.includes(val);
|
|
29
|
+
case 'contains': return targets.length > 0 && val.includes(targets[0]);
|
|
30
|
+
case 'starts_with': return targets.length > 0 && val.startsWith(targets[0]);
|
|
31
|
+
case 'ends_with': return targets.length > 0 && val.endsWith(targets[0]);
|
|
32
|
+
case 'greater_than': return targets.length > 0 && parseFloat(val) > parseFloat(targets[0]);
|
|
33
|
+
case 'less_than': return targets.length > 0 && parseFloat(val) < parseFloat(targets[0]);
|
|
34
|
+
default: return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=local-evaluator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-evaluator.js","sourceRoot":"","sources":["../../src/local-evaluator.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,aAAa,CAC3B,MAAkB,EAClB,WAAmB,EACnB,GAAW,EACX,OAA2B;IAE3B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;IACrD,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAE1D,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;IAChD,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACnC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IAC/D,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QACvE,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;YAC1B,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC;gBAAE,SAAS;YAC9C,IAAI,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;gBAC7B,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;YACrD,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAC5E,CAAC;AAED,SAAS,SAAS,CAAC,IAAoB,EAAE,OAA0B;IACjE,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC;IACzC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtB,KAAK,QAAQ,CAAC,CAAC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/D,KAAK,YAAY,CAAC,CAAC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;QACnE,KAAK,IAAI,CAAC,CAAC,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACxC,KAAK,QAAQ,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC7C,KAAK,UAAU,CAAC,CAAC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,KAAK,aAAa,CAAC,CAAC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5E,KAAK,WAAW,CAAC,CAAC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACxE,KAAK,cAAc,CAAC,CAAC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3F,KAAK,WAAW,CAAC,CAAC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACxF,OAAO,CAAC,CAAC,OAAO,KAAK,CAAC;IACxB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Flag } from './types';
|
|
2
|
+
/** Callback invoked whenever a flag update arrives over SSE. */
|
|
3
|
+
export type FlagUpdateHandler = (flags: Flag[]) => void;
|
|
4
|
+
/** Callback invoked when the SSE connection encounters an error. */
|
|
5
|
+
export type StreamErrorHandler = (error: Error) => void;
|
|
6
|
+
interface StreamOptions {
|
|
7
|
+
/** Full URL of the SSE endpoint including query parameters. */
|
|
8
|
+
url: string;
|
|
9
|
+
/** Headers to attach to the request (e.g. Authorization). */
|
|
10
|
+
headers: Record<string, string>;
|
|
11
|
+
/** Called when one or more flag updates are received. */
|
|
12
|
+
onUpdate: FlagUpdateHandler;
|
|
13
|
+
/** Called when the stream encounters an error. */
|
|
14
|
+
onError?: StreamErrorHandler;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Lightweight SSE streaming client that keeps the local flag cache
|
|
18
|
+
* synchronised with the DeploySentry service.
|
|
19
|
+
*
|
|
20
|
+
* Uses the built-in `fetch` readable stream API available in Node 18+
|
|
21
|
+
* to avoid external EventSource dependencies.
|
|
22
|
+
*/
|
|
23
|
+
export declare class FlagStreamClient {
|
|
24
|
+
private abortController;
|
|
25
|
+
private reconnectTimer;
|
|
26
|
+
private closed;
|
|
27
|
+
private retryMs;
|
|
28
|
+
private readonly url;
|
|
29
|
+
private readonly headers;
|
|
30
|
+
private readonly onUpdate;
|
|
31
|
+
private readonly onError;
|
|
32
|
+
constructor(options: StreamOptions);
|
|
33
|
+
/** Open the SSE connection and start processing events. */
|
|
34
|
+
connect(): Promise<void>;
|
|
35
|
+
/** Close the connection and stop reconnection attempts. */
|
|
36
|
+
close(): void;
|
|
37
|
+
private consumeStream;
|
|
38
|
+
private processEvent;
|
|
39
|
+
private scheduleReconnect;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=streaming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../../src/streaming.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,gEAAgE;AAChE,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;AAExD,oEAAoE;AACpE,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAOxD,UAAU,aAAa;IACrB,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,yDAAyD;IACzD,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,kDAAkD;IAClD,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAwB;IAEvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEjC,OAAO,EAAE,aAAa;IAOlC,2DAA2D;IACrD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAuC9B,2DAA2D;IAC3D,KAAK,IAAI,IAAI;YAkBC,aAAa;IA8B3B,OAAO,CAAC,YAAY;IAuBpB,OAAO,CAAC,iBAAiB;CAgB1B"}
|