@dr-sentry/sdk 1.0.4 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -4
- package/dist/cjs/cache.d.ts +16 -0
- package/dist/cjs/cache.d.ts.map +1 -1
- package/dist/cjs/cache.js +21 -1
- package/dist/cjs/cache.js.map +1 -1
- package/dist/cjs/client.d.ts +46 -1
- package/dist/cjs/client.d.ts.map +1 -1
- package/dist/cjs/client.js +236 -9
- package/dist/cjs/client.js.map +1 -1
- package/dist/cjs/defaults.d.ts +58 -0
- package/dist/cjs/defaults.d.ts.map +1 -0
- package/dist/cjs/defaults.js +175 -0
- package/dist/cjs/defaults.js.map +1 -0
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/status-reporter.d.ts +42 -0
- package/dist/cjs/status-reporter.d.ts.map +1 -0
- package/dist/cjs/status-reporter.js +153 -0
- package/dist/cjs/status-reporter.js.map +1 -0
- package/dist/cjs/streaming.d.ts +8 -2
- package/dist/cjs/streaming.d.ts.map +1 -1
- package/dist/cjs/streaming.js +17 -4
- package/dist/cjs/streaming.js.map +1 -1
- package/dist/cjs/types.d.ts +65 -0
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/esm/cache.d.ts +16 -0
- package/dist/esm/cache.d.ts.map +1 -1
- package/dist/esm/cache.js +21 -1
- package/dist/esm/cache.js.map +1 -1
- package/dist/esm/client.d.ts +46 -1
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +236 -9
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/defaults.d.ts +58 -0
- package/dist/esm/defaults.d.ts.map +1 -0
- package/dist/esm/defaults.js +136 -0
- package/dist/esm/defaults.js.map +1 -0
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/status-reporter.d.ts +42 -0
- package/dist/esm/status-reporter.d.ts.map +1 -0
- package/dist/esm/status-reporter.js +148 -0
- package/dist/esm/status-reporter.js.map +1 -0
- package/dist/esm/streaming.d.ts +8 -2
- package/dist/esm/streaming.d.ts.map +1 -1
- package/dist/esm/streaming.js +17 -4
- package/dist/esm/streaming.js.map +1 -1
- package/dist/esm/types.d.ts +65 -0
- package/dist/esm/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streaming.js","sourceRoot":"","sources":["../../src/streaming.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"streaming.js","sourceRoot":"","sources":["../../src/streaming.ts"],"names":[],"mappings":";;;AAaA,MAAM,oBAAoB,GAAG,KAAK,CAAC;AACnC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAChC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AACjC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAahC;;;;;;GAMG;AACH,MAAa,gBAAgB;IACnB,eAAe,GAA2B,IAAI,CAAC;IAC/C,cAAc,GAAyC,IAAI,CAAC;IAC5D,MAAM,GAAG,KAAK,CAAC;IACf,OAAO,GAAG,oBAAoB,CAAC;IAEtB,GAAG,CAAS;IACZ,OAAO,CAAyB;IAChC,QAAQ,CAAoB;IAC5B,OAAO,CAAqB;IAE7C,YAAY,OAAsB;QAChC,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,2DAA2D;IAC3D,KAAK,CAAC,OAAO;QACX,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QAExB,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAE7C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;gBACrC,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,GAAG,IAAI,CAAC,OAAO;oBACf,MAAM,EAAE,mBAAmB;oBAC3B,eAAe,EAAE,UAAU;iBAC5B;gBACD,MAAM,EAAE,IAAI,CAAC,eAAe,CAAC,MAAM;aACpC,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CACb,0BAA0B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CACnE,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;YAC9C,CAAC;YAED,IAAI,CAAC,OAAO,GAAG,oBAAoB,CAAC;YACpC,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,IAAI,IAAI,CAAC,MAAM;gBAAE,OAAO;YAExB,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAClE,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;gBAAE,OAAO;YAExC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,2DAA2D;IAC3D,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;QAED,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;YAC7B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,YAAY;IACZ,8EAA8E;IAEtE,KAAK,CAAC,aAAa,CAAC,IAAgC;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACpB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5C,IAAI,IAAI;oBAAE,MAAM;gBAEhB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;gBAElD,+CAA+C;gBAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACnC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;gBAE3B,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;oBACxB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,CAAC;QAED,oEAAoE;QACpE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,GAAW;QAC9B,IAAI,SAAS,GAAG,SAAS,CAAC;QAC1B,IAAI,IAAI,GAAG,EAAE,CAAC;QAEd,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9B,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACnC,CAAC;iBAAM,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC/B,CAAC;iBAAM,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAChC,oCAAoC;gBACpC,OAAO;YACT,CAAC;QACH,CAAC;QAED,IAAI,SAAS,KAAK,aAAa,IAAI,SAAS,KAAK,aAAa,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC1F,IAAI,MAAM,GAAoB,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;YACrE,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAChC,MAAM,GAAG;oBACP,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE;oBACzB,MAAM,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;oBAC5B,OAAO,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE;iBAC/B,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACP,sDAAsD;YACxD,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAEO,iBAAiB;QACvB,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QAExB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,GAAG,mBAAmB,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;QAC5E,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QAEpC,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE;YACpC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC3B,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC,EAAE,KAAK,CAAC,CAAC;QAEV,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CACrB,IAAI,CAAC,OAAO,GAAG,sBAAsB,EACrC,gBAAgB,CACjB,CAAC;IACJ,CAAC;CACF;AA1JD,4CA0JC"}
|
package/dist/cjs/types.d.ts
CHANGED
|
@@ -31,6 +31,40 @@ export interface Flag {
|
|
|
31
31
|
/** ISO-8601 timestamp of the last update. */
|
|
32
32
|
updatedAt: string;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Where an inspected flag's current value originated.
|
|
36
|
+
*
|
|
37
|
+
* - `server` — fetched live from the API and still within its cache TTL.
|
|
38
|
+
* - `cache` — a previously-fetched server value whose TTL has elapsed but
|
|
39
|
+
* is still being served (server currently unreachable).
|
|
40
|
+
* - `file` — an offline file: a `mode: 'file'` config, or the offline
|
|
41
|
+
* defaults loaded via `loadDefaults*()` used as a fallback.
|
|
42
|
+
* - `default`— no value from any source; callers receive their coded default.
|
|
43
|
+
*/
|
|
44
|
+
export type FlagSource = 'server' | 'cache' | 'file' | 'default';
|
|
45
|
+
/**
|
|
46
|
+
* A read-only view of a single flag's resolved value and provenance,
|
|
47
|
+
* suitable for wiring into an admin or support panel. Produced by
|
|
48
|
+
* {@link DeploySentryClient.inspect}.
|
|
49
|
+
*/
|
|
50
|
+
export interface FlagInspection {
|
|
51
|
+
/** The flag key. */
|
|
52
|
+
key: string;
|
|
53
|
+
/** The currently-resolved value (parsed to its declared type). */
|
|
54
|
+
value: unknown;
|
|
55
|
+
/** The flag's value type. `unknown` when it cannot be determined. */
|
|
56
|
+
type: 'boolean' | 'integer' | 'number' | 'string' | 'json' | 'unknown';
|
|
57
|
+
/** Whether the flag is enabled in the resolved environment. */
|
|
58
|
+
enabled: boolean;
|
|
59
|
+
/** Where {@link value} came from. */
|
|
60
|
+
source: FlagSource;
|
|
61
|
+
/** Evaluation reason code (e.g. LIVE, CACHE, OFFLINE_FILE, OFFLINE_DEFAULT, DEFAULT). */
|
|
62
|
+
reason: string;
|
|
63
|
+
/** ISO-8601 timestamp the value was last fetched / loaded. Undefined for `default`. */
|
|
64
|
+
fetchedAt?: string;
|
|
65
|
+
/** True when {@link source} is `cache` and the entry is past its TTL. */
|
|
66
|
+
stale: boolean;
|
|
67
|
+
}
|
|
34
68
|
/** Contextual information sent with every evaluation request. */
|
|
35
69
|
export interface EvaluationContext {
|
|
36
70
|
/** Identifier of the user being evaluated. */
|
|
@@ -77,6 +111,37 @@ export interface ClientOptions {
|
|
|
77
111
|
mode?: 'server' | 'file' | 'server-with-fallback';
|
|
78
112
|
/** Path to a local YAML flag config file. Defaults to .deploysentry/flags.yaml. */
|
|
79
113
|
flagFilePath?: string;
|
|
114
|
+
/** Called whenever the flag cache is refreshed from an SSE change event. */
|
|
115
|
+
onFlagChange?: (flags: Flag[]) => void;
|
|
116
|
+
/**
|
|
117
|
+
* Application UUID. Required when `reportStatus` is true. Distinct from
|
|
118
|
+
* `application` (the slug used for flag evaluation) because the status
|
|
119
|
+
* endpoint is keyed on the UUID.
|
|
120
|
+
*/
|
|
121
|
+
applicationId?: string;
|
|
122
|
+
/** Enable the status reporter. Default: false. */
|
|
123
|
+
reportStatus?: boolean;
|
|
124
|
+
/** Interval in ms between status reports. Default: 30_000. 0 = send once on init. */
|
|
125
|
+
reportStatusIntervalMs?: number;
|
|
126
|
+
/** Override the auto-detected version string. */
|
|
127
|
+
reportStatusVersion?: string;
|
|
128
|
+
/** Commit SHA reported alongside the version. */
|
|
129
|
+
reportStatusCommitSha?: string;
|
|
130
|
+
/** Optional deploy-slot tag (`stable` / `canary`). */
|
|
131
|
+
reportStatusDeploySlot?: string;
|
|
132
|
+
/** Arbitrary tags attached to every report. */
|
|
133
|
+
reportStatusTags?: Record<string, string>;
|
|
134
|
+
/**
|
|
135
|
+
* Optional callback resolving the current health. If omitted the reporter
|
|
136
|
+
* sends `state: 'healthy'` on every tick (the "process alive" floor).
|
|
137
|
+
*/
|
|
138
|
+
reportStatusHealthProvider?: () => HealthReport | Promise<HealthReport>;
|
|
139
|
+
}
|
|
140
|
+
/** Shape returned by a status reporter's health provider. */
|
|
141
|
+
export interface HealthReport {
|
|
142
|
+
state: 'healthy' | 'degraded' | 'unhealthy' | 'unknown';
|
|
143
|
+
score?: number;
|
|
144
|
+
reason?: string;
|
|
80
145
|
}
|
|
81
146
|
export interface FlagConfig {
|
|
82
147
|
version: number;
|
package/dist/cjs/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,2EAA2E;AAC3E,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,KAAK,GAAG,YAAY,CAAC;AAEvF,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,QAAQ,EAAE,YAAY,CAAC;IACvB,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,wDAAwD;IACxD,WAAW,EAAE,OAAO,CAAC;IACrB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,0DAA0D;AAC1D,MAAM,WAAW,IAAI;IACnB,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ,6CAA6C;IAC7C,OAAO,EAAE,OAAO,CAAC;IACjB,oEAAoE;IACpE,KAAK,EAAE,OAAO,CAAC;IACf,yCAAyC;IACzC,QAAQ,EAAE,YAAY,CAAC;IACvB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,wEAAwE;AACxE,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,OAAO;IAC3C,uCAAuC;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,KAAK,EAAE,CAAC,CAAC;IACT,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAC;IACjB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,QAAQ,EAAE,YAAY,CAAC;IACvB,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,sBAAsB,CAAC;IAClD,mFAAmF;IACnF,YAAY,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/cache.d.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { Flag } from './types.js';
|
|
2
|
+
/** A cache entry exposed for inspection, including staleness. */
|
|
3
|
+
export interface CacheInspectionEntry {
|
|
4
|
+
flag: Flag;
|
|
5
|
+
/** Epoch-ms when the entry was last written. */
|
|
6
|
+
storedAt: number;
|
|
7
|
+
/** Epoch-ms when the entry's TTL elapses. */
|
|
8
|
+
expiresAt: number;
|
|
9
|
+
/** True when the TTL has elapsed but the entry is still held. */
|
|
10
|
+
stale: boolean;
|
|
11
|
+
}
|
|
2
12
|
/**
|
|
3
13
|
* In-memory flag cache with per-entry TTL support.
|
|
4
14
|
*
|
|
@@ -21,6 +31,12 @@ export declare class FlagCache {
|
|
|
21
31
|
get(key: string): Flag | undefined;
|
|
22
32
|
/** Return all non-expired flags currently in the cache. */
|
|
23
33
|
getAll(): Flag[];
|
|
34
|
+
/**
|
|
35
|
+
* Return every entry held in the cache — including stale (TTL-elapsed)
|
|
36
|
+
* entries — without evicting anything. For inspection / admin views only;
|
|
37
|
+
* read paths should use {@link get} / {@link getAll} which evict.
|
|
38
|
+
*/
|
|
39
|
+
entries(): CacheInspectionEntry[];
|
|
24
40
|
/** Remove a single key from the cache. */
|
|
25
41
|
delete(key: string): void;
|
|
26
42
|
/** Remove all expired entries. Returns the number of entries purged. */
|
package/dist/esm/cache.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAQ/B,iEAAiE;AACjE,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,IAAI,CAAC;IACX,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;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;IASrB,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;;;;OAIG;IACH,OAAO,IAAI,oBAAoB,EAAE;IAcjC,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"}
|
package/dist/esm/cache.js
CHANGED
|
@@ -16,9 +16,11 @@ export class FlagCache {
|
|
|
16
16
|
}
|
|
17
17
|
/** Store or update a single flag in the cache. */
|
|
18
18
|
set(flag) {
|
|
19
|
+
const now = Date.now();
|
|
19
20
|
this.store.set(flag.key, {
|
|
20
21
|
flag,
|
|
21
|
-
|
|
22
|
+
storedAt: now,
|
|
23
|
+
expiresAt: now + this.ttlMs,
|
|
22
24
|
});
|
|
23
25
|
}
|
|
24
26
|
/** Bulk-insert flags, replacing any stale entries. */
|
|
@@ -52,6 +54,24 @@ export class FlagCache {
|
|
|
52
54
|
}
|
|
53
55
|
return result;
|
|
54
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Return every entry held in the cache — including stale (TTL-elapsed)
|
|
59
|
+
* entries — without evicting anything. For inspection / admin views only;
|
|
60
|
+
* read paths should use {@link get} / {@link getAll} which evict.
|
|
61
|
+
*/
|
|
62
|
+
entries() {
|
|
63
|
+
const now = Date.now();
|
|
64
|
+
const result = [];
|
|
65
|
+
for (const entry of this.store.values()) {
|
|
66
|
+
result.push({
|
|
67
|
+
flag: entry.flag,
|
|
68
|
+
storedAt: entry.storedAt,
|
|
69
|
+
expiresAt: entry.expiresAt,
|
|
70
|
+
stale: now > entry.expiresAt,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
55
75
|
/** Remove a single key from the cache. */
|
|
56
76
|
delete(key) {
|
|
57
77
|
this.store.delete(key);
|
package/dist/esm/cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/cache.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ClientOptions, EvaluationContext, EvaluationResult, Flag, FlagCategory } from './types.js';
|
|
1
|
+
import { ClientOptions, EvaluationContext, EvaluationResult, Flag, FlagCategory, FlagInspection } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* DeploySentry feature-flag client.
|
|
4
4
|
*
|
|
@@ -26,11 +26,18 @@ export declare class DeploySentryClient {
|
|
|
26
26
|
private readonly sessionId;
|
|
27
27
|
private readonly mode;
|
|
28
28
|
private readonly flagFilePath?;
|
|
29
|
+
private readonly onFlagChange?;
|
|
29
30
|
private readonly cache;
|
|
30
31
|
private streamClient;
|
|
31
32
|
private _initialized;
|
|
32
33
|
private flagConfig;
|
|
34
|
+
private offlineDefaults;
|
|
35
|
+
private offlineDefaultsEnvUUID;
|
|
36
|
+
private flagConfigLoadedAt?;
|
|
37
|
+
private offlineDefaultsLoadedAt?;
|
|
33
38
|
private registry;
|
|
39
|
+
private statusReporter;
|
|
40
|
+
private readonly statusReporterOptions;
|
|
34
41
|
constructor(options: ClientOptions);
|
|
35
42
|
/**
|
|
36
43
|
* Fetch the initial flag set and open an SSE connection for real-time
|
|
@@ -39,6 +46,7 @@ export declare class DeploySentryClient {
|
|
|
39
46
|
initialize(): Promise<void>;
|
|
40
47
|
/** Tear down the SSE connection and release resources. */
|
|
41
48
|
close(): void;
|
|
49
|
+
private startStatusReporter;
|
|
42
50
|
/**
|
|
43
51
|
* Clear the local cache and re-fetch all flags from the server.
|
|
44
52
|
* Useful when session state may have changed and the client needs
|
|
@@ -68,10 +76,47 @@ export declare class DeploySentryClient {
|
|
|
68
76
|
flagOwners(key: string): string[];
|
|
69
77
|
/** Return every flag currently held in the local cache. */
|
|
70
78
|
allFlags(): Flag[];
|
|
79
|
+
/**
|
|
80
|
+
* Return a provenance-tagged view of every flag the SDK currently knows
|
|
81
|
+
* about, drawn from all sources (live server cache, offline file config,
|
|
82
|
+
* and offline defaults). Each entry reports the resolved value, its type,
|
|
83
|
+
* the {@link FlagSource | source} it came from, an evaluation reason code,
|
|
84
|
+
* and when it was last fetched / loaded.
|
|
85
|
+
*
|
|
86
|
+
* Intended for wiring into an admin or support panel so operators can see
|
|
87
|
+
* exactly what value an application is serving and where it came from. This
|
|
88
|
+
* is a read-only snapshot — it does not contact the server or evaluate
|
|
89
|
+
* targeting rules for a specific user.
|
|
90
|
+
*/
|
|
91
|
+
inspect(): FlagInspection[];
|
|
71
92
|
register<T extends (...args: any[]) => any>(operation: string, handler: T, flagKey?: string): void;
|
|
72
93
|
dispatch<T extends (...args: any[]) => any>(operation: string, _context?: EvaluationContext): T;
|
|
73
94
|
private evaluate;
|
|
95
|
+
/**
|
|
96
|
+
* Load offline default values from a flag-export file. When the live API
|
|
97
|
+
* is unreachable and the cache has no entry, the SDK falls back to these
|
|
98
|
+
* defaults for {@link boolValue} / {@link stringValue} / {@link intValue}
|
|
99
|
+
* / {@link jsonValue} calls.
|
|
100
|
+
*
|
|
101
|
+
* Accepts the JSON (default) or YAML format produced by
|
|
102
|
+
* `deploysentry flags export`.
|
|
103
|
+
*
|
|
104
|
+
* Environment matching: the SDK matches the configured `environment`
|
|
105
|
+
* option against the export's `environments[]` first by UUID, then by
|
|
106
|
+
* name (case-insensitive). When a match is found, that env's per-flag
|
|
107
|
+
* `{enabled, value}` overrides the flag's global `default_value`.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* await client.loadDefaultsFromFile('flags.json');
|
|
111
|
+
*/
|
|
112
|
+
loadDefaultsFromFile(path: string): Promise<void>;
|
|
113
|
+
/**
|
|
114
|
+
* Synchronous variant of {@link loadDefaultsFromFile} that accepts an
|
|
115
|
+
* already-parsed object (or a JSON string).
|
|
116
|
+
*/
|
|
117
|
+
loadDefaults(payload: unknown): void;
|
|
74
118
|
private fetchAllFlags;
|
|
119
|
+
private fetchFlag;
|
|
75
120
|
private post;
|
|
76
121
|
private request;
|
|
77
122
|
private authHeaders;
|
package/dist/esm/client.d.ts.map
CHANGED
|
@@ -1 +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,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/client.js
CHANGED
|
@@ -2,13 +2,32 @@ import { FlagCache } from './cache.js';
|
|
|
2
2
|
import { FlagStreamClient } from './streaming.js';
|
|
3
3
|
import { loadFlagConfig } from './file-loader.js';
|
|
4
4
|
import { evaluateLocal } from './local-evaluator.js';
|
|
5
|
+
import { coerceOfflineValue, lookupOfflineDefault, parseDefaults, readDefaultsFile, } from './defaults.js';
|
|
6
|
+
import { StatusReporter } from './status-reporter.js';
|
|
5
7
|
const DEFAULT_BASE_URL = 'https://api.dr-sentry.com';
|
|
8
|
+
/** Parse a string value into its typed representation based on flag_type. */
|
|
9
|
+
function parseValue(raw, flagType) {
|
|
10
|
+
if (!raw && raw !== '0')
|
|
11
|
+
return undefined;
|
|
12
|
+
switch (flagType) {
|
|
13
|
+
case 'boolean': return raw === 'true';
|
|
14
|
+
case 'integer':
|
|
15
|
+
case 'number': return Number(raw);
|
|
16
|
+
case 'json': try {
|
|
17
|
+
return JSON.parse(raw);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return raw;
|
|
21
|
+
}
|
|
22
|
+
default: return raw;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
6
25
|
/** Map the API's snake_case flag response to the SDK's Flag type. */
|
|
7
26
|
function mapRawFlag(raw) {
|
|
8
27
|
return {
|
|
9
28
|
key: raw.key,
|
|
10
29
|
enabled: raw.enabled,
|
|
11
|
-
value: raw.default_value,
|
|
30
|
+
value: parseValue(raw.default_value, raw.flag_type),
|
|
12
31
|
metadata: {
|
|
13
32
|
category: raw.category,
|
|
14
33
|
purpose: raw.purpose ?? '',
|
|
@@ -48,11 +67,18 @@ export class DeploySentryClient {
|
|
|
48
67
|
sessionId;
|
|
49
68
|
mode;
|
|
50
69
|
flagFilePath;
|
|
70
|
+
onFlagChange;
|
|
51
71
|
cache;
|
|
52
72
|
streamClient = null;
|
|
53
73
|
_initialized = false;
|
|
54
74
|
flagConfig = null;
|
|
75
|
+
offlineDefaults = null;
|
|
76
|
+
offlineDefaultsEnvUUID = '';
|
|
77
|
+
flagConfigLoadedAt;
|
|
78
|
+
offlineDefaultsLoadedAt;
|
|
55
79
|
registry = new Map();
|
|
80
|
+
statusReporter = null;
|
|
81
|
+
statusReporterOptions;
|
|
56
82
|
constructor(options) {
|
|
57
83
|
if (!options.apiKey)
|
|
58
84
|
throw new Error('apiKey is required');
|
|
@@ -71,7 +97,9 @@ export class DeploySentryClient {
|
|
|
71
97
|
this.sessionId = options.sessionId;
|
|
72
98
|
this.mode = options.mode ?? 'server';
|
|
73
99
|
this.flagFilePath = options.flagFilePath;
|
|
100
|
+
this.onFlagChange = options.onFlagChange;
|
|
74
101
|
this.cache = new FlagCache(options.cacheTimeout ?? DEFAULT_CACHE_TIMEOUT_MS);
|
|
102
|
+
this.statusReporterOptions = options;
|
|
75
103
|
}
|
|
76
104
|
// ---------------------------------------------------------------------------
|
|
77
105
|
// Lifecycle
|
|
@@ -83,6 +111,7 @@ export class DeploySentryClient {
|
|
|
83
111
|
async initialize() {
|
|
84
112
|
if (this.mode === 'file') {
|
|
85
113
|
this.flagConfig = loadFlagConfig(this.flagFilePath);
|
|
114
|
+
this.flagConfigLoadedAt = new Date().toISOString();
|
|
86
115
|
this._initialized = true;
|
|
87
116
|
return;
|
|
88
117
|
}
|
|
@@ -94,13 +123,21 @@ export class DeploySentryClient {
|
|
|
94
123
|
// Fetch all flags for the project so the cache is warm.
|
|
95
124
|
const flags = await this.fetchAllFlags();
|
|
96
125
|
this.cache.setMany(flags);
|
|
97
|
-
// Start streaming updates.
|
|
126
|
+
// Start streaming updates. Each SSE event identifies the changed flag
|
|
127
|
+
// by ID — fetch just that flag to get the authoritative state.
|
|
98
128
|
this.streamClient = new FlagStreamClient({
|
|
99
129
|
url: `${this.baseURL}/api/v1/flags/stream?project_id=${enc(this.project)}&environment_id=${enc(this.environment)}&application=${enc(this.application)}`,
|
|
100
130
|
headers: this.authHeaders(),
|
|
101
|
-
onChange: () => {
|
|
102
|
-
|
|
103
|
-
|
|
131
|
+
onChange: (change) => {
|
|
132
|
+
if (!change.flagId)
|
|
133
|
+
return;
|
|
134
|
+
this.fetchFlag(change.flagId)
|
|
135
|
+
.then((flag) => {
|
|
136
|
+
if (flag) {
|
|
137
|
+
this.cache.set(flag);
|
|
138
|
+
this.onFlagChange?.([flag]);
|
|
139
|
+
}
|
|
140
|
+
})
|
|
104
141
|
.catch(() => { }); // stale cache still serves
|
|
105
142
|
},
|
|
106
143
|
onError: (err) => {
|
|
@@ -111,11 +148,13 @@ export class DeploySentryClient {
|
|
|
111
148
|
// Fire-and-forget; the stream reconnects automatically.
|
|
112
149
|
this.streamClient.connect();
|
|
113
150
|
this._initialized = true;
|
|
151
|
+
this.startStatusReporter();
|
|
114
152
|
}
|
|
115
153
|
catch (err) {
|
|
116
154
|
if (this.mode === 'server-with-fallback') {
|
|
117
155
|
console.warn('[DeploySentry] Server unavailable, falling back to flag config file');
|
|
118
156
|
this.flagConfig = loadFlagConfig(this.flagFilePath);
|
|
157
|
+
this.flagConfigLoadedAt = new Date().toISOString();
|
|
119
158
|
this._initialized = true;
|
|
120
159
|
return;
|
|
121
160
|
}
|
|
@@ -126,9 +165,32 @@ export class DeploySentryClient {
|
|
|
126
165
|
close() {
|
|
127
166
|
this.streamClient?.close();
|
|
128
167
|
this.streamClient = null;
|
|
168
|
+
this.statusReporter?.stop();
|
|
169
|
+
this.statusReporter = null;
|
|
129
170
|
this.cache.clear();
|
|
130
171
|
this._initialized = false;
|
|
131
172
|
}
|
|
173
|
+
startStatusReporter() {
|
|
174
|
+
const o = this.statusReporterOptions;
|
|
175
|
+
if (!o.reportStatus)
|
|
176
|
+
return;
|
|
177
|
+
if (!o.applicationId) {
|
|
178
|
+
console.warn('[DeploySentry] reportStatus=true but applicationId is not set; status reporter disabled');
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
this.statusReporter = new StatusReporter({
|
|
182
|
+
baseURL: this.baseURL,
|
|
183
|
+
apiKey: this.apiKey,
|
|
184
|
+
applicationId: o.applicationId,
|
|
185
|
+
intervalMs: o.reportStatusIntervalMs,
|
|
186
|
+
version: o.reportStatusVersion,
|
|
187
|
+
commitSha: o.reportStatusCommitSha,
|
|
188
|
+
deploySlot: o.reportStatusDeploySlot,
|
|
189
|
+
tags: o.reportStatusTags,
|
|
190
|
+
healthProvider: o.reportStatusHealthProvider,
|
|
191
|
+
});
|
|
192
|
+
this.statusReporter.start();
|
|
193
|
+
}
|
|
132
194
|
/**
|
|
133
195
|
* Clear the local cache and re-fetch all flags from the server.
|
|
134
196
|
* Useful when session state may have changed and the client needs
|
|
@@ -231,6 +293,72 @@ export class DeploySentryClient {
|
|
|
231
293
|
allFlags() {
|
|
232
294
|
return this.cache.getAll();
|
|
233
295
|
}
|
|
296
|
+
/**
|
|
297
|
+
* Return a provenance-tagged view of every flag the SDK currently knows
|
|
298
|
+
* about, drawn from all sources (live server cache, offline file config,
|
|
299
|
+
* and offline defaults). Each entry reports the resolved value, its type,
|
|
300
|
+
* the {@link FlagSource | source} it came from, an evaluation reason code,
|
|
301
|
+
* and when it was last fetched / loaded.
|
|
302
|
+
*
|
|
303
|
+
* Intended for wiring into an admin or support panel so operators can see
|
|
304
|
+
* exactly what value an application is serving and where it came from. This
|
|
305
|
+
* is a read-only snapshot — it does not contact the server or evaluate
|
|
306
|
+
* targeting rules for a specific user.
|
|
307
|
+
*/
|
|
308
|
+
inspect() {
|
|
309
|
+
const byKey = new Map();
|
|
310
|
+
// 1) Server cache (live + stale). Highest-fidelity source; recorded first.
|
|
311
|
+
for (const e of this.cache.entries()) {
|
|
312
|
+
byKey.set(e.flag.key, {
|
|
313
|
+
key: e.flag.key,
|
|
314
|
+
value: e.flag.value,
|
|
315
|
+
type: typeOfValue(e.flag.value),
|
|
316
|
+
enabled: e.flag.enabled,
|
|
317
|
+
source: e.stale ? 'cache' : 'server',
|
|
318
|
+
reason: e.stale ? 'CACHE' : 'LIVE',
|
|
319
|
+
fetchedAt: new Date(e.storedAt).toISOString(),
|
|
320
|
+
stale: e.stale,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
// 2) Offline file config (mode 'file' or fallback). Only fills gaps.
|
|
324
|
+
if (this.flagConfig) {
|
|
325
|
+
for (const f of this.flagConfig.flags) {
|
|
326
|
+
if (byKey.has(f.key))
|
|
327
|
+
continue;
|
|
328
|
+
const result = evaluateLocal(this.flagConfig, this.environment, f.key);
|
|
329
|
+
const envState = f.environments[this.environment];
|
|
330
|
+
byKey.set(f.key, {
|
|
331
|
+
key: f.key,
|
|
332
|
+
value: parseValue(result.value, f.flag_type),
|
|
333
|
+
type: typeOfFlagType(f.flag_type),
|
|
334
|
+
enabled: envState?.enabled ?? false,
|
|
335
|
+
source: 'file',
|
|
336
|
+
reason: 'OFFLINE_FILE',
|
|
337
|
+
fetchedAt: this.flagConfigLoadedAt,
|
|
338
|
+
stale: false,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
// 3) Offline defaults loaded via loadDefaults*(). Only fills gaps.
|
|
343
|
+
if (this.offlineDefaults) {
|
|
344
|
+
for (const [key, def] of this.offlineDefaults) {
|
|
345
|
+
if (byKey.has(key))
|
|
346
|
+
continue;
|
|
347
|
+
const resolved = lookupOfflineDefault(this.offlineDefaults, this.offlineDefaultsEnvUUID, key);
|
|
348
|
+
byKey.set(key, {
|
|
349
|
+
key,
|
|
350
|
+
value: resolved ? parseValue(resolved.value, def.flagType) : undefined,
|
|
351
|
+
type: typeOfFlagType(def.flagType),
|
|
352
|
+
enabled: resolved?.enabled ?? false,
|
|
353
|
+
source: 'file',
|
|
354
|
+
reason: 'OFFLINE_DEFAULT',
|
|
355
|
+
fetchedAt: this.offlineDefaultsLoadedAt,
|
|
356
|
+
stale: false,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return [...byKey.values()];
|
|
361
|
+
}
|
|
234
362
|
// ---------------------------------------------------------------------------
|
|
235
363
|
// Register / Dispatch
|
|
236
364
|
// ---------------------------------------------------------------------------
|
|
@@ -294,14 +422,78 @@ export class DeploySentryClient {
|
|
|
294
422
|
return result.value;
|
|
295
423
|
}
|
|
296
424
|
catch {
|
|
297
|
-
//
|
|
425
|
+
// 1) Cached value (from a prior live call) wins over offline defaults.
|
|
298
426
|
const cached = this.cache.get(key);
|
|
299
|
-
|
|
427
|
+
if (cached?.value !== undefined)
|
|
428
|
+
return cached.value;
|
|
429
|
+
// 2) Offline defaults loaded via loadDefaults*().
|
|
430
|
+
const offline = this.offlineDefaults
|
|
431
|
+
? lookupOfflineDefault(this.offlineDefaults, this.offlineDefaultsEnvUUID, key)
|
|
432
|
+
: undefined;
|
|
433
|
+
if (offline) {
|
|
434
|
+
const requested = inferRequestedType(defaultValue);
|
|
435
|
+
const coerced = coerceOfflineValue(offline.value, requested);
|
|
436
|
+
if (coerced !== undefined)
|
|
437
|
+
return coerced;
|
|
438
|
+
}
|
|
439
|
+
return defaultValue;
|
|
300
440
|
}
|
|
301
441
|
}
|
|
442
|
+
// ---------------------------------------------------------------------------
|
|
443
|
+
// Offline defaults
|
|
444
|
+
// ---------------------------------------------------------------------------
|
|
445
|
+
/**
|
|
446
|
+
* Load offline default values from a flag-export file. When the live API
|
|
447
|
+
* is unreachable and the cache has no entry, the SDK falls back to these
|
|
448
|
+
* defaults for {@link boolValue} / {@link stringValue} / {@link intValue}
|
|
449
|
+
* / {@link jsonValue} calls.
|
|
450
|
+
*
|
|
451
|
+
* Accepts the JSON (default) or YAML format produced by
|
|
452
|
+
* `deploysentry flags export`.
|
|
453
|
+
*
|
|
454
|
+
* Environment matching: the SDK matches the configured `environment`
|
|
455
|
+
* option against the export's `environments[]` first by UUID, then by
|
|
456
|
+
* name (case-insensitive). When a match is found, that env's per-flag
|
|
457
|
+
* `{enabled, value}` overrides the flag's global `default_value`.
|
|
458
|
+
*
|
|
459
|
+
* @example
|
|
460
|
+
* await client.loadDefaultsFromFile('flags.json');
|
|
461
|
+
*/
|
|
462
|
+
async loadDefaultsFromFile(path) {
|
|
463
|
+
const payload = await readDefaultsFile(path);
|
|
464
|
+
this.loadDefaults(payload);
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Synchronous variant of {@link loadDefaultsFromFile} that accepts an
|
|
468
|
+
* already-parsed object (or a JSON string).
|
|
469
|
+
*/
|
|
470
|
+
loadDefaults(payload) {
|
|
471
|
+
const data = typeof payload === 'string' ? JSON.parse(payload) : payload;
|
|
472
|
+
const { defaults, envUUID } = parseDefaults(data, this.environment);
|
|
473
|
+
this.offlineDefaults = defaults;
|
|
474
|
+
this.offlineDefaultsEnvUUID = envUUID;
|
|
475
|
+
this.offlineDefaultsLoadedAt = new Date().toISOString();
|
|
476
|
+
}
|
|
302
477
|
async fetchAllFlags() {
|
|
303
|
-
const
|
|
304
|
-
|
|
478
|
+
const pageSize = 500;
|
|
479
|
+
const flags = [];
|
|
480
|
+
let offset = 0;
|
|
481
|
+
for (;;) {
|
|
482
|
+
const response = await this.request('GET', `/api/v1/flags?project_id=${enc(this.project)}&application=${enc(this.application)}&environment_id=${enc(this.environment)}&limit=${pageSize}&offset=${offset}`);
|
|
483
|
+
const page = Array.isArray(response) ? response : (response.flags ?? []);
|
|
484
|
+
flags.push(...page);
|
|
485
|
+
const total = Array.isArray(response) ? undefined : response.total_count;
|
|
486
|
+
if (Array.isArray(response) || page.length === 0 || total === undefined || flags.length >= total)
|
|
487
|
+
break;
|
|
488
|
+
offset += page.length;
|
|
489
|
+
}
|
|
490
|
+
return flags.map(mapRawFlag);
|
|
491
|
+
}
|
|
492
|
+
async fetchFlag(flagId) {
|
|
493
|
+
const raw = await this.request('GET', `/api/v1/flags/${enc(flagId)}?environment_id=${enc(this.environment)}`);
|
|
494
|
+
if (!raw?.key)
|
|
495
|
+
return null;
|
|
496
|
+
return mapRawFlag(raw);
|
|
305
497
|
}
|
|
306
498
|
async post(path, body) {
|
|
307
499
|
return this.request('POST', path, body);
|
|
@@ -376,4 +568,39 @@ export class DeploySentryClient {
|
|
|
376
568
|
function enc(value) {
|
|
377
569
|
return encodeURIComponent(value);
|
|
378
570
|
}
|
|
571
|
+
/** Map a flag_type string to the inspection `type` field. */
|
|
572
|
+
function typeOfFlagType(flagType) {
|
|
573
|
+
switch (flagType) {
|
|
574
|
+
case 'boolean': return 'boolean';
|
|
575
|
+
case 'integer': return 'integer';
|
|
576
|
+
case 'number': return 'number';
|
|
577
|
+
case 'json': return 'json';
|
|
578
|
+
case 'string': return 'string';
|
|
579
|
+
default: return 'unknown';
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
/** Infer the inspection `type` field from an already-parsed value. */
|
|
583
|
+
function typeOfValue(value) {
|
|
584
|
+
switch (typeof value) {
|
|
585
|
+
case 'boolean': return 'boolean';
|
|
586
|
+
case 'number': return Number.isInteger(value) ? 'integer' : 'number';
|
|
587
|
+
case 'string': return 'string';
|
|
588
|
+
case 'object': return value === null ? 'unknown' : 'json';
|
|
589
|
+
default: return 'unknown';
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Infer which coercion to apply to an offline-default raw value based on
|
|
594
|
+
* the caller's `defaultValue` type. Falls back to 'json' for objects /
|
|
595
|
+
* arrays so JSON-typed flags round-trip correctly.
|
|
596
|
+
*/
|
|
597
|
+
function inferRequestedType(defaultValue) {
|
|
598
|
+
if (typeof defaultValue === 'boolean')
|
|
599
|
+
return 'bool';
|
|
600
|
+
if (typeof defaultValue === 'string')
|
|
601
|
+
return 'string';
|
|
602
|
+
if (typeof defaultValue === 'number')
|
|
603
|
+
return 'number';
|
|
604
|
+
return 'json';
|
|
605
|
+
}
|
|
379
606
|
//# sourceMappingURL=client.js.map
|