@shipeasy/sdk 3.1.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,6 +53,58 @@ const client = new FlagsClient({ sdkKey: process.env.SHIPEASY_SERVER_KEY! });
53
53
  const cfg = await client.getConfig("plan_limits", { user_id: "u-1" });
54
54
  ```
55
55
 
56
+ ## Error tracking — `see()`
57
+
58
+ `see` (shipeasy error) is the structured error reporter — opes-style: every
59
+ handled exception documents its **product consequence**, not just its stack.
60
+ Works in vanilla JS on both sides; the whole grammar hangs off one import:
61
+
62
+ ```ts
63
+ import { see } from "@shipeasy/sdk/client"; // or "@shipeasy/sdk/server"
64
+
65
+ try {
66
+ await submitOrder(order);
67
+ } catch (e) {
68
+ see(e).causes_the("checkout").to("use cached prices").extras({ order_id: order.id });
69
+ }
70
+
71
+ // Non-exception problems — the name is a stable identifier (it participates
72
+ // in the issue fingerprint); variable data goes in .message() / .extras():
73
+ if (rows.length > LIMIT) {
74
+ see.Violation("large query")
75
+ .message(`got ${rows.length} rows`)
76
+ .causes_the("search results")
77
+ .to("be trimmed");
78
+ }
79
+
80
+ // Expected control-flow exceptions: document them, report nothing —
81
+ // auto-capture skips marked errors. The reason must start with "because".
82
+ try {
83
+ return decodeFoo(blob);
84
+ } catch (e) {
85
+ see.ControlFlowException(e, "because it wasn't an encoded Foo");
86
+ return decodeBar(blob);
87
+ }
88
+ ```
89
+
90
+ Reports land in the Shipeasy **errors** primitive: fingerprint-grouped issues
91
+ (open / resolved / ignored, regression auto-reopens) with a near-real-time
92
+ occurrence timeseries. The chain dispatches on the next microtask — no
93
+ `.send()` — and ships immediately (`sendBeacon` in the browser, fire-and-forget
94
+ `fetch` on the server), spam-guarded by a 30s dedup window and a per-session
95
+ cap.
96
+
97
+ The client SDK also auto-captures uncaught exceptions, unhandled rejections,
98
+ and network failures (fetch network errors + 5xx) into the same primitive
99
+ (`autoCollect: { errors }`, on by default). Auto-capture is the outer safety
100
+ net — it does not replace `see()` in catch blocks, where you know the
101
+ consequence and it cannot.
102
+
103
+ **Rules**: if you don't know the consequence, don't catch the exception. Never
104
+ `see()` then `throw` (double counting — either handle or rethrow). Never use
105
+ `see.Violation()` for a caught exception (you'd drop the stack). No PII or
106
+ high-cardinality data in extras.
107
+
56
108
  ## Drop-in `<script>` loader (no bundler)
57
109
 
58
110
  ```html
@@ -1,3 +1,62 @@
1
+ type SeeExtras = Record<string, string | number | boolean | null | undefined>;
2
+ type SeeKind = "caught" | "uncaught" | "unhandled_rejection" | "network" | "violation";
3
+ /** Built by `causesThe(subject).to(outcome)` — never constructed by hand. */
4
+ interface Consequence {
5
+ readonly __seConsequence: true;
6
+ readonly subject: string;
7
+ readonly outcome: string;
8
+ }
9
+ /**
10
+ * Non-exception problem, built by `violation(name)`. A plain branded object
11
+ * (not an Error subclass) so `.message()` can be a builder method without
12
+ * colliding with `Error.prototype.message`.
13
+ */
14
+ interface Violation {
15
+ readonly __seViolation: true;
16
+ readonly violationName: string;
17
+ readonly violationMessage?: string;
18
+ /** Attach free-form detail. Variable data goes HERE (or in extras), never in the name. */
19
+ message(msg: string): Violation;
20
+ }
21
+ /** Wire shape — the `type:"error"` RawEvent variant accepted by POST /collect. */
22
+ interface SeeErrorEvent {
23
+ type: "error";
24
+ kind: SeeKind;
25
+ /** Error class/name (e.g. "TypeError") or the violation name. */
26
+ error_type: string;
27
+ message: string;
28
+ stack?: string;
29
+ /** Consequence: "<error_type> causes the <subject> to <outcome>". */
30
+ subject: string;
31
+ outcome: string;
32
+ extras?: Record<string, string | number | boolean>;
33
+ url?: string;
34
+ user_id?: string;
35
+ anonymous_id?: string;
36
+ side: "client" | "server";
37
+ env?: string;
38
+ sdk_version: string;
39
+ ts: number;
40
+ }
41
+ interface SeeExtrasTail {
42
+ /** Attach debugging metadata. Callable repeatedly — keys merge, later wins. */
43
+ extras(extras: SeeExtras): SeeExtrasTail;
44
+ }
45
+ interface SeeOutcomeStep {
46
+ /** The user-visible impact: `.causes_the("checkout").to("use cached prices")`. */
47
+ to(outcome: string): SeeExtrasTail;
48
+ }
49
+ interface SeeChain {
50
+ /** Start the consequence sentence — the product surface affected. */
51
+ causes_the(subject: string): SeeOutcomeStep;
52
+ /** camelCase alias of {@link SeeChain.causes_the}. */
53
+ causesThe(subject: string): SeeOutcomeStep;
54
+ }
55
+ interface SeeViolationChain extends SeeChain {
56
+ /** Free-form detail. Variable data goes here (or extras), never in the name. */
57
+ message(msg: string): SeeViolationChain;
58
+ }
59
+
1
60
  declare global {
2
61
  interface Window {
3
62
  i18n?: {
@@ -8,7 +67,7 @@ declare global {
8
67
  };
9
68
  }
10
69
  }
11
- declare const version = "1.0.0";
70
+ declare const version = "4.0.0";
12
71
  interface User {
13
72
  user_id?: string;
14
73
  [attr: string]: unknown;
@@ -51,6 +110,13 @@ interface FlagsClientBrowserOptions {
51
110
  * true when `autoGuardrails` is true).
52
111
  */
53
112
  autoGuardrailGroups?: Partial<AutoCollectGroups>;
113
+ /**
114
+ * Emit `__auto_*` metric events for ALL visitors, not just experiment
115
+ * participants. Default false: auto-metrics are gated on the visitor having
116
+ * seen ≥1 experiment exposure (the only data the analysis pipeline reads;
117
+ * ungated emission is pure AE write cost at scale — see cost.md).
118
+ */
119
+ autoCollectAlways?: boolean;
54
120
  /** Which published env to read values from. Defaults to "prod". */
55
121
  env?: FlagsClientBrowserEnv;
56
122
  /**
@@ -68,12 +134,14 @@ declare class FlagsClientBrowser {
68
134
  private readonly baseUrl;
69
135
  private readonly autoGuardrails;
70
136
  private readonly autoGuardrailGroups;
137
+ private readonly autoCollectAlways;
71
138
  private readonly env;
72
139
  private evalResult;
73
140
  private anonId;
74
141
  private userId;
75
142
  private buffer;
76
143
  private telemetry;
144
+ private seeLimiter;
77
145
  private guardrailsInstalled;
78
146
  private listeners;
79
147
  private overrideListenerInstalled;
@@ -81,6 +149,12 @@ declare class FlagsClientBrowser {
81
149
  private onOverrideChange;
82
150
  constructor(opts: FlagsClientBrowserOptions);
83
151
  identify(user: User): Promise<void>;
152
+ /**
153
+ * Report a structured error into the errors primitive. Flushes immediately
154
+ * (beacon-first) — error occurrences are near-real-time, never queued behind
155
+ * the 5s metric batch. Spam-guarded by a 30s dedup window + per-session cap.
156
+ */
157
+ reportError(problem: unknown, consequence: Consequence, extras?: SeeExtras, kind?: SeeKind): void;
84
158
  get ready(): boolean;
85
159
  private notify;
86
160
  initFromBootstrap(data: EvalResponse): void;
@@ -171,10 +245,11 @@ interface ShipeasyClientConfig {
171
245
  */
172
246
  autoIdentify?: boolean;
173
247
  /**
174
- * Capture web vitals (LCP, CLS, INP, TTFB, FCP, navigation timing), JS /
175
- * network errors, and engagement signals (abandonment) as `__auto_*`
176
- * metric events. Defaults to `true` the worker bypasses event-catalog
177
- * validation for `__auto_*` names so this is safe out of the box.
248
+ * Capture web vitals (LCP, CLS, INP, TTFB, FCP, navigation timing) and
249
+ * engagement signals (abandonment) as `__auto_*` metric events, plus JS /
250
+ * network errors as structured error events in the errors primitive (same
251
+ * pipeline as `see()` grouped by fingerprint, near-real-time). Defaults
252
+ * to `true`.
178
253
  *
179
254
  * Pass `false` to disable everything, or a per-group object to narrow:
180
255
  *
@@ -183,8 +258,23 @@ interface ShipeasyClientConfig {
183
258
  * shipeasy({ clientKey, autoCollect: { errors: false } }); // vitals + engagement only
184
259
  * shipeasy({ clientKey }); // all groups on
185
260
  * ```
261
+ *
262
+ * Since 4.1.0, `__auto_*` metric events are only emitted for visitors who
263
+ * are in ≥1 active experiment (the analysis pipeline reads nothing else;
264
+ * gating cuts the dominant Analytics Engine write cost at scale). Pass
265
+ * `{ always: true }` to collect site-wide vitals regardless of experiment
266
+ * participation:
267
+ *
268
+ * ```ts
269
+ * shipeasy({ clientKey, autoCollect: { always: true } }); // site-wide vitals
270
+ * ```
271
+ *
272
+ * `__auto_abandoned` is always emitted (it fires when the user leaves
273
+ * before exposures could land) and error capture is unaffected.
186
274
  */
187
- autoCollect?: boolean | Partial<AutoCollectGroups>;
275
+ autoCollect?: boolean | (Partial<AutoCollectGroups> & {
276
+ always?: boolean;
277
+ });
188
278
  /**
189
279
  * Disable per-evaluation usage telemetry. Telemetry is ON by default — every
190
280
  * flag/config/experiment/killswitch read fires one fire-and-forget beacon
@@ -276,6 +366,58 @@ declare const flags: {
276
366
  /** True once identify() has completed and flags are available. */
277
367
  readonly ready: boolean;
278
368
  };
369
+ interface SeeApi {
370
+ /**
371
+ * Report a handled problem and its product consequence:
372
+ *
373
+ * ```ts
374
+ * import { see } from "@shipeasy/sdk/client";
375
+ *
376
+ * try {
377
+ * await submitOrder(order);
378
+ * } catch (e) {
379
+ * see(e).causes_the("checkout").to("use cached prices").extras({ order_id: order.id });
380
+ * }
381
+ * ```
382
+ *
383
+ * The chain dispatches on the next microtask, so the report ships
384
+ * immediately after the statement (no `.send()` needed) into the errors
385
+ * primitive — grouped by fingerprint, near-real-time timeseries. If you
386
+ * don't know the consequence of an exception, don't catch it.
387
+ */
388
+ (problem: unknown): SeeChain;
389
+ /**
390
+ * Report a non-exception problem. Prefer passing a caught Error to `see()`
391
+ * when one exists. The name is a stable identifier (it participates in the
392
+ * issue fingerprint) — variable data goes in `.message()` or `.extras()`.
393
+ *
394
+ * ```ts
395
+ * if (rows.length > LIMIT) {
396
+ * see.Violation("large query").message(`got ${rows.length} rows`)
397
+ * .causes_the("search results").to("be trimmed");
398
+ * }
399
+ * ```
400
+ */
401
+ Violation(name: string): SeeViolationChain;
402
+ /**
403
+ * Mark an exception as expected control flow — auto-capture skips it and
404
+ * nothing is reported. The reason must start with "because".
405
+ *
406
+ * ```ts
407
+ * } catch (e) {
408
+ * see.ControlFlowException(e, "because the blob wasn't an encoded Foo");
409
+ * return decodeAsBar(blob);
410
+ * }
411
+ * ```
412
+ */
413
+ ControlFlowException(err: unknown, because: string): void;
414
+ }
415
+ /**
416
+ * Structured error reporter — the whole grammar hangs off this one import.
417
+ * Safe to import anywhere; a call before `shipeasy({ clientKey })` warns and
418
+ * drops (never throws).
419
+ */
420
+ declare const see: SeeApi;
279
421
  declare const LABEL_MARKER_START = "\uFFF9";
280
422
  declare const LABEL_MARKER_SEP = "\uFFFA";
281
423
  declare const LABEL_MARKER_END = "\uFFFB";
@@ -314,4 +456,4 @@ interface I18nFacade {
314
456
  }
315
457
  declare const i18n: I18nFacade;
316
458
 
317
- export { type AutoCollectGroups, type BootstrapPayload, type ExperimentResult, FlagsClientBrowser, type FlagsClientBrowserEnv, type FlagsClientBrowserOptions, type I18nFacade, type I18nKey, type I18nRichComponents, type I18nString, type I18nTagRenderer, type I18nVariables, LABEL_MARKER_END, LABEL_MARKER_RE, LABEL_MARKER_SEP, LABEL_MARKER_START, type LabelAttrs, type ShipeasyClientConfig, type ShipeasySdkBridge, type User, _resetShipeasyForTests, attachDevtools, configureShipeasy, encodeLabelMarker, flags, getShipeasyClient, i18n, isDevtoolsRequested, labelAttrs, loadDevtools, readConfigOverride, readExpOverride, readGateOverride, shipeasy, version };
459
+ export { type AutoCollectGroups, type BootstrapPayload, type Consequence, type ExperimentResult, FlagsClientBrowser, type FlagsClientBrowserEnv, type FlagsClientBrowserOptions, type I18nFacade, type I18nKey, type I18nRichComponents, type I18nString, type I18nTagRenderer, type I18nVariables, LABEL_MARKER_END, LABEL_MARKER_RE, LABEL_MARKER_SEP, LABEL_MARKER_START, type LabelAttrs, type SeeApi, type SeeChain, type SeeErrorEvent, type SeeExtras, type SeeKind, type SeeViolationChain, type ShipeasyClientConfig, type ShipeasySdkBridge, type User, type Violation, _resetShipeasyForTests, attachDevtools, configureShipeasy, encodeLabelMarker, flags, getShipeasyClient, i18n, isDevtoolsRequested, labelAttrs, loadDevtools, readConfigOverride, readExpOverride, readGateOverride, see, shipeasy, version };
@@ -1,3 +1,62 @@
1
+ type SeeExtras = Record<string, string | number | boolean | null | undefined>;
2
+ type SeeKind = "caught" | "uncaught" | "unhandled_rejection" | "network" | "violation";
3
+ /** Built by `causesThe(subject).to(outcome)` — never constructed by hand. */
4
+ interface Consequence {
5
+ readonly __seConsequence: true;
6
+ readonly subject: string;
7
+ readonly outcome: string;
8
+ }
9
+ /**
10
+ * Non-exception problem, built by `violation(name)`. A plain branded object
11
+ * (not an Error subclass) so `.message()` can be a builder method without
12
+ * colliding with `Error.prototype.message`.
13
+ */
14
+ interface Violation {
15
+ readonly __seViolation: true;
16
+ readonly violationName: string;
17
+ readonly violationMessage?: string;
18
+ /** Attach free-form detail. Variable data goes HERE (or in extras), never in the name. */
19
+ message(msg: string): Violation;
20
+ }
21
+ /** Wire shape — the `type:"error"` RawEvent variant accepted by POST /collect. */
22
+ interface SeeErrorEvent {
23
+ type: "error";
24
+ kind: SeeKind;
25
+ /** Error class/name (e.g. "TypeError") or the violation name. */
26
+ error_type: string;
27
+ message: string;
28
+ stack?: string;
29
+ /** Consequence: "<error_type> causes the <subject> to <outcome>". */
30
+ subject: string;
31
+ outcome: string;
32
+ extras?: Record<string, string | number | boolean>;
33
+ url?: string;
34
+ user_id?: string;
35
+ anonymous_id?: string;
36
+ side: "client" | "server";
37
+ env?: string;
38
+ sdk_version: string;
39
+ ts: number;
40
+ }
41
+ interface SeeExtrasTail {
42
+ /** Attach debugging metadata. Callable repeatedly — keys merge, later wins. */
43
+ extras(extras: SeeExtras): SeeExtrasTail;
44
+ }
45
+ interface SeeOutcomeStep {
46
+ /** The user-visible impact: `.causes_the("checkout").to("use cached prices")`. */
47
+ to(outcome: string): SeeExtrasTail;
48
+ }
49
+ interface SeeChain {
50
+ /** Start the consequence sentence — the product surface affected. */
51
+ causes_the(subject: string): SeeOutcomeStep;
52
+ /** camelCase alias of {@link SeeChain.causes_the}. */
53
+ causesThe(subject: string): SeeOutcomeStep;
54
+ }
55
+ interface SeeViolationChain extends SeeChain {
56
+ /** Free-form detail. Variable data goes here (or extras), never in the name. */
57
+ message(msg: string): SeeViolationChain;
58
+ }
59
+
1
60
  declare global {
2
61
  interface Window {
3
62
  i18n?: {
@@ -8,7 +67,7 @@ declare global {
8
67
  };
9
68
  }
10
69
  }
11
- declare const version = "1.0.0";
70
+ declare const version = "4.0.0";
12
71
  interface User {
13
72
  user_id?: string;
14
73
  [attr: string]: unknown;
@@ -51,6 +110,13 @@ interface FlagsClientBrowserOptions {
51
110
  * true when `autoGuardrails` is true).
52
111
  */
53
112
  autoGuardrailGroups?: Partial<AutoCollectGroups>;
113
+ /**
114
+ * Emit `__auto_*` metric events for ALL visitors, not just experiment
115
+ * participants. Default false: auto-metrics are gated on the visitor having
116
+ * seen ≥1 experiment exposure (the only data the analysis pipeline reads;
117
+ * ungated emission is pure AE write cost at scale — see cost.md).
118
+ */
119
+ autoCollectAlways?: boolean;
54
120
  /** Which published env to read values from. Defaults to "prod". */
55
121
  env?: FlagsClientBrowserEnv;
56
122
  /**
@@ -68,12 +134,14 @@ declare class FlagsClientBrowser {
68
134
  private readonly baseUrl;
69
135
  private readonly autoGuardrails;
70
136
  private readonly autoGuardrailGroups;
137
+ private readonly autoCollectAlways;
71
138
  private readonly env;
72
139
  private evalResult;
73
140
  private anonId;
74
141
  private userId;
75
142
  private buffer;
76
143
  private telemetry;
144
+ private seeLimiter;
77
145
  private guardrailsInstalled;
78
146
  private listeners;
79
147
  private overrideListenerInstalled;
@@ -81,6 +149,12 @@ declare class FlagsClientBrowser {
81
149
  private onOverrideChange;
82
150
  constructor(opts: FlagsClientBrowserOptions);
83
151
  identify(user: User): Promise<void>;
152
+ /**
153
+ * Report a structured error into the errors primitive. Flushes immediately
154
+ * (beacon-first) — error occurrences are near-real-time, never queued behind
155
+ * the 5s metric batch. Spam-guarded by a 30s dedup window + per-session cap.
156
+ */
157
+ reportError(problem: unknown, consequence: Consequence, extras?: SeeExtras, kind?: SeeKind): void;
84
158
  get ready(): boolean;
85
159
  private notify;
86
160
  initFromBootstrap(data: EvalResponse): void;
@@ -171,10 +245,11 @@ interface ShipeasyClientConfig {
171
245
  */
172
246
  autoIdentify?: boolean;
173
247
  /**
174
- * Capture web vitals (LCP, CLS, INP, TTFB, FCP, navigation timing), JS /
175
- * network errors, and engagement signals (abandonment) as `__auto_*`
176
- * metric events. Defaults to `true` the worker bypasses event-catalog
177
- * validation for `__auto_*` names so this is safe out of the box.
248
+ * Capture web vitals (LCP, CLS, INP, TTFB, FCP, navigation timing) and
249
+ * engagement signals (abandonment) as `__auto_*` metric events, plus JS /
250
+ * network errors as structured error events in the errors primitive (same
251
+ * pipeline as `see()` grouped by fingerprint, near-real-time). Defaults
252
+ * to `true`.
178
253
  *
179
254
  * Pass `false` to disable everything, or a per-group object to narrow:
180
255
  *
@@ -183,8 +258,23 @@ interface ShipeasyClientConfig {
183
258
  * shipeasy({ clientKey, autoCollect: { errors: false } }); // vitals + engagement only
184
259
  * shipeasy({ clientKey }); // all groups on
185
260
  * ```
261
+ *
262
+ * Since 4.1.0, `__auto_*` metric events are only emitted for visitors who
263
+ * are in ≥1 active experiment (the analysis pipeline reads nothing else;
264
+ * gating cuts the dominant Analytics Engine write cost at scale). Pass
265
+ * `{ always: true }` to collect site-wide vitals regardless of experiment
266
+ * participation:
267
+ *
268
+ * ```ts
269
+ * shipeasy({ clientKey, autoCollect: { always: true } }); // site-wide vitals
270
+ * ```
271
+ *
272
+ * `__auto_abandoned` is always emitted (it fires when the user leaves
273
+ * before exposures could land) and error capture is unaffected.
186
274
  */
187
- autoCollect?: boolean | Partial<AutoCollectGroups>;
275
+ autoCollect?: boolean | (Partial<AutoCollectGroups> & {
276
+ always?: boolean;
277
+ });
188
278
  /**
189
279
  * Disable per-evaluation usage telemetry. Telemetry is ON by default — every
190
280
  * flag/config/experiment/killswitch read fires one fire-and-forget beacon
@@ -276,6 +366,58 @@ declare const flags: {
276
366
  /** True once identify() has completed and flags are available. */
277
367
  readonly ready: boolean;
278
368
  };
369
+ interface SeeApi {
370
+ /**
371
+ * Report a handled problem and its product consequence:
372
+ *
373
+ * ```ts
374
+ * import { see } from "@shipeasy/sdk/client";
375
+ *
376
+ * try {
377
+ * await submitOrder(order);
378
+ * } catch (e) {
379
+ * see(e).causes_the("checkout").to("use cached prices").extras({ order_id: order.id });
380
+ * }
381
+ * ```
382
+ *
383
+ * The chain dispatches on the next microtask, so the report ships
384
+ * immediately after the statement (no `.send()` needed) into the errors
385
+ * primitive — grouped by fingerprint, near-real-time timeseries. If you
386
+ * don't know the consequence of an exception, don't catch it.
387
+ */
388
+ (problem: unknown): SeeChain;
389
+ /**
390
+ * Report a non-exception problem. Prefer passing a caught Error to `see()`
391
+ * when one exists. The name is a stable identifier (it participates in the
392
+ * issue fingerprint) — variable data goes in `.message()` or `.extras()`.
393
+ *
394
+ * ```ts
395
+ * if (rows.length > LIMIT) {
396
+ * see.Violation("large query").message(`got ${rows.length} rows`)
397
+ * .causes_the("search results").to("be trimmed");
398
+ * }
399
+ * ```
400
+ */
401
+ Violation(name: string): SeeViolationChain;
402
+ /**
403
+ * Mark an exception as expected control flow — auto-capture skips it and
404
+ * nothing is reported. The reason must start with "because".
405
+ *
406
+ * ```ts
407
+ * } catch (e) {
408
+ * see.ControlFlowException(e, "because the blob wasn't an encoded Foo");
409
+ * return decodeAsBar(blob);
410
+ * }
411
+ * ```
412
+ */
413
+ ControlFlowException(err: unknown, because: string): void;
414
+ }
415
+ /**
416
+ * Structured error reporter — the whole grammar hangs off this one import.
417
+ * Safe to import anywhere; a call before `shipeasy({ clientKey })` warns and
418
+ * drops (never throws).
419
+ */
420
+ declare const see: SeeApi;
279
421
  declare const LABEL_MARKER_START = "\uFFF9";
280
422
  declare const LABEL_MARKER_SEP = "\uFFFA";
281
423
  declare const LABEL_MARKER_END = "\uFFFB";
@@ -314,4 +456,4 @@ interface I18nFacade {
314
456
  }
315
457
  declare const i18n: I18nFacade;
316
458
 
317
- export { type AutoCollectGroups, type BootstrapPayload, type ExperimentResult, FlagsClientBrowser, type FlagsClientBrowserEnv, type FlagsClientBrowserOptions, type I18nFacade, type I18nKey, type I18nRichComponents, type I18nString, type I18nTagRenderer, type I18nVariables, LABEL_MARKER_END, LABEL_MARKER_RE, LABEL_MARKER_SEP, LABEL_MARKER_START, type LabelAttrs, type ShipeasyClientConfig, type ShipeasySdkBridge, type User, _resetShipeasyForTests, attachDevtools, configureShipeasy, encodeLabelMarker, flags, getShipeasyClient, i18n, isDevtoolsRequested, labelAttrs, loadDevtools, readConfigOverride, readExpOverride, readGateOverride, shipeasy, version };
459
+ export { type AutoCollectGroups, type BootstrapPayload, type Consequence, type ExperimentResult, FlagsClientBrowser, type FlagsClientBrowserEnv, type FlagsClientBrowserOptions, type I18nFacade, type I18nKey, type I18nRichComponents, type I18nString, type I18nTagRenderer, type I18nVariables, LABEL_MARKER_END, LABEL_MARKER_RE, LABEL_MARKER_SEP, LABEL_MARKER_START, type LabelAttrs, type SeeApi, type SeeChain, type SeeErrorEvent, type SeeExtras, type SeeKind, type SeeViolationChain, type ShipeasyClientConfig, type ShipeasySdkBridge, type User, type Violation, _resetShipeasyForTests, attachDevtools, configureShipeasy, encodeLabelMarker, flags, getShipeasyClient, i18n, isDevtoolsRequested, labelAttrs, loadDevtools, readConfigOverride, readExpOverride, readGateOverride, see, shipeasy, version };