@shipeasy/sdk 2.4.0 → 2.5.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/dist/client/index.d.mts +28 -0
- package/dist/client/index.d.ts +28 -0
- package/dist/client/index.js +33 -0
- package/dist/client/index.mjs +33 -0
- package/dist/server/index.d.mts +38 -0
- package/dist/server/index.d.ts +38 -0
- package/dist/server/index.js +35 -2
- package/dist/server/index.mjs +35 -2
- package/package.json +1 -1
package/dist/client/index.d.mts
CHANGED
|
@@ -27,6 +27,12 @@ interface EvalResponse {
|
|
|
27
27
|
flags: Record<string, boolean>;
|
|
28
28
|
configs: Record<string, unknown>;
|
|
29
29
|
experiments: Record<string, EvalExpResult>;
|
|
30
|
+
/**
|
|
31
|
+
* Killswitch state, flattened by the server. A boolean means the killswitch
|
|
32
|
+
* is whole-killed; an object means it's not whole-killed and carries per-
|
|
33
|
+
* switch booleans.
|
|
34
|
+
*/
|
|
35
|
+
killswitches?: Record<string, boolean | Record<string, boolean>>;
|
|
30
36
|
}
|
|
31
37
|
interface AutoCollectGroups {
|
|
32
38
|
vitals: boolean;
|
|
@@ -83,6 +89,12 @@ declare class FlagsClientBrowser {
|
|
|
83
89
|
*/
|
|
84
90
|
installBridge(): ShipeasySdkBridge | null;
|
|
85
91
|
track(eventName: string, props?: Record<string, unknown>): void;
|
|
92
|
+
/**
|
|
93
|
+
* Read a killswitch from the server's evaluated state. Without `switchKey`,
|
|
94
|
+
* returns true when the killswitch is whole-killed. With `switchKey`, returns
|
|
95
|
+
* the per-switch state. Returns false for unknown killswitches / switches.
|
|
96
|
+
*/
|
|
97
|
+
getKillswitch(name: string, switchKey?: string): boolean;
|
|
86
98
|
flush(): Promise<void>;
|
|
87
99
|
destroy(): void;
|
|
88
100
|
}
|
|
@@ -180,6 +192,12 @@ interface BootstrapPayload {
|
|
|
180
192
|
group: string;
|
|
181
193
|
params: Record<string, unknown>;
|
|
182
194
|
}>;
|
|
195
|
+
/**
|
|
196
|
+
* Killswitch state, flattened by the server. A value of `boolean` means the
|
|
197
|
+
* killswitch is killed as a whole (no per-switch detail); a `Record` means
|
|
198
|
+
* the killswitch is not whole-killed and the map carries per-switch state.
|
|
199
|
+
*/
|
|
200
|
+
killswitches?: Record<string, boolean | Record<string, boolean>>;
|
|
183
201
|
/** Set by getBootstrapHtml() for auto-init. Not part of evaluate() output. */
|
|
184
202
|
apiKey?: string;
|
|
185
203
|
apiUrl?: string;
|
|
@@ -205,6 +223,16 @@ declare const flags: {
|
|
|
205
223
|
getConfig<T = unknown>(name: string, decode?: (raw: unknown) => T): T | undefined;
|
|
206
224
|
getExperiment<P extends Record<string, unknown>>(name: string, defaultParams: P, decode?: (raw: unknown) => P, variants?: Record<string, Partial<P>>): ExperimentResult<P>;
|
|
207
225
|
track(eventName: string, props?: Record<string, unknown>): void;
|
|
226
|
+
/**
|
|
227
|
+
* Read a killswitch. Without `switchKey`, returns true when the killswitch is
|
|
228
|
+
* killed as a whole. With `switchKey`, returns true when that specific switch
|
|
229
|
+
* is on. Unknown killswitches / switches return false.
|
|
230
|
+
*
|
|
231
|
+
* Priority: bootstrap → CDN evalResult (post-mount) → false. Matches the
|
|
232
|
+
* pattern used by `flags.get` / `flags.getConfig` so SSR-hydrated values are
|
|
233
|
+
* available synchronously on first render.
|
|
234
|
+
*/
|
|
235
|
+
ks(name: string, switchKey?: string): boolean;
|
|
208
236
|
flush(): Promise<void>;
|
|
209
237
|
/**
|
|
210
238
|
* Called by FlagsBoundary after React hydration to unlock flag reads.
|
package/dist/client/index.d.ts
CHANGED
|
@@ -27,6 +27,12 @@ interface EvalResponse {
|
|
|
27
27
|
flags: Record<string, boolean>;
|
|
28
28
|
configs: Record<string, unknown>;
|
|
29
29
|
experiments: Record<string, EvalExpResult>;
|
|
30
|
+
/**
|
|
31
|
+
* Killswitch state, flattened by the server. A boolean means the killswitch
|
|
32
|
+
* is whole-killed; an object means it's not whole-killed and carries per-
|
|
33
|
+
* switch booleans.
|
|
34
|
+
*/
|
|
35
|
+
killswitches?: Record<string, boolean | Record<string, boolean>>;
|
|
30
36
|
}
|
|
31
37
|
interface AutoCollectGroups {
|
|
32
38
|
vitals: boolean;
|
|
@@ -83,6 +89,12 @@ declare class FlagsClientBrowser {
|
|
|
83
89
|
*/
|
|
84
90
|
installBridge(): ShipeasySdkBridge | null;
|
|
85
91
|
track(eventName: string, props?: Record<string, unknown>): void;
|
|
92
|
+
/**
|
|
93
|
+
* Read a killswitch from the server's evaluated state. Without `switchKey`,
|
|
94
|
+
* returns true when the killswitch is whole-killed. With `switchKey`, returns
|
|
95
|
+
* the per-switch state. Returns false for unknown killswitches / switches.
|
|
96
|
+
*/
|
|
97
|
+
getKillswitch(name: string, switchKey?: string): boolean;
|
|
86
98
|
flush(): Promise<void>;
|
|
87
99
|
destroy(): void;
|
|
88
100
|
}
|
|
@@ -180,6 +192,12 @@ interface BootstrapPayload {
|
|
|
180
192
|
group: string;
|
|
181
193
|
params: Record<string, unknown>;
|
|
182
194
|
}>;
|
|
195
|
+
/**
|
|
196
|
+
* Killswitch state, flattened by the server. A value of `boolean` means the
|
|
197
|
+
* killswitch is killed as a whole (no per-switch detail); a `Record` means
|
|
198
|
+
* the killswitch is not whole-killed and the map carries per-switch state.
|
|
199
|
+
*/
|
|
200
|
+
killswitches?: Record<string, boolean | Record<string, boolean>>;
|
|
183
201
|
/** Set by getBootstrapHtml() for auto-init. Not part of evaluate() output. */
|
|
184
202
|
apiKey?: string;
|
|
185
203
|
apiUrl?: string;
|
|
@@ -205,6 +223,16 @@ declare const flags: {
|
|
|
205
223
|
getConfig<T = unknown>(name: string, decode?: (raw: unknown) => T): T | undefined;
|
|
206
224
|
getExperiment<P extends Record<string, unknown>>(name: string, defaultParams: P, decode?: (raw: unknown) => P, variants?: Record<string, Partial<P>>): ExperimentResult<P>;
|
|
207
225
|
track(eventName: string, props?: Record<string, unknown>): void;
|
|
226
|
+
/**
|
|
227
|
+
* Read a killswitch. Without `switchKey`, returns true when the killswitch is
|
|
228
|
+
* killed as a whole. With `switchKey`, returns true when that specific switch
|
|
229
|
+
* is on. Unknown killswitches / switches return false.
|
|
230
|
+
*
|
|
231
|
+
* Priority: bootstrap → CDN evalResult (post-mount) → false. Matches the
|
|
232
|
+
* pattern used by `flags.get` / `flags.getConfig` so SSR-hydrated values are
|
|
233
|
+
* available synchronously on first render.
|
|
234
|
+
*/
|
|
235
|
+
ks(name: string, switchKey?: string): boolean;
|
|
208
236
|
flush(): Promise<void>;
|
|
209
237
|
/**
|
|
210
238
|
* Called by FlagsBoundary after React hydration to unlock flag reads.
|
package/dist/client/index.js
CHANGED
|
@@ -575,6 +575,19 @@ var FlagsClientBrowser = class {
|
|
|
575
575
|
track(eventName, props) {
|
|
576
576
|
this.buffer.pushMetric(eventName, this.userId, this.anonId, props);
|
|
577
577
|
}
|
|
578
|
+
/**
|
|
579
|
+
* Read a killswitch from the server's evaluated state. Without `switchKey`,
|
|
580
|
+
* returns true when the killswitch is whole-killed. With `switchKey`, returns
|
|
581
|
+
* the per-switch state. Returns false for unknown killswitches / switches.
|
|
582
|
+
*/
|
|
583
|
+
getKillswitch(name, switchKey) {
|
|
584
|
+
if (this.evalResult === null) return false;
|
|
585
|
+
const ks = this.evalResult.killswitches?.[name];
|
|
586
|
+
if (ks === void 0) return false;
|
|
587
|
+
if (typeof ks === "boolean") return switchKey === void 0 ? ks : false;
|
|
588
|
+
if (switchKey === void 0) return false;
|
|
589
|
+
return ks[switchKey] === true;
|
|
590
|
+
}
|
|
578
591
|
async flush() {
|
|
579
592
|
await this.buffer.flushAsync();
|
|
580
593
|
}
|
|
@@ -794,6 +807,26 @@ var flags = {
|
|
|
794
807
|
track(eventName, props) {
|
|
795
808
|
_client?.track(eventName, props);
|
|
796
809
|
},
|
|
810
|
+
/**
|
|
811
|
+
* Read a killswitch. Without `switchKey`, returns true when the killswitch is
|
|
812
|
+
* killed as a whole. With `switchKey`, returns true when that specific switch
|
|
813
|
+
* is on. Unknown killswitches / switches return false.
|
|
814
|
+
*
|
|
815
|
+
* Priority: bootstrap → CDN evalResult (post-mount) → false. Matches the
|
|
816
|
+
* pattern used by `flags.get` / `flags.getConfig` so SSR-hydrated values are
|
|
817
|
+
* available synchronously on first render.
|
|
818
|
+
*/
|
|
819
|
+
ks(name, switchKey) {
|
|
820
|
+
const bs = getBootstrap();
|
|
821
|
+
if (bs !== null && bs.killswitches && name in bs.killswitches) {
|
|
822
|
+
const ks = bs.killswitches[name];
|
|
823
|
+
if (typeof ks === "boolean") return switchKey === void 0 ? ks : false;
|
|
824
|
+
if (switchKey === void 0) return false;
|
|
825
|
+
return ks[switchKey] === true;
|
|
826
|
+
}
|
|
827
|
+
if (!_mountedAndReady) return false;
|
|
828
|
+
return _client?.getKillswitch(name, switchKey) ?? false;
|
|
829
|
+
},
|
|
797
830
|
flush() {
|
|
798
831
|
return _client?.flush() ?? Promise.resolve();
|
|
799
832
|
},
|
package/dist/client/index.mjs
CHANGED
|
@@ -532,6 +532,19 @@ var FlagsClientBrowser = class {
|
|
|
532
532
|
track(eventName, props) {
|
|
533
533
|
this.buffer.pushMetric(eventName, this.userId, this.anonId, props);
|
|
534
534
|
}
|
|
535
|
+
/**
|
|
536
|
+
* Read a killswitch from the server's evaluated state. Without `switchKey`,
|
|
537
|
+
* returns true when the killswitch is whole-killed. With `switchKey`, returns
|
|
538
|
+
* the per-switch state. Returns false for unknown killswitches / switches.
|
|
539
|
+
*/
|
|
540
|
+
getKillswitch(name, switchKey) {
|
|
541
|
+
if (this.evalResult === null) return false;
|
|
542
|
+
const ks = this.evalResult.killswitches?.[name];
|
|
543
|
+
if (ks === void 0) return false;
|
|
544
|
+
if (typeof ks === "boolean") return switchKey === void 0 ? ks : false;
|
|
545
|
+
if (switchKey === void 0) return false;
|
|
546
|
+
return ks[switchKey] === true;
|
|
547
|
+
}
|
|
535
548
|
async flush() {
|
|
536
549
|
await this.buffer.flushAsync();
|
|
537
550
|
}
|
|
@@ -751,6 +764,26 @@ var flags = {
|
|
|
751
764
|
track(eventName, props) {
|
|
752
765
|
_client?.track(eventName, props);
|
|
753
766
|
},
|
|
767
|
+
/**
|
|
768
|
+
* Read a killswitch. Without `switchKey`, returns true when the killswitch is
|
|
769
|
+
* killed as a whole. With `switchKey`, returns true when that specific switch
|
|
770
|
+
* is on. Unknown killswitches / switches return false.
|
|
771
|
+
*
|
|
772
|
+
* Priority: bootstrap → CDN evalResult (post-mount) → false. Matches the
|
|
773
|
+
* pattern used by `flags.get` / `flags.getConfig` so SSR-hydrated values are
|
|
774
|
+
* available synchronously on first render.
|
|
775
|
+
*/
|
|
776
|
+
ks(name, switchKey) {
|
|
777
|
+
const bs = getBootstrap();
|
|
778
|
+
if (bs !== null && bs.killswitches && name in bs.killswitches) {
|
|
779
|
+
const ks = bs.killswitches[name];
|
|
780
|
+
if (typeof ks === "boolean") return switchKey === void 0 ? ks : false;
|
|
781
|
+
if (switchKey === void 0) return false;
|
|
782
|
+
return ks[switchKey] === true;
|
|
783
|
+
}
|
|
784
|
+
if (!_mountedAndReady) return false;
|
|
785
|
+
return _client?.getKillswitch(name, switchKey) ?? false;
|
|
786
|
+
},
|
|
754
787
|
flush() {
|
|
755
788
|
return _client?.flush() ?? Promise.resolve();
|
|
756
789
|
},
|
package/dist/server/index.d.mts
CHANGED
|
@@ -9,10 +9,36 @@ interface ExperimentResult<P> {
|
|
|
9
9
|
group: string;
|
|
10
10
|
params: P;
|
|
11
11
|
}
|
|
12
|
+
interface GateRule {
|
|
13
|
+
attr: string;
|
|
14
|
+
op: "eq" | "neq" | "in" | "not_in" | "gt" | "gte" | "lt" | "lte" | "contains" | "regex";
|
|
15
|
+
value: unknown;
|
|
16
|
+
}
|
|
17
|
+
interface Gate {
|
|
18
|
+
rules: GateRule[];
|
|
19
|
+
rolloutPct: number;
|
|
20
|
+
salt: string;
|
|
21
|
+
enabled: 0 | 1 | boolean;
|
|
22
|
+
killswitch?: 0 | 1 | boolean;
|
|
23
|
+
}
|
|
24
|
+
interface Killswitch {
|
|
25
|
+
killed: 0 | 1 | boolean;
|
|
26
|
+
switches?: Record<string, 0 | 1 | boolean>;
|
|
27
|
+
}
|
|
28
|
+
interface FlagsBlob {
|
|
29
|
+
version: string;
|
|
30
|
+
plan: string;
|
|
31
|
+
gates: Record<string, Gate>;
|
|
32
|
+
configs: Record<string, {
|
|
33
|
+
value: unknown;
|
|
34
|
+
}>;
|
|
35
|
+
killswitches: Record<string, Killswitch>;
|
|
36
|
+
}
|
|
12
37
|
interface BootstrapPayload {
|
|
13
38
|
flags: Record<string, boolean>;
|
|
14
39
|
configs: Record<string, unknown>;
|
|
15
40
|
experiments: Record<string, ExperimentResult<Record<string, unknown>>>;
|
|
41
|
+
killswitches: Record<string, boolean | Record<string, boolean>>;
|
|
16
42
|
}
|
|
17
43
|
type FlagsClientEnv = "dev" | "staging" | "prod";
|
|
18
44
|
interface FlagsClientOptions {
|
|
@@ -20,6 +46,11 @@ interface FlagsClientOptions {
|
|
|
20
46
|
baseUrl?: string;
|
|
21
47
|
/** Which published env to read values from. Defaults to "prod". */
|
|
22
48
|
env?: FlagsClientEnv;
|
|
49
|
+
/**
|
|
50
|
+
* Preload the flags blob synchronously without a network fetch. Primarily
|
|
51
|
+
* for tests; production callers should rely on init()/initOnce().
|
|
52
|
+
*/
|
|
53
|
+
initialBlob?: FlagsBlob;
|
|
23
54
|
}
|
|
24
55
|
declare class FlagsClient {
|
|
25
56
|
private readonly apiKey;
|
|
@@ -54,6 +85,7 @@ declare class FlagsClient {
|
|
|
54
85
|
* synchronously without waiting for identify() to resolve.
|
|
55
86
|
*/
|
|
56
87
|
evaluate(user: User, rawUrl?: string): BootstrapPayload;
|
|
88
|
+
getKillswitch(name: string, switchKey?: string): boolean;
|
|
57
89
|
}
|
|
58
90
|
interface I18nForRequest {
|
|
59
91
|
strings: Record<string, string>;
|
|
@@ -165,6 +197,12 @@ declare const flags: {
|
|
|
165
197
|
get(name: string, user: User): boolean;
|
|
166
198
|
getConfig<T = unknown>(name: string, decode?: (raw: unknown) => T): T | undefined;
|
|
167
199
|
getExperiment<P extends Record<string, unknown>>(name: string, user: User, defaultParams: P, decode?: (raw: unknown) => P): ExperimentResult<P>;
|
|
200
|
+
/**
|
|
201
|
+
* Read a killswitch. Without `switchKey`, returns true when the whole
|
|
202
|
+
* killswitch is killed. With `switchKey`, returns true when that specific
|
|
203
|
+
* switch is on. Unknown killswitches / switches return false.
|
|
204
|
+
*/
|
|
205
|
+
ks(name: string, switchKey?: string): boolean;
|
|
168
206
|
track(userId: string, eventName: string, props?: Record<string, unknown>): void;
|
|
169
207
|
/**
|
|
170
208
|
* Evaluate all flags / configs / experiments for a user against the locally
|
package/dist/server/index.d.ts
CHANGED
|
@@ -9,10 +9,36 @@ interface ExperimentResult<P> {
|
|
|
9
9
|
group: string;
|
|
10
10
|
params: P;
|
|
11
11
|
}
|
|
12
|
+
interface GateRule {
|
|
13
|
+
attr: string;
|
|
14
|
+
op: "eq" | "neq" | "in" | "not_in" | "gt" | "gte" | "lt" | "lte" | "contains" | "regex";
|
|
15
|
+
value: unknown;
|
|
16
|
+
}
|
|
17
|
+
interface Gate {
|
|
18
|
+
rules: GateRule[];
|
|
19
|
+
rolloutPct: number;
|
|
20
|
+
salt: string;
|
|
21
|
+
enabled: 0 | 1 | boolean;
|
|
22
|
+
killswitch?: 0 | 1 | boolean;
|
|
23
|
+
}
|
|
24
|
+
interface Killswitch {
|
|
25
|
+
killed: 0 | 1 | boolean;
|
|
26
|
+
switches?: Record<string, 0 | 1 | boolean>;
|
|
27
|
+
}
|
|
28
|
+
interface FlagsBlob {
|
|
29
|
+
version: string;
|
|
30
|
+
plan: string;
|
|
31
|
+
gates: Record<string, Gate>;
|
|
32
|
+
configs: Record<string, {
|
|
33
|
+
value: unknown;
|
|
34
|
+
}>;
|
|
35
|
+
killswitches: Record<string, Killswitch>;
|
|
36
|
+
}
|
|
12
37
|
interface BootstrapPayload {
|
|
13
38
|
flags: Record<string, boolean>;
|
|
14
39
|
configs: Record<string, unknown>;
|
|
15
40
|
experiments: Record<string, ExperimentResult<Record<string, unknown>>>;
|
|
41
|
+
killswitches: Record<string, boolean | Record<string, boolean>>;
|
|
16
42
|
}
|
|
17
43
|
type FlagsClientEnv = "dev" | "staging" | "prod";
|
|
18
44
|
interface FlagsClientOptions {
|
|
@@ -20,6 +46,11 @@ interface FlagsClientOptions {
|
|
|
20
46
|
baseUrl?: string;
|
|
21
47
|
/** Which published env to read values from. Defaults to "prod". */
|
|
22
48
|
env?: FlagsClientEnv;
|
|
49
|
+
/**
|
|
50
|
+
* Preload the flags blob synchronously without a network fetch. Primarily
|
|
51
|
+
* for tests; production callers should rely on init()/initOnce().
|
|
52
|
+
*/
|
|
53
|
+
initialBlob?: FlagsBlob;
|
|
23
54
|
}
|
|
24
55
|
declare class FlagsClient {
|
|
25
56
|
private readonly apiKey;
|
|
@@ -54,6 +85,7 @@ declare class FlagsClient {
|
|
|
54
85
|
* synchronously without waiting for identify() to resolve.
|
|
55
86
|
*/
|
|
56
87
|
evaluate(user: User, rawUrl?: string): BootstrapPayload;
|
|
88
|
+
getKillswitch(name: string, switchKey?: string): boolean;
|
|
57
89
|
}
|
|
58
90
|
interface I18nForRequest {
|
|
59
91
|
strings: Record<string, string>;
|
|
@@ -165,6 +197,12 @@ declare const flags: {
|
|
|
165
197
|
get(name: string, user: User): boolean;
|
|
166
198
|
getConfig<T = unknown>(name: string, decode?: (raw: unknown) => T): T | undefined;
|
|
167
199
|
getExperiment<P extends Record<string, unknown>>(name: string, user: User, defaultParams: P, decode?: (raw: unknown) => P): ExperimentResult<P>;
|
|
200
|
+
/**
|
|
201
|
+
* Read a killswitch. Without `switchKey`, returns true when the whole
|
|
202
|
+
* killswitch is killed. With `switchKey`, returns true when that specific
|
|
203
|
+
* switch is on. Unknown killswitches / switches return false.
|
|
204
|
+
*/
|
|
205
|
+
ks(name: string, switchKey?: string): boolean;
|
|
168
206
|
track(userId: string, eventName: string, props?: Record<string, unknown>): void;
|
|
169
207
|
/**
|
|
170
208
|
* Evaluate all flags / configs / experiments for a user against the locally
|
package/dist/server/index.js
CHANGED
|
@@ -203,6 +203,10 @@ var FlagsClient = class {
|
|
|
203
203
|
this.apiKey = opts.apiKey;
|
|
204
204
|
this.baseUrl = (opts.baseUrl ?? "https://cdn.shipeasy.ai").replace(/\/$/, "");
|
|
205
205
|
this.env = opts.env ?? "prod";
|
|
206
|
+
if (opts.initialBlob) {
|
|
207
|
+
this.flagsBlob = opts.initialBlob;
|
|
208
|
+
this.initialized = true;
|
|
209
|
+
}
|
|
206
210
|
}
|
|
207
211
|
async init() {
|
|
208
212
|
await this.fetchAll();
|
|
@@ -343,6 +347,7 @@ var FlagsClient = class {
|
|
|
343
347
|
const flags2 = {};
|
|
344
348
|
const configs = {};
|
|
345
349
|
const experiments = {};
|
|
350
|
+
const killswitches = {};
|
|
346
351
|
for (const [name, gate] of Object.entries(this.flagsBlob?.gates ?? {})) {
|
|
347
352
|
flags2[name] = evalGateInternal(gate, user);
|
|
348
353
|
}
|
|
@@ -352,6 +357,15 @@ var FlagsClient = class {
|
|
|
352
357
|
for (const [name] of Object.entries(this.expsBlob?.experiments ?? {})) {
|
|
353
358
|
experiments[name] = this.getExperiment(name, user, {});
|
|
354
359
|
}
|
|
360
|
+
for (const [name, ks] of Object.entries(this.flagsBlob?.killswitches ?? {})) {
|
|
361
|
+
if (ks.switches && Object.keys(ks.switches).length > 0) {
|
|
362
|
+
const out = {};
|
|
363
|
+
for (const [k, v] of Object.entries(ks.switches)) out[k] = isEnabled(v);
|
|
364
|
+
killswitches[name] = out;
|
|
365
|
+
} else {
|
|
366
|
+
killswitches[name] = isEnabled(ks.killed);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
355
369
|
if (rawUrl) {
|
|
356
370
|
const ov = parseOverrides(rawUrl);
|
|
357
371
|
Object.assign(flags2, ov.gates);
|
|
@@ -360,7 +374,13 @@ var FlagsClient = class {
|
|
|
360
374
|
experiments[name] = { inExperiment: true, group, params: {} };
|
|
361
375
|
}
|
|
362
376
|
}
|
|
363
|
-
return { flags: flags2, configs, experiments };
|
|
377
|
+
return { flags: flags2, configs, experiments, killswitches };
|
|
378
|
+
}
|
|
379
|
+
getKillswitch(name, switchKey) {
|
|
380
|
+
const ks = this.flagsBlob?.killswitches?.[name];
|
|
381
|
+
if (!ks) return false;
|
|
382
|
+
if (switchKey === void 0) return isEnabled(ks.killed);
|
|
383
|
+
return isEnabled(ks.switches?.[switchKey]);
|
|
364
384
|
}
|
|
365
385
|
};
|
|
366
386
|
var _I18N_SSR_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:ssr-i18n");
|
|
@@ -589,6 +609,14 @@ var flags = {
|
|
|
589
609
|
params: defaultParams
|
|
590
610
|
};
|
|
591
611
|
},
|
|
612
|
+
/**
|
|
613
|
+
* Read a killswitch. Without `switchKey`, returns true when the whole
|
|
614
|
+
* killswitch is killed. With `switchKey`, returns true when that specific
|
|
615
|
+
* switch is on. Unknown killswitches / switches return false.
|
|
616
|
+
*/
|
|
617
|
+
ks(name, switchKey) {
|
|
618
|
+
return _server?.getKillswitch(name, switchKey) ?? false;
|
|
619
|
+
},
|
|
592
620
|
track(userId, eventName, props) {
|
|
593
621
|
_server?.track(userId, eventName, props);
|
|
594
622
|
},
|
|
@@ -598,7 +626,12 @@ var flags = {
|
|
|
598
626
|
* overrides. Returns an empty payload when the blob hasn't been fetched yet.
|
|
599
627
|
*/
|
|
600
628
|
evaluate(user, rawUrl) {
|
|
601
|
-
return _server?.evaluate(user, rawUrl) ?? {
|
|
629
|
+
return _server?.evaluate(user, rawUrl) ?? {
|
|
630
|
+
flags: {},
|
|
631
|
+
configs: {},
|
|
632
|
+
experiments: {},
|
|
633
|
+
killswitches: {}
|
|
634
|
+
};
|
|
602
635
|
}
|
|
603
636
|
};
|
|
604
637
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/server/index.mjs
CHANGED
|
@@ -160,6 +160,10 @@ var FlagsClient = class {
|
|
|
160
160
|
this.apiKey = opts.apiKey;
|
|
161
161
|
this.baseUrl = (opts.baseUrl ?? "https://cdn.shipeasy.ai").replace(/\/$/, "");
|
|
162
162
|
this.env = opts.env ?? "prod";
|
|
163
|
+
if (opts.initialBlob) {
|
|
164
|
+
this.flagsBlob = opts.initialBlob;
|
|
165
|
+
this.initialized = true;
|
|
166
|
+
}
|
|
163
167
|
}
|
|
164
168
|
async init() {
|
|
165
169
|
await this.fetchAll();
|
|
@@ -300,6 +304,7 @@ var FlagsClient = class {
|
|
|
300
304
|
const flags2 = {};
|
|
301
305
|
const configs = {};
|
|
302
306
|
const experiments = {};
|
|
307
|
+
const killswitches = {};
|
|
303
308
|
for (const [name, gate] of Object.entries(this.flagsBlob?.gates ?? {})) {
|
|
304
309
|
flags2[name] = evalGateInternal(gate, user);
|
|
305
310
|
}
|
|
@@ -309,6 +314,15 @@ var FlagsClient = class {
|
|
|
309
314
|
for (const [name] of Object.entries(this.expsBlob?.experiments ?? {})) {
|
|
310
315
|
experiments[name] = this.getExperiment(name, user, {});
|
|
311
316
|
}
|
|
317
|
+
for (const [name, ks] of Object.entries(this.flagsBlob?.killswitches ?? {})) {
|
|
318
|
+
if (ks.switches && Object.keys(ks.switches).length > 0) {
|
|
319
|
+
const out = {};
|
|
320
|
+
for (const [k, v] of Object.entries(ks.switches)) out[k] = isEnabled(v);
|
|
321
|
+
killswitches[name] = out;
|
|
322
|
+
} else {
|
|
323
|
+
killswitches[name] = isEnabled(ks.killed);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
312
326
|
if (rawUrl) {
|
|
313
327
|
const ov = parseOverrides(rawUrl);
|
|
314
328
|
Object.assign(flags2, ov.gates);
|
|
@@ -317,7 +331,13 @@ var FlagsClient = class {
|
|
|
317
331
|
experiments[name] = { inExperiment: true, group, params: {} };
|
|
318
332
|
}
|
|
319
333
|
}
|
|
320
|
-
return { flags: flags2, configs, experiments };
|
|
334
|
+
return { flags: flags2, configs, experiments, killswitches };
|
|
335
|
+
}
|
|
336
|
+
getKillswitch(name, switchKey) {
|
|
337
|
+
const ks = this.flagsBlob?.killswitches?.[name];
|
|
338
|
+
if (!ks) return false;
|
|
339
|
+
if (switchKey === void 0) return isEnabled(ks.killed);
|
|
340
|
+
return isEnabled(ks.switches?.[switchKey]);
|
|
321
341
|
}
|
|
322
342
|
};
|
|
323
343
|
var _I18N_SSR_SYM = /* @__PURE__ */ Symbol.for("@shipeasy/sdk:ssr-i18n");
|
|
@@ -546,6 +566,14 @@ var flags = {
|
|
|
546
566
|
params: defaultParams
|
|
547
567
|
};
|
|
548
568
|
},
|
|
569
|
+
/**
|
|
570
|
+
* Read a killswitch. Without `switchKey`, returns true when the whole
|
|
571
|
+
* killswitch is killed. With `switchKey`, returns true when that specific
|
|
572
|
+
* switch is on. Unknown killswitches / switches return false.
|
|
573
|
+
*/
|
|
574
|
+
ks(name, switchKey) {
|
|
575
|
+
return _server?.getKillswitch(name, switchKey) ?? false;
|
|
576
|
+
},
|
|
549
577
|
track(userId, eventName, props) {
|
|
550
578
|
_server?.track(userId, eventName, props);
|
|
551
579
|
},
|
|
@@ -555,7 +583,12 @@ var flags = {
|
|
|
555
583
|
* overrides. Returns an empty payload when the blob hasn't been fetched yet.
|
|
556
584
|
*/
|
|
557
585
|
evaluate(user, rawUrl) {
|
|
558
|
-
return _server?.evaluate(user, rawUrl) ?? {
|
|
586
|
+
return _server?.evaluate(user, rawUrl) ?? {
|
|
587
|
+
flags: {},
|
|
588
|
+
configs: {},
|
|
589
|
+
experiments: {},
|
|
590
|
+
killswitches: {}
|
|
591
|
+
};
|
|
559
592
|
}
|
|
560
593
|
};
|
|
561
594
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shipeasy/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Shipeasy SDK — feature gates, runtime configs, experiments, and metrics for the Shipeasy hosted service.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"homepage": "https://shipeasy.ai",
|