@shipeasy/sdk 1.0.0 → 1.2.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/LICENSE +40 -0
- package/README.md +94 -0
- package/dist/client/index.d.mts +143 -7
- package/dist/client/index.d.ts +143 -7
- package/dist/client/index.js +509 -25
- package/dist/client/index.mjs +492 -25
- package/dist/server/index.d.mts +38 -1
- package/dist/server/index.d.ts +38 -1
- package/dist/server/index.js +94 -1
- package/dist/server/index.mjs +89 -1
- package/package.json +34 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
Shipeasy Source-Available License (Shipeasy-SAL) 1.0
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shipeasy, Inc. All rights reserved.
|
|
4
|
+
|
|
5
|
+
1. License Grant.
|
|
6
|
+
Subject to the terms of this License, Shipeasy, Inc. ("Shipeasy") grants
|
|
7
|
+
you a non-exclusive, non-transferable, revocable, worldwide license to:
|
|
8
|
+
|
|
9
|
+
(a) Use, copy, and modify the Software solely as a client integration for
|
|
10
|
+
interacting with Shipeasy's hosted services (the "Service");
|
|
11
|
+
(b) Distribute the Software as part of an application that calls the
|
|
12
|
+
Service, in object form, provided the recipient also agrees to this
|
|
13
|
+
License.
|
|
14
|
+
|
|
15
|
+
2. Restrictions.
|
|
16
|
+
You may not:
|
|
17
|
+
|
|
18
|
+
(a) Use the Software, in whole or in part, to build, host, or operate any
|
|
19
|
+
service that competes with the Service or that provides feature-flag,
|
|
20
|
+
experimentation, configuration, internationalization, or related
|
|
21
|
+
functionality to third parties on a commercial basis;
|
|
22
|
+
(b) Sublicense, sell, rent, or lease the Software;
|
|
23
|
+
(c) Remove or alter copyright notices, license terms, or attribution.
|
|
24
|
+
|
|
25
|
+
3. Contributions.
|
|
26
|
+
Any pull request you submit is licensed back to Shipeasy under this
|
|
27
|
+
License plus a perpetual, irrevocable right for Shipeasy to relicense.
|
|
28
|
+
|
|
29
|
+
4. Trademarks.
|
|
30
|
+
This License does not grant rights in the names "Shipeasy", related
|
|
31
|
+
marks, or logos.
|
|
32
|
+
|
|
33
|
+
5. No Warranty / Limitation of Liability.
|
|
34
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. IN NO
|
|
35
|
+
EVENT SHALL SHIPEASY BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER
|
|
36
|
+
LIABILITY ARISING FROM USE OF THE SOFTWARE.
|
|
37
|
+
|
|
38
|
+
6. Termination.
|
|
39
|
+
This License terminates automatically if you breach it. Sections 2-5
|
|
40
|
+
survive termination.
|
package/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# @shipeasy/sdk
|
|
2
|
+
|
|
3
|
+
Feature gates, runtime configs, experiments, and metrics for the
|
|
4
|
+
[Shipeasy](https://shipeasy.ai) hosted service.
|
|
5
|
+
|
|
6
|
+
> Source-available under the [Shipeasy-SAL 1.0](./LICENSE). Use it freely
|
|
7
|
+
> as a client of Shipeasy. Don't use it to build a competing service.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @shipeasy/sdk
|
|
13
|
+
# or
|
|
14
|
+
pnpm add @shipeasy/sdk
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
For React projects use [`@shipeasy/sdk-react`](https://github.com/shipeasy-ai/sdk-react)
|
|
18
|
+
which wraps this package with a `<ShipeasyProvider>` and hooks.
|
|
19
|
+
|
|
20
|
+
## Quickstart — browser
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { FlagsClientBrowser } from "@shipeasy/sdk/client";
|
|
24
|
+
|
|
25
|
+
const client = new FlagsClientBrowser({
|
|
26
|
+
sdkKey: process.env.NEXT_PUBLIC_SHIPEASY_CLIENT_KEY!,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
await client.identify({ user_id: "user-123", plan: "pro" });
|
|
30
|
+
|
|
31
|
+
if (client.getFlag("new_checkout")) {
|
|
32
|
+
// ship it
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const cfg = client.getConfig<{ max_uploads: number }>("upload_limits");
|
|
36
|
+
const { params } = client.getExperiment("hero_cta", {
|
|
37
|
+
primary_label: "Sign up",
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`identify()` automatically merges browser context (`locale`, `timezone`,
|
|
42
|
+
`path`, `referrer`, `screen_*`, `user_agent`) and a persisted
|
|
43
|
+
`anonymous_id` into the payload — so gate rules can target by locale or
|
|
44
|
+
holdouts can hash anonymous visitors out of the box.
|
|
45
|
+
|
|
46
|
+
## Quickstart — server (Node, Cloudflare Worker, Deno)
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { FlagsClient } from "@shipeasy/sdk/server";
|
|
50
|
+
|
|
51
|
+
const client = new FlagsClient({ sdkKey: process.env.SHIPEASY_SERVER_KEY! });
|
|
52
|
+
|
|
53
|
+
const cfg = await client.getConfig("plan_limits", { user_id: "u-1" });
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Drop-in `<script>` loader (no bundler)
|
|
57
|
+
|
|
58
|
+
```html
|
|
59
|
+
<script
|
|
60
|
+
src="https://cdn.shipeasy.ai/sdk/loader.js"
|
|
61
|
+
data-sdk-key="sdk_client_..."
|
|
62
|
+
data-user-id="user-123"
|
|
63
|
+
data-user-email="u@x.com"
|
|
64
|
+
data-user-plan="pro"
|
|
65
|
+
data-attrs='{"country":"US"}'
|
|
66
|
+
defer
|
|
67
|
+
></script>
|
|
68
|
+
<script>
|
|
69
|
+
await window.shipeasy.ready;
|
|
70
|
+
if (window.shipeasy.getFlag("new_checkout")) { /* … */ }
|
|
71
|
+
</script>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The loader IIFE is published to a public R2 bucket on every release and
|
|
75
|
+
cached for 1y at `loader-vX.Y.Z.js` (immutable) plus a rolling 5-minute
|
|
76
|
+
`loader.js`.
|
|
77
|
+
|
|
78
|
+
## Devtools overlay
|
|
79
|
+
|
|
80
|
+
Press `Shift+Alt+S` on any page running the SDK (or append `?se=1` to the
|
|
81
|
+
URL). The Shipeasy devtools panel mounts in a Shadow DOM overlay and lets
|
|
82
|
+
you flip every gate / config / experiment / translation **for the current
|
|
83
|
+
session only** — handy for QA, demos, and bug repro.
|
|
84
|
+
|
|
85
|
+
## Documentation
|
|
86
|
+
|
|
87
|
+
Full docs at [docs.shipeasy.ai](https://docs.shipeasy.ai). API surfaces
|
|
88
|
+
covered there: targeting rules, holdouts, sequential stats, custom
|
|
89
|
+
metrics, Slack digests, OAuth/SSO, Claude/MCP integration.
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
[Shipeasy-SAL 1.0](./LICENSE) — source-available, non-commercial-use,
|
|
94
|
+
permitted for use as a Shipeasy client.
|
package/dist/client/index.d.mts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
interface Window {
|
|
3
|
+
i18n?: {
|
|
4
|
+
t: (key: string, vars?: Record<string, string | number>) => string;
|
|
5
|
+
ready: (cb: () => void) => void;
|
|
6
|
+
on: (event: "update", cb: () => void) => () => void;
|
|
7
|
+
locale: string | null;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
}
|
|
1
11
|
declare const version = "1.0.0";
|
|
2
12
|
interface User {
|
|
3
13
|
user_id?: string;
|
|
@@ -8,41 +18,167 @@ interface ExperimentResult<P> {
|
|
|
8
18
|
group: string;
|
|
9
19
|
params: P;
|
|
10
20
|
}
|
|
11
|
-
interface EvalFlagResult {
|
|
12
|
-
enabled: boolean;
|
|
13
|
-
}
|
|
14
21
|
interface EvalExpResult {
|
|
15
|
-
|
|
22
|
+
inExperiment: boolean;
|
|
16
23
|
group: string;
|
|
17
24
|
params: Record<string, unknown>;
|
|
18
25
|
}
|
|
19
26
|
interface EvalResponse {
|
|
20
|
-
flags: Record<string,
|
|
27
|
+
flags: Record<string, boolean>;
|
|
28
|
+
configs: Record<string, unknown>;
|
|
21
29
|
experiments: Record<string, EvalExpResult>;
|
|
22
30
|
}
|
|
31
|
+
type FlagsClientBrowserEnv = "dev" | "staging" | "prod";
|
|
23
32
|
interface FlagsClientBrowserOptions {
|
|
24
33
|
sdkKey: string;
|
|
25
34
|
baseUrl?: string;
|
|
26
35
|
autoGuardrails?: boolean;
|
|
36
|
+
/** Which published env to read values from. Defaults to "prod". */
|
|
37
|
+
env?: FlagsClientBrowserEnv;
|
|
27
38
|
}
|
|
28
39
|
declare class FlagsClientBrowser {
|
|
29
40
|
private readonly sdkKey;
|
|
30
41
|
private readonly baseUrl;
|
|
31
42
|
private readonly autoGuardrails;
|
|
43
|
+
private readonly env;
|
|
32
44
|
private evalResult;
|
|
33
45
|
private anonId;
|
|
34
46
|
private userId;
|
|
35
47
|
private buffer;
|
|
36
48
|
private guardrailsInstalled;
|
|
49
|
+
private listeners;
|
|
50
|
+
private overrideListenerInstalled;
|
|
51
|
+
private onOverrideChange;
|
|
37
52
|
constructor(opts: FlagsClientBrowserOptions);
|
|
38
53
|
identify(user: User): Promise<void>;
|
|
54
|
+
get ready(): boolean;
|
|
55
|
+
private notify;
|
|
39
56
|
initFromBootstrap(data: EvalResponse): void;
|
|
40
57
|
getFlag(name: string): boolean;
|
|
41
58
|
getConfig<T = unknown>(name: string, decode?: (raw: unknown) => T): T | undefined;
|
|
42
|
-
getExperiment<P extends Record<string, unknown>>(name: string, defaultParams: P, decode?: (raw: unknown) => P): ExperimentResult<P>;
|
|
59
|
+
getExperiment<P extends Record<string, unknown>>(name: string, defaultParams: P, decode?: (raw: unknown) => P, variants?: Record<string, Partial<P>>): ExperimentResult<P>;
|
|
60
|
+
/**
|
|
61
|
+
* Subscribe to state changes — fires after identify() completes and on
|
|
62
|
+
* `se:override:change` events from the devtools overlay. Returns an
|
|
63
|
+
* unsubscribe function. Used by framework adapters to trigger re-renders.
|
|
64
|
+
*/
|
|
65
|
+
subscribe(listener: () => void): () => void;
|
|
66
|
+
/**
|
|
67
|
+
* Publishes the SDK to `window.__shipeasy` so the devtools overlay can read
|
|
68
|
+
* current values. Idempotent. Returns the bridge object for tests.
|
|
69
|
+
*/
|
|
70
|
+
installBridge(): ShipeasySdkBridge | null;
|
|
43
71
|
track(eventName: string, props?: Record<string, unknown>): void;
|
|
44
72
|
flush(): Promise<void>;
|
|
45
73
|
destroy(): void;
|
|
46
74
|
}
|
|
75
|
+
declare function readGateOverride(name: string): boolean | null;
|
|
76
|
+
declare function readConfigOverride(name: string): unknown;
|
|
77
|
+
declare function readExpOverride(name: string): string | null;
|
|
78
|
+
declare function isDevtoolsRequested(): boolean;
|
|
79
|
+
/** Bridge written to window.__shipeasy — mirrors @shipeasy/devtools' contract. */
|
|
80
|
+
interface ShipeasySdkBridge {
|
|
81
|
+
getFlag(name: string): boolean;
|
|
82
|
+
getExperiment(name: string): {
|
|
83
|
+
inExperiment: boolean;
|
|
84
|
+
group: string;
|
|
85
|
+
} | undefined;
|
|
86
|
+
getConfig(name: string): unknown;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* If the host page already mounted the standalone devtools IIFE bundle (which
|
|
90
|
+
* exposes `window.__shipeasy_devtools_global`), call its init() and wire up a
|
|
91
|
+
* toggle handle at `window.__shipeasy_devtools`. No-op when the bundle is
|
|
92
|
+
* absent — the customer is responsible for mounting it themselves.
|
|
93
|
+
*/
|
|
94
|
+
declare function loadDevtools(opts?: {
|
|
95
|
+
adminUrl?: string;
|
|
96
|
+
edgeUrl?: string;
|
|
97
|
+
}): void;
|
|
98
|
+
interface AttachDevtoolsOptions {
|
|
99
|
+
/** Hotkey string in the form "Shift+Alt+S". */
|
|
100
|
+
hotkey?: string;
|
|
101
|
+
adminUrl?: string;
|
|
102
|
+
edgeUrl?: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* One-call bootstrap for the devtools overlay. Installs the bridge, optionally
|
|
106
|
+
* auto-loads the overlay if the page was opened with `?se`, registers a hotkey
|
|
107
|
+
* listener for opening/toggling the overlay, and re-publishes the bridge after
|
|
108
|
+
* each `identify()`/override change. Returns an unsubscribe function for
|
|
109
|
+
* cleanup (e.g. React effect teardown).
|
|
110
|
+
*/
|
|
111
|
+
declare function attachDevtools(client: FlagsClientBrowser, opts?: AttachDevtoolsOptions): () => void;
|
|
112
|
+
/** Configure the singleton. Idempotent — re-calling with the same opts is a no-op. */
|
|
113
|
+
declare function configureShipeasy(opts: FlagsClientBrowserOptions): FlagsClientBrowser;
|
|
114
|
+
/** Returns the configured singleton, or null if configureShipeasy() hasn't run yet. */
|
|
115
|
+
declare function getShipeasyClient(): FlagsClientBrowser | null;
|
|
116
|
+
/**
|
|
117
|
+
* Test helper — drop the singleton so the next configureShipeasy() builds fresh.
|
|
118
|
+
* Not part of the documented surface; production code should never call this.
|
|
119
|
+
*/
|
|
120
|
+
declare function _resetShipeasyForTests(): void;
|
|
121
|
+
/**
|
|
122
|
+
* Universal flags facade. Methods return safe defaults when the singleton
|
|
123
|
+
* hasn't been configured yet (false / undefined / `notIn` experiment), so
|
|
124
|
+
* importing this in a module that loads before app boot is harmless.
|
|
125
|
+
*/
|
|
126
|
+
declare const flags: {
|
|
127
|
+
configure(opts: FlagsClientBrowserOptions): void;
|
|
128
|
+
identify(user: User): Promise<void>;
|
|
129
|
+
/** Read a feature gate. Returns false until identify() resolves. */
|
|
130
|
+
get(name: string): boolean;
|
|
131
|
+
getConfig<T = unknown>(name: string, decode?: (raw: unknown) => T): T | undefined;
|
|
132
|
+
getExperiment<P extends Record<string, unknown>>(name: string, defaultParams: P, decode?: (raw: unknown) => P, variants?: Record<string, Partial<P>>): ExperimentResult<P>;
|
|
133
|
+
track(eventName: string, props?: Record<string, unknown>): void;
|
|
134
|
+
flush(): Promise<void>;
|
|
135
|
+
/** Subscribe for change notifications (identify/override). Used by framework adapters. */
|
|
136
|
+
subscribe(listener: () => void): () => void;
|
|
137
|
+
/** True once identify() has completed and flags are available. */
|
|
138
|
+
readonly ready: boolean;
|
|
139
|
+
};
|
|
140
|
+
declare const LABEL_MARKER_START = "\uFFF9";
|
|
141
|
+
declare const LABEL_MARKER_SEP = "\uFFFA";
|
|
142
|
+
declare const LABEL_MARKER_END = "\uFFFB";
|
|
143
|
+
declare const LABEL_MARKER_RE: RegExp;
|
|
144
|
+
declare function encodeLabelMarker(key: string, value: string): string;
|
|
145
|
+
interface LabelAttrs {
|
|
146
|
+
"data-label": string;
|
|
147
|
+
"data-variables"?: string;
|
|
148
|
+
"data-label-desc"?: string;
|
|
149
|
+
}
|
|
150
|
+
declare function labelAttrs(key: string, variables?: Record<string, string | number>, desc?: string): LabelAttrs;
|
|
151
|
+
/**
|
|
152
|
+
* Universal i18n facade. Backed by the `window.i18n` global the loader
|
|
153
|
+
* script installs. Returns the key itself when the loader hasn't run
|
|
154
|
+
* (SSR, missing script tag, before profile fetch completes), so call
|
|
155
|
+
* sites never need to null-check.
|
|
156
|
+
*/
|
|
157
|
+
declare const i18n: {
|
|
158
|
+
t(key: string, variables?: Record<string, string | number>): string;
|
|
159
|
+
/**
|
|
160
|
+
* Translate a key and return a framework element (e.g. React <span>)
|
|
161
|
+
* carrying `data-label` / `data-variables` attributes so the ShipEasy
|
|
162
|
+
* devtools "Edit labels" overlay can highlight and edit it in place.
|
|
163
|
+
*
|
|
164
|
+
* Requires a one-time setup call: `i18n.configure({ createElement })`.
|
|
165
|
+
* The returned value is whatever `createElement` returns — pass React's
|
|
166
|
+
* `createElement`, Vue's `h`, Solid's `createSignal`-based factory, etc.
|
|
167
|
+
*
|
|
168
|
+
* Falls back to a plain translated string if `createElement` was not
|
|
169
|
+
* configured (e.g. server-side or in non-JSX contexts).
|
|
170
|
+
*/
|
|
171
|
+
tEl(key: string, variables?: Record<string, string | number>, desc?: string): any;
|
|
172
|
+
/** Wire up the element creator once at app startup (call before any tEl use). */
|
|
173
|
+
configure(opts: {
|
|
174
|
+
createElement: (tag: string, props: object, children: string) => any;
|
|
175
|
+
}): void;
|
|
176
|
+
readonly locale: string | null;
|
|
177
|
+
readonly ready: boolean;
|
|
178
|
+
/** Resolves when the loader has installed window.i18n and fetched a profile. */
|
|
179
|
+
whenReady(): Promise<void>;
|
|
180
|
+
/** Subscribe to locale/profile updates. Returns an unsubscribe fn. */
|
|
181
|
+
onUpdate(cb: () => void): () => void;
|
|
182
|
+
};
|
|
47
183
|
|
|
48
|
-
export { type ExperimentResult, FlagsClientBrowser, type FlagsClientBrowserOptions, type User, version };
|
|
184
|
+
export { type ExperimentResult, FlagsClientBrowser, type FlagsClientBrowserEnv, type FlagsClientBrowserOptions, LABEL_MARKER_END, LABEL_MARKER_RE, LABEL_MARKER_SEP, LABEL_MARKER_START, type LabelAttrs, type ShipeasySdkBridge, type User, _resetShipeasyForTests, attachDevtools, configureShipeasy, encodeLabelMarker, flags, getShipeasyClient, i18n, isDevtoolsRequested, labelAttrs, loadDevtools, readConfigOverride, readExpOverride, readGateOverride, version };
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
interface Window {
|
|
3
|
+
i18n?: {
|
|
4
|
+
t: (key: string, vars?: Record<string, string | number>) => string;
|
|
5
|
+
ready: (cb: () => void) => void;
|
|
6
|
+
on: (event: "update", cb: () => void) => () => void;
|
|
7
|
+
locale: string | null;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
}
|
|
1
11
|
declare const version = "1.0.0";
|
|
2
12
|
interface User {
|
|
3
13
|
user_id?: string;
|
|
@@ -8,41 +18,167 @@ interface ExperimentResult<P> {
|
|
|
8
18
|
group: string;
|
|
9
19
|
params: P;
|
|
10
20
|
}
|
|
11
|
-
interface EvalFlagResult {
|
|
12
|
-
enabled: boolean;
|
|
13
|
-
}
|
|
14
21
|
interface EvalExpResult {
|
|
15
|
-
|
|
22
|
+
inExperiment: boolean;
|
|
16
23
|
group: string;
|
|
17
24
|
params: Record<string, unknown>;
|
|
18
25
|
}
|
|
19
26
|
interface EvalResponse {
|
|
20
|
-
flags: Record<string,
|
|
27
|
+
flags: Record<string, boolean>;
|
|
28
|
+
configs: Record<string, unknown>;
|
|
21
29
|
experiments: Record<string, EvalExpResult>;
|
|
22
30
|
}
|
|
31
|
+
type FlagsClientBrowserEnv = "dev" | "staging" | "prod";
|
|
23
32
|
interface FlagsClientBrowserOptions {
|
|
24
33
|
sdkKey: string;
|
|
25
34
|
baseUrl?: string;
|
|
26
35
|
autoGuardrails?: boolean;
|
|
36
|
+
/** Which published env to read values from. Defaults to "prod". */
|
|
37
|
+
env?: FlagsClientBrowserEnv;
|
|
27
38
|
}
|
|
28
39
|
declare class FlagsClientBrowser {
|
|
29
40
|
private readonly sdkKey;
|
|
30
41
|
private readonly baseUrl;
|
|
31
42
|
private readonly autoGuardrails;
|
|
43
|
+
private readonly env;
|
|
32
44
|
private evalResult;
|
|
33
45
|
private anonId;
|
|
34
46
|
private userId;
|
|
35
47
|
private buffer;
|
|
36
48
|
private guardrailsInstalled;
|
|
49
|
+
private listeners;
|
|
50
|
+
private overrideListenerInstalled;
|
|
51
|
+
private onOverrideChange;
|
|
37
52
|
constructor(opts: FlagsClientBrowserOptions);
|
|
38
53
|
identify(user: User): Promise<void>;
|
|
54
|
+
get ready(): boolean;
|
|
55
|
+
private notify;
|
|
39
56
|
initFromBootstrap(data: EvalResponse): void;
|
|
40
57
|
getFlag(name: string): boolean;
|
|
41
58
|
getConfig<T = unknown>(name: string, decode?: (raw: unknown) => T): T | undefined;
|
|
42
|
-
getExperiment<P extends Record<string, unknown>>(name: string, defaultParams: P, decode?: (raw: unknown) => P): ExperimentResult<P>;
|
|
59
|
+
getExperiment<P extends Record<string, unknown>>(name: string, defaultParams: P, decode?: (raw: unknown) => P, variants?: Record<string, Partial<P>>): ExperimentResult<P>;
|
|
60
|
+
/**
|
|
61
|
+
* Subscribe to state changes — fires after identify() completes and on
|
|
62
|
+
* `se:override:change` events from the devtools overlay. Returns an
|
|
63
|
+
* unsubscribe function. Used by framework adapters to trigger re-renders.
|
|
64
|
+
*/
|
|
65
|
+
subscribe(listener: () => void): () => void;
|
|
66
|
+
/**
|
|
67
|
+
* Publishes the SDK to `window.__shipeasy` so the devtools overlay can read
|
|
68
|
+
* current values. Idempotent. Returns the bridge object for tests.
|
|
69
|
+
*/
|
|
70
|
+
installBridge(): ShipeasySdkBridge | null;
|
|
43
71
|
track(eventName: string, props?: Record<string, unknown>): void;
|
|
44
72
|
flush(): Promise<void>;
|
|
45
73
|
destroy(): void;
|
|
46
74
|
}
|
|
75
|
+
declare function readGateOverride(name: string): boolean | null;
|
|
76
|
+
declare function readConfigOverride(name: string): unknown;
|
|
77
|
+
declare function readExpOverride(name: string): string | null;
|
|
78
|
+
declare function isDevtoolsRequested(): boolean;
|
|
79
|
+
/** Bridge written to window.__shipeasy — mirrors @shipeasy/devtools' contract. */
|
|
80
|
+
interface ShipeasySdkBridge {
|
|
81
|
+
getFlag(name: string): boolean;
|
|
82
|
+
getExperiment(name: string): {
|
|
83
|
+
inExperiment: boolean;
|
|
84
|
+
group: string;
|
|
85
|
+
} | undefined;
|
|
86
|
+
getConfig(name: string): unknown;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* If the host page already mounted the standalone devtools IIFE bundle (which
|
|
90
|
+
* exposes `window.__shipeasy_devtools_global`), call its init() and wire up a
|
|
91
|
+
* toggle handle at `window.__shipeasy_devtools`. No-op when the bundle is
|
|
92
|
+
* absent — the customer is responsible for mounting it themselves.
|
|
93
|
+
*/
|
|
94
|
+
declare function loadDevtools(opts?: {
|
|
95
|
+
adminUrl?: string;
|
|
96
|
+
edgeUrl?: string;
|
|
97
|
+
}): void;
|
|
98
|
+
interface AttachDevtoolsOptions {
|
|
99
|
+
/** Hotkey string in the form "Shift+Alt+S". */
|
|
100
|
+
hotkey?: string;
|
|
101
|
+
adminUrl?: string;
|
|
102
|
+
edgeUrl?: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* One-call bootstrap for the devtools overlay. Installs the bridge, optionally
|
|
106
|
+
* auto-loads the overlay if the page was opened with `?se`, registers a hotkey
|
|
107
|
+
* listener for opening/toggling the overlay, and re-publishes the bridge after
|
|
108
|
+
* each `identify()`/override change. Returns an unsubscribe function for
|
|
109
|
+
* cleanup (e.g. React effect teardown).
|
|
110
|
+
*/
|
|
111
|
+
declare function attachDevtools(client: FlagsClientBrowser, opts?: AttachDevtoolsOptions): () => void;
|
|
112
|
+
/** Configure the singleton. Idempotent — re-calling with the same opts is a no-op. */
|
|
113
|
+
declare function configureShipeasy(opts: FlagsClientBrowserOptions): FlagsClientBrowser;
|
|
114
|
+
/** Returns the configured singleton, or null if configureShipeasy() hasn't run yet. */
|
|
115
|
+
declare function getShipeasyClient(): FlagsClientBrowser | null;
|
|
116
|
+
/**
|
|
117
|
+
* Test helper — drop the singleton so the next configureShipeasy() builds fresh.
|
|
118
|
+
* Not part of the documented surface; production code should never call this.
|
|
119
|
+
*/
|
|
120
|
+
declare function _resetShipeasyForTests(): void;
|
|
121
|
+
/**
|
|
122
|
+
* Universal flags facade. Methods return safe defaults when the singleton
|
|
123
|
+
* hasn't been configured yet (false / undefined / `notIn` experiment), so
|
|
124
|
+
* importing this in a module that loads before app boot is harmless.
|
|
125
|
+
*/
|
|
126
|
+
declare const flags: {
|
|
127
|
+
configure(opts: FlagsClientBrowserOptions): void;
|
|
128
|
+
identify(user: User): Promise<void>;
|
|
129
|
+
/** Read a feature gate. Returns false until identify() resolves. */
|
|
130
|
+
get(name: string): boolean;
|
|
131
|
+
getConfig<T = unknown>(name: string, decode?: (raw: unknown) => T): T | undefined;
|
|
132
|
+
getExperiment<P extends Record<string, unknown>>(name: string, defaultParams: P, decode?: (raw: unknown) => P, variants?: Record<string, Partial<P>>): ExperimentResult<P>;
|
|
133
|
+
track(eventName: string, props?: Record<string, unknown>): void;
|
|
134
|
+
flush(): Promise<void>;
|
|
135
|
+
/** Subscribe for change notifications (identify/override). Used by framework adapters. */
|
|
136
|
+
subscribe(listener: () => void): () => void;
|
|
137
|
+
/** True once identify() has completed and flags are available. */
|
|
138
|
+
readonly ready: boolean;
|
|
139
|
+
};
|
|
140
|
+
declare const LABEL_MARKER_START = "\uFFF9";
|
|
141
|
+
declare const LABEL_MARKER_SEP = "\uFFFA";
|
|
142
|
+
declare const LABEL_MARKER_END = "\uFFFB";
|
|
143
|
+
declare const LABEL_MARKER_RE: RegExp;
|
|
144
|
+
declare function encodeLabelMarker(key: string, value: string): string;
|
|
145
|
+
interface LabelAttrs {
|
|
146
|
+
"data-label": string;
|
|
147
|
+
"data-variables"?: string;
|
|
148
|
+
"data-label-desc"?: string;
|
|
149
|
+
}
|
|
150
|
+
declare function labelAttrs(key: string, variables?: Record<string, string | number>, desc?: string): LabelAttrs;
|
|
151
|
+
/**
|
|
152
|
+
* Universal i18n facade. Backed by the `window.i18n` global the loader
|
|
153
|
+
* script installs. Returns the key itself when the loader hasn't run
|
|
154
|
+
* (SSR, missing script tag, before profile fetch completes), so call
|
|
155
|
+
* sites never need to null-check.
|
|
156
|
+
*/
|
|
157
|
+
declare const i18n: {
|
|
158
|
+
t(key: string, variables?: Record<string, string | number>): string;
|
|
159
|
+
/**
|
|
160
|
+
* Translate a key and return a framework element (e.g. React <span>)
|
|
161
|
+
* carrying `data-label` / `data-variables` attributes so the ShipEasy
|
|
162
|
+
* devtools "Edit labels" overlay can highlight and edit it in place.
|
|
163
|
+
*
|
|
164
|
+
* Requires a one-time setup call: `i18n.configure({ createElement })`.
|
|
165
|
+
* The returned value is whatever `createElement` returns — pass React's
|
|
166
|
+
* `createElement`, Vue's `h`, Solid's `createSignal`-based factory, etc.
|
|
167
|
+
*
|
|
168
|
+
* Falls back to a plain translated string if `createElement` was not
|
|
169
|
+
* configured (e.g. server-side or in non-JSX contexts).
|
|
170
|
+
*/
|
|
171
|
+
tEl(key: string, variables?: Record<string, string | number>, desc?: string): any;
|
|
172
|
+
/** Wire up the element creator once at app startup (call before any tEl use). */
|
|
173
|
+
configure(opts: {
|
|
174
|
+
createElement: (tag: string, props: object, children: string) => any;
|
|
175
|
+
}): void;
|
|
176
|
+
readonly locale: string | null;
|
|
177
|
+
readonly ready: boolean;
|
|
178
|
+
/** Resolves when the loader has installed window.i18n and fetched a profile. */
|
|
179
|
+
whenReady(): Promise<void>;
|
|
180
|
+
/** Subscribe to locale/profile updates. Returns an unsubscribe fn. */
|
|
181
|
+
onUpdate(cb: () => void): () => void;
|
|
182
|
+
};
|
|
47
183
|
|
|
48
|
-
export { type ExperimentResult, FlagsClientBrowser, type FlagsClientBrowserOptions, type User, version };
|
|
184
|
+
export { type ExperimentResult, FlagsClientBrowser, type FlagsClientBrowserEnv, type FlagsClientBrowserOptions, LABEL_MARKER_END, LABEL_MARKER_RE, LABEL_MARKER_SEP, LABEL_MARKER_START, type LabelAttrs, type ShipeasySdkBridge, type User, _resetShipeasyForTests, attachDevtools, configureShipeasy, encodeLabelMarker, flags, getShipeasyClient, i18n, isDevtoolsRequested, labelAttrs, loadDevtools, readConfigOverride, readExpOverride, readGateOverride, version };
|