@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.
Files changed (59) hide show
  1. package/README.md +285 -0
  2. package/dist/cjs/cache.d.ts +33 -0
  3. package/dist/cjs/cache.d.ts.map +1 -0
  4. package/dist/cjs/cache.js +84 -0
  5. package/dist/cjs/cache.js.map +1 -0
  6. package/dist/cjs/client.d.ts +81 -0
  7. package/dist/cjs/client.d.ts.map +1 -0
  8. package/dist/cjs/client.js +362 -0
  9. package/dist/cjs/client.js.map +1 -0
  10. package/dist/cjs/file-loader.d.ts +3 -0
  11. package/dist/cjs/file-loader.d.ts.map +1 -0
  12. package/dist/cjs/file-loader.js +53 -0
  13. package/dist/cjs/file-loader.js.map +1 -0
  14. package/dist/cjs/index.d.ts +29 -0
  15. package/dist/cjs/index.d.ts.map +1 -0
  16. package/dist/cjs/index.js +36 -0
  17. package/dist/cjs/index.js.map +1 -0
  18. package/dist/cjs/local-evaluator.d.ts +6 -0
  19. package/dist/cjs/local-evaluator.d.ts.map +1 -0
  20. package/dist/cjs/local-evaluator.js +40 -0
  21. package/dist/cjs/local-evaluator.js.map +1 -0
  22. package/dist/cjs/package.json +1 -0
  23. package/dist/cjs/streaming.d.ts +42 -0
  24. package/dist/cjs/streaming.d.ts.map +1 -0
  25. package/dist/cjs/streaming.js +140 -0
  26. package/dist/cjs/streaming.js.map +1 -0
  27. package/dist/cjs/types.d.ts +126 -0
  28. package/dist/cjs/types.d.ts.map +1 -0
  29. package/dist/cjs/types.js +6 -0
  30. package/dist/cjs/types.js.map +1 -0
  31. package/dist/esm/cache.d.ts +33 -0
  32. package/dist/esm/cache.d.ts.map +1 -0
  33. package/dist/esm/cache.js +80 -0
  34. package/dist/esm/cache.js.map +1 -0
  35. package/dist/esm/client.d.ts +81 -0
  36. package/dist/esm/client.d.ts.map +1 -0
  37. package/dist/esm/client.js +358 -0
  38. package/dist/esm/client.js.map +1 -0
  39. package/dist/esm/file-loader.d.ts +3 -0
  40. package/dist/esm/file-loader.d.ts.map +1 -0
  41. package/dist/esm/file-loader.js +17 -0
  42. package/dist/esm/file-loader.js.map +1 -0
  43. package/dist/esm/index.d.ts +29 -0
  44. package/dist/esm/index.d.ts.map +1 -0
  45. package/dist/esm/index.js +28 -0
  46. package/dist/esm/index.js.map +1 -0
  47. package/dist/esm/local-evaluator.d.ts +6 -0
  48. package/dist/esm/local-evaluator.d.ts.map +1 -0
  49. package/dist/esm/local-evaluator.js +37 -0
  50. package/dist/esm/local-evaluator.js.map +1 -0
  51. package/dist/esm/streaming.d.ts +42 -0
  52. package/dist/esm/streaming.d.ts.map +1 -0
  53. package/dist/esm/streaming.js +136 -0
  54. package/dist/esm/streaming.js.map +1 -0
  55. package/dist/esm/types.d.ts +126 -0
  56. package/dist/esm/types.d.ts.map +1 -0
  57. package/dist/esm/types.js +5 -0
  58. package/dist/esm/types.js.map +1 -0
  59. package/package.json +62 -0
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FlagStreamClient = void 0;
4
+ const SSE_INITIAL_RETRY_MS = 1_000;
5
+ const SSE_MAX_RETRY_MS = 30_000;
6
+ const SSE_BACKOFF_MULTIPLIER = 2;
7
+ const SSE_JITTER_FRACTION = 0.2;
8
+ /**
9
+ * Lightweight SSE streaming client that keeps the local flag cache
10
+ * synchronised with the DeploySentry service.
11
+ *
12
+ * Uses the built-in `fetch` readable stream API available in Node 18+
13
+ * to avoid external EventSource dependencies.
14
+ */
15
+ class FlagStreamClient {
16
+ abortController = null;
17
+ reconnectTimer = null;
18
+ closed = false;
19
+ retryMs = SSE_INITIAL_RETRY_MS;
20
+ url;
21
+ headers;
22
+ onUpdate;
23
+ onError;
24
+ constructor(options) {
25
+ this.url = options.url;
26
+ this.headers = options.headers;
27
+ this.onUpdate = options.onUpdate;
28
+ this.onError = options.onError ?? (() => { });
29
+ }
30
+ /** Open the SSE connection and start processing events. */
31
+ async connect() {
32
+ if (this.closed)
33
+ return;
34
+ this.abortController = new AbortController();
35
+ try {
36
+ const response = await fetch(this.url, {
37
+ method: 'GET',
38
+ headers: {
39
+ ...this.headers,
40
+ Accept: 'text/event-stream',
41
+ 'Cache-Control': 'no-cache',
42
+ },
43
+ signal: this.abortController.signal,
44
+ });
45
+ if (!response.ok) {
46
+ throw new Error(`SSE connection failed: ${response.status} ${response.statusText}`);
47
+ }
48
+ if (!response.body) {
49
+ throw new Error('SSE response has no body');
50
+ }
51
+ this.retryMs = SSE_INITIAL_RETRY_MS;
52
+ await this.consumeStream(response.body);
53
+ }
54
+ catch (err) {
55
+ if (this.closed)
56
+ return;
57
+ const error = err instanceof Error ? err : new Error(String(err));
58
+ if (error.name === 'AbortError')
59
+ return;
60
+ this.onError(error);
61
+ this.scheduleReconnect();
62
+ }
63
+ }
64
+ /** Close the connection and stop reconnection attempts. */
65
+ close() {
66
+ this.closed = true;
67
+ if (this.reconnectTimer) {
68
+ clearTimeout(this.reconnectTimer);
69
+ this.reconnectTimer = null;
70
+ }
71
+ if (this.abortController) {
72
+ this.abortController.abort();
73
+ this.abortController = null;
74
+ }
75
+ }
76
+ // ---------------------------------------------------------------------------
77
+ // Internals
78
+ // ---------------------------------------------------------------------------
79
+ async consumeStream(body) {
80
+ const reader = body.getReader();
81
+ const decoder = new TextDecoder();
82
+ let buffer = '';
83
+ try {
84
+ while (!this.closed) {
85
+ const { done, value } = await reader.read();
86
+ if (done)
87
+ break;
88
+ buffer += decoder.decode(value, { stream: true });
89
+ // SSE events are delimited by double newlines.
90
+ const parts = buffer.split('\n\n');
91
+ buffer = parts.pop() ?? '';
92
+ for (const raw of parts) {
93
+ this.processEvent(raw);
94
+ }
95
+ }
96
+ }
97
+ finally {
98
+ reader.releaseLock();
99
+ }
100
+ // If the stream ended naturally (server closed), attempt reconnect.
101
+ if (!this.closed) {
102
+ this.scheduleReconnect();
103
+ }
104
+ }
105
+ processEvent(raw) {
106
+ let eventType = 'message';
107
+ let data = '';
108
+ for (const line of raw.split('\n')) {
109
+ if (line.startsWith('event:')) {
110
+ eventType = line.slice(6).trim();
111
+ }
112
+ else if (line.startsWith('data:')) {
113
+ data += line.slice(5).trim();
114
+ }
115
+ }
116
+ if (eventType === 'flag_update' || eventType === 'message') {
117
+ try {
118
+ const parsed = JSON.parse(data);
119
+ const flags = Array.isArray(parsed) ? parsed : [parsed];
120
+ this.onUpdate(flags);
121
+ }
122
+ catch {
123
+ // Ignore malformed payloads (e.g. keep-alive comments).
124
+ }
125
+ }
126
+ }
127
+ scheduleReconnect() {
128
+ if (this.closed)
129
+ return;
130
+ const jitter = this.retryMs * SSE_JITTER_FRACTION * (2 * Math.random() - 1);
131
+ const delay = this.retryMs + jitter;
132
+ this.reconnectTimer = setTimeout(() => {
133
+ this.reconnectTimer = null;
134
+ this.connect();
135
+ }, delay);
136
+ this.retryMs = Math.min(this.retryMs * SSE_BACKOFF_MULTIPLIER, SSE_MAX_RETRY_MS);
137
+ }
138
+ }
139
+ exports.FlagStreamClient = FlagStreamClient;
140
+ //# sourceMappingURL=streaming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming.js","sourceRoot":"","sources":["../../src/streaming.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * DeploySentry SDK type definitions.
3
+ */
4
+ /** Categories that classify the intent and lifecycle of a feature flag. */
5
+ export type FlagCategory = 'release' | 'feature' | 'experiment' | 'ops' | 'permission';
6
+ /** Rich metadata attached to every feature flag. */
7
+ export interface FlagMetadata {
8
+ /** Categorisation that drives lifecycle policies. */
9
+ category: FlagCategory;
10
+ /** Human-readable explanation of what this flag controls. */
11
+ purpose: string;
12
+ /** Team or individual owners responsible for this flag. */
13
+ owners: string[];
14
+ /** When true the flag is not expected to be removed. */
15
+ isPermanent: boolean;
16
+ /** ISO-8601 expiration timestamp. Undefined for permanent flags. */
17
+ expiresAt?: string;
18
+ /** Free-form tags for filtering and grouping. */
19
+ tags: string[];
20
+ }
21
+ /** A feature flag as returned by the DeploySentry API. */
22
+ export interface Flag {
23
+ /** Unique key used to reference the flag in code. */
24
+ key: string;
25
+ /** Whether the flag is currently enabled. */
26
+ enabled: boolean;
27
+ /** The resolved value (boolean, string, number, or JSON object). */
28
+ value: unknown;
29
+ /** Rich metadata describing the flag. */
30
+ metadata: FlagMetadata;
31
+ /** ISO-8601 timestamp of the last update. */
32
+ updatedAt: string;
33
+ }
34
+ /** Contextual information sent with every evaluation request. */
35
+ export interface EvaluationContext {
36
+ /** Identifier of the user being evaluated. */
37
+ userId?: string;
38
+ /** Identifier of the organisation the user belongs to. */
39
+ orgId?: string;
40
+ /** Arbitrary key-value attributes for targeting rules. */
41
+ attributes?: Record<string, string>;
42
+ }
43
+ /** Full evaluation result including the resolved value and metadata. */
44
+ export interface EvaluationResult<T = unknown> {
45
+ /** The flag key that was evaluated. */
46
+ key: string;
47
+ /** The resolved value after evaluation. */
48
+ value: T;
49
+ /** Whether the flag is enabled for the given context. */
50
+ enabled: boolean;
51
+ /** Reason the value was resolved (e.g. "TARGETING_MATCH", "DEFAULT"). */
52
+ reason: string;
53
+ /** Rich metadata for the flag. */
54
+ metadata: FlagMetadata;
55
+ /** ISO-8601 evaluation timestamp. */
56
+ evaluatedAt: string;
57
+ }
58
+ /** Configuration options for the DeploySentry client. */
59
+ export interface ClientOptions {
60
+ /** API key used for authenticating with the DeploySentry service. */
61
+ apiKey: string;
62
+ /** Base URL of the DeploySentry API. Defaults to https://api.dr-sentry.com. */
63
+ baseURL?: string;
64
+ /** Environment identifier (e.g. "production", "staging"). */
65
+ environment: string;
66
+ /** Project identifier. */
67
+ project: string;
68
+ /** Application identifier. */
69
+ application: string;
70
+ /** Cache TTL in milliseconds. Defaults to 60 000 (1 minute). */
71
+ cacheTimeout?: number;
72
+ /** When true, the client returns default values without contacting the API. */
73
+ offlineMode?: boolean;
74
+ /** Optional session identifier for consistent flag evaluation across requests. */
75
+ sessionId?: string;
76
+ /** SDK mode: server (default), file (YAML only), or server-with-fallback. */
77
+ mode?: 'server' | 'file' | 'server-with-fallback';
78
+ /** Path to a local YAML flag config file. Defaults to .deploysentry/flags.yaml. */
79
+ flagFilePath?: string;
80
+ }
81
+ export interface FlagConfig {
82
+ version: number;
83
+ project: string;
84
+ application: string;
85
+ exported_at: string;
86
+ environments: FlagConfigEnvironment[];
87
+ flags: FlagConfigFlag[];
88
+ }
89
+ export interface FlagConfigEnvironment {
90
+ id: string;
91
+ name: string;
92
+ is_production: boolean;
93
+ }
94
+ export interface FlagConfigFlag {
95
+ key: string;
96
+ name: string;
97
+ flag_type: string;
98
+ category: string;
99
+ default_value: string;
100
+ is_permanent: boolean;
101
+ expires_at?: string;
102
+ environments: Record<string, {
103
+ enabled: boolean;
104
+ value: string;
105
+ }>;
106
+ rules?: FlagConfigRule[];
107
+ }
108
+ export interface FlagConfigRule {
109
+ attribute: string;
110
+ operator: string;
111
+ target_values: string[];
112
+ value: string;
113
+ priority: number;
114
+ environments: Record<string, boolean>;
115
+ }
116
+ /** Internal representation of an API error response. */
117
+ export interface ApiError {
118
+ status: number;
119
+ message: string;
120
+ code?: string;
121
+ }
122
+ export interface Registration<T extends (...args: any[]) => any = (...args: any[]) => any> {
123
+ handler: T;
124
+ flagKey?: string;
125
+ }
126
+ //# 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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"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * DeploySentry SDK type definitions.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";AAAA;;GAEG"}
@@ -0,0 +1,33 @@
1
+ import { Flag } from './types';
2
+ /**
3
+ * In-memory flag cache with per-entry TTL support.
4
+ *
5
+ * Entries are lazily evicted on read. A periodic sweep can be triggered
6
+ * via {@link purgeExpired} if deterministic memory reclamation is required.
7
+ */
8
+ export declare class FlagCache {
9
+ private readonly store;
10
+ private readonly ttlMs;
11
+ /**
12
+ * @param ttlMs - Time-to-live for every cache entry in milliseconds.
13
+ * Defaults to 60 000 (1 minute).
14
+ */
15
+ constructor(ttlMs?: number);
16
+ /** Store or update a single flag in the cache. */
17
+ set(flag: Flag): void;
18
+ /** Bulk-insert flags, replacing any stale entries. */
19
+ setMany(flags: Flag[]): void;
20
+ /** Retrieve a flag by key. Returns `undefined` if missing or expired. */
21
+ get(key: string): Flag | undefined;
22
+ /** Return all non-expired flags currently in the cache. */
23
+ getAll(): Flag[];
24
+ /** Remove a single key from the cache. */
25
+ delete(key: string): void;
26
+ /** Remove all expired entries. Returns the number of entries purged. */
27
+ purgeExpired(): number;
28
+ /** Drop every entry from the cache. */
29
+ clear(): void;
30
+ /** Number of entries (including potentially expired ones). */
31
+ get size(): number;
32
+ }
33
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAO/B;;;;;GAKG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IACvD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAE/B;;;OAGG;gBACS,KAAK,GAAE,MAAe;IAIlC,kDAAkD;IAClD,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAOrB,sDAAsD;IACtD,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI;IAM5B,yEAAyE;IACzE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAYlC,2DAA2D;IAC3D,MAAM,IAAI,IAAI,EAAE;IAehB,0CAA0C;IAC1C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB,wEAAwE;IACxE,YAAY,IAAI,MAAM;IActB,uCAAuC;IACvC,KAAK,IAAI,IAAI;IAIb,8DAA8D;IAC9D,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * In-memory flag cache with per-entry TTL support.
3
+ *
4
+ * Entries are lazily evicted on read. A periodic sweep can be triggered
5
+ * via {@link purgeExpired} if deterministic memory reclamation is required.
6
+ */
7
+ export class FlagCache {
8
+ store = new Map();
9
+ ttlMs;
10
+ /**
11
+ * @param ttlMs - Time-to-live for every cache entry in milliseconds.
12
+ * Defaults to 60 000 (1 minute).
13
+ */
14
+ constructor(ttlMs = 60_000) {
15
+ this.ttlMs = ttlMs;
16
+ }
17
+ /** Store or update a single flag in the cache. */
18
+ set(flag) {
19
+ this.store.set(flag.key, {
20
+ flag,
21
+ expiresAt: Date.now() + this.ttlMs,
22
+ });
23
+ }
24
+ /** Bulk-insert flags, replacing any stale entries. */
25
+ setMany(flags) {
26
+ for (const flag of flags) {
27
+ this.set(flag);
28
+ }
29
+ }
30
+ /** Retrieve a flag by key. Returns `undefined` if missing or expired. */
31
+ get(key) {
32
+ const entry = this.store.get(key);
33
+ if (!entry)
34
+ return undefined;
35
+ if (Date.now() > entry.expiresAt) {
36
+ this.store.delete(key);
37
+ return undefined;
38
+ }
39
+ return entry.flag;
40
+ }
41
+ /** Return all non-expired flags currently in the cache. */
42
+ getAll() {
43
+ const now = Date.now();
44
+ const result = [];
45
+ for (const [key, entry] of this.store) {
46
+ if (now > entry.expiresAt) {
47
+ this.store.delete(key);
48
+ }
49
+ else {
50
+ result.push(entry.flag);
51
+ }
52
+ }
53
+ return result;
54
+ }
55
+ /** Remove a single key from the cache. */
56
+ delete(key) {
57
+ this.store.delete(key);
58
+ }
59
+ /** Remove all expired entries. Returns the number of entries purged. */
60
+ purgeExpired() {
61
+ const now = Date.now();
62
+ let purged = 0;
63
+ for (const [key, entry] of this.store) {
64
+ if (now > entry.expiresAt) {
65
+ this.store.delete(key);
66
+ purged++;
67
+ }
68
+ }
69
+ return purged;
70
+ }
71
+ /** Drop every entry from the cache. */
72
+ clear() {
73
+ this.store.clear();
74
+ }
75
+ /** Number of entries (including potentially expired ones). */
76
+ get size() {
77
+ return this.store.size;
78
+ }
79
+ }
80
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,MAAM,OAAO,SAAS;IACH,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;IACtC,KAAK,CAAS;IAE/B;;;OAGG;IACH,YAAY,QAAgB,MAAM;QAChC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,kDAAkD;IAClD,GAAG,CAAC,IAAU;QACZ,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE;YACvB,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK;SACnC,CAAC,CAAC;IACL,CAAC;IAED,sDAAsD;IACtD,OAAO,CAAC,KAAa;QACnB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,GAAG,CAAC,GAAW;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAE7B,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IAED,2DAA2D;IAC3D,MAAM;QACJ,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAW,EAAE,CAAC;QAE1B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACtC,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;gBAC1B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,0CAA0C;IAC1C,MAAM,CAAC,GAAW;QAChB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,wEAAwE;IACxE,YAAY;QACV,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,MAAM,GAAG,CAAC,CAAC;QAEf,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACtC,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;gBAC1B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvB,MAAM,EAAE,CAAC;YACX,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,uCAAuC;IACvC,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,8DAA8D;IAC9D,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,81 @@
1
+ import { ClientOptions, EvaluationContext, EvaluationResult, Flag, FlagCategory } from './types';
2
+ /**
3
+ * DeploySentry feature-flag client.
4
+ *
5
+ * ```ts
6
+ * const client = new DeploySentryClient({
7
+ * apiKey: 'ds_live_xxx',
8
+ * environment: 'production',
9
+ * project: 'my-app',
10
+ * });
11
+ *
12
+ * await client.initialize();
13
+ *
14
+ * const darkMode = client.boolValue('dark-mode', false, { userId: 'u1' });
15
+ *
16
+ * client.close();
17
+ * ```
18
+ */
19
+ export declare class DeploySentryClient {
20
+ private readonly apiKey;
21
+ private readonly baseURL;
22
+ private readonly environment;
23
+ private readonly project;
24
+ private readonly application;
25
+ private readonly offlineMode;
26
+ private readonly sessionId;
27
+ private readonly mode;
28
+ private readonly flagFilePath?;
29
+ private readonly cache;
30
+ private streamClient;
31
+ private _initialized;
32
+ private flagConfig;
33
+ private registry;
34
+ constructor(options: ClientOptions);
35
+ /**
36
+ * Fetch the initial flag set and open an SSE connection for real-time
37
+ * updates. Must be called before evaluating flags.
38
+ */
39
+ initialize(): Promise<void>;
40
+ /** Tear down the SSE connection and release resources. */
41
+ close(): void;
42
+ /**
43
+ * Clear the local cache and re-fetch all flags from the server.
44
+ * Useful when session state may have changed and the client needs
45
+ * fresh evaluations.
46
+ */
47
+ refreshSession(): Promise<void>;
48
+ /** Whether {@link initialize} has been called successfully. */
49
+ get isInitialized(): boolean;
50
+ /** Evaluate a flag as a boolean. */
51
+ boolValue(key: string, defaultValue: boolean, context?: EvaluationContext): Promise<boolean>;
52
+ /** Evaluate a flag as a string. */
53
+ stringValue(key: string, defaultValue: string, context?: EvaluationContext): Promise<string>;
54
+ /** Evaluate a flag as an integer. */
55
+ intValue(key: string, defaultValue: number, context?: EvaluationContext): Promise<number>;
56
+ /** Evaluate a flag and return the value as a parsed JSON object. */
57
+ jsonValue<T = unknown>(key: string, defaultValue: T, context?: EvaluationContext): Promise<T>;
58
+ /**
59
+ * Return the full {@link EvaluationResult} for a flag including metadata,
60
+ * reason, and resolved value.
61
+ */
62
+ detail(key: string, context?: EvaluationContext): Promise<EvaluationResult>;
63
+ /** Return all cached flags belonging to a given category. */
64
+ flagsByCategory(category: FlagCategory): Flag[];
65
+ /** Return all cached flags whose `expiresAt` is in the past. */
66
+ expiredFlags(): Flag[];
67
+ /** Return the owners array for a given flag key. */
68
+ flagOwners(key: string): string[];
69
+ /** Return every flag currently held in the local cache. */
70
+ allFlags(): Flag[];
71
+ register<T extends (...args: any[]) => any>(operation: string, handler: T, flagKey?: string): void;
72
+ dispatch<T extends (...args: any[]) => any>(operation: string, _context?: EvaluationContext): T;
73
+ private evaluate;
74
+ private fetchAllFlags;
75
+ private post;
76
+ private request;
77
+ private authHeaders;
78
+ private offlineResult;
79
+ private cachedResult;
80
+ }
81
+ //# 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,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,IAAI,EACJ,YAAY,EAEb,MAAM,SAAS,CAAC;AAUjB;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA6C;IAClE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAS;IAEvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAY;IAClC,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,QAAQ,CAA0C;gBAE9C,OAAO,EAAE,aAAa;IAuBlC;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA0CjC,0DAA0D;IAC1D,KAAK,IAAI,IAAI;IAOb;;;;OAIG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAQrC,+DAA+D;IAC/D,IAAI,aAAa,IAAI,OAAO,CAE3B;IAMD,oCAAoC;IAC9B,SAAS,CACb,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,OAAO,EACrB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,OAAO,CAAC;IAcnB,mCAAmC;IAC7B,WAAW,CACf,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC;IAKlB,qCAAqC;IAC/B,QAAQ,CACZ,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC;IAOlB,oEAAoE;IAC9D,SAAS,CAAC,CAAC,GAAG,OAAO,EACzB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,CAAC,EACf,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,CAAC,CAAC;IASb;;;OAGG;IACG,MAAM,CACV,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,gBAAgB,CAAC;IA2B5B,6DAA6D;IAC7D,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,EAAE;IAI/C,gEAAgE;IAChE,YAAY,IAAI,IAAI,EAAE;IAOtB,oDAAoD;IACpD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE;IAKjC,2DAA2D;IAC3D,QAAQ,IAAI,IAAI,EAAE;IAQlB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACxC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,EACV,OAAO,CAAC,EAAE,MAAM,GACf,IAAI;IAeP,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACxC,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,CAAC;YA0BU,QAAQ;YAkCR,aAAa;YAQb,IAAI;YAIJ,OAAO;IAgCrB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,YAAY;CAmBrB"}