@shieldlabs-ai/react 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,380 @@
1
+ "use client";
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.ts
22
+ var src_exports = {};
23
+ __export(src_exports, {
24
+ ShieldLabsError: () => import_js4.ShieldLabsError,
25
+ ShieldLabsProvider: () => ShieldLabsProvider,
26
+ useIdentify: () => useIdentify,
27
+ useShieldLabs: () => useShieldLabs
28
+ });
29
+ module.exports = __toCommonJS(src_exports);
30
+
31
+ // src/provider.ts
32
+ var import_react = require("react");
33
+ var import_js3 = require("@shieldlabs-ai/js");
34
+
35
+ // src/internal.ts
36
+ var import_js = require("@shieldlabs-ai/js");
37
+ var DEFAULT_TIMEOUT = 1e4;
38
+ var MAX_TIMEOUT = 2147483647;
39
+ function isObject(value) {
40
+ return typeof value === "object" && value !== null;
41
+ }
42
+ function isValidTimeout(value) {
43
+ return typeof value === "number" && value > 0 && value <= MAX_TIMEOUT;
44
+ }
45
+ function asShieldLabsError(error, code, message) {
46
+ return error instanceof import_js.ShieldLabsError ? error : new import_js.ShieldLabsError(code, message, error);
47
+ }
48
+ function withTimeout(promise, ms, message) {
49
+ return new Promise((resolve, reject) => {
50
+ const timer = setTimeout(() => {
51
+ reject(new import_js.ShieldLabsError("timeout", message));
52
+ }, ms);
53
+ const clear = () => {
54
+ clearTimeout(timer);
55
+ };
56
+ promise.then(clear, clear);
57
+ promise.then(resolve, reject);
58
+ });
59
+ }
60
+ function ignore() {
61
+ }
62
+
63
+ // src/loader.ts
64
+ var import_js2 = require("@shieldlabs-ai/js");
65
+ var LOAD_FAILED = "Could not load the ShieldLabs agent.";
66
+ var NOT_LOADED = "The ShieldLabs agent is not loaded: ShieldLabsProvider has autoLoad={false} and load() from useShieldLabs() has not been called.";
67
+ function keyOf(options) {
68
+ return [options.publicKey, options.environment, options.scriptUrl, options.timeout].map((value) => typeof value + ":" + String(value)).join("|");
69
+ }
70
+ function userIdOf(options) {
71
+ return isObject(options) && typeof options.userId === "string" ? options.userId : null;
72
+ }
73
+ function startLoad(options) {
74
+ return new Promise((resolve) => {
75
+ resolve((0, import_js2.load)(options));
76
+ }).catch((error) => {
77
+ throw asShieldLabsError(error, "load_failed", LOAD_FAILED);
78
+ });
79
+ }
80
+ function canRetry(slot) {
81
+ var _a;
82
+ const code = (_a = slot.error) == null ? void 0 : _a.code;
83
+ return code === "load_failed" || code === "timeout";
84
+ }
85
+ function warnSetupProblem(error) {
86
+ if (error.code === "invalid_options" || error.code === "unsupported_environment") {
87
+ console.warn("[ShieldLabs] ShieldLabsProvider could not load the agent: " + error.message);
88
+ }
89
+ }
90
+ function callTimeout(callOptions, loadOptions) {
91
+ const perCall = callOptions == null ? void 0 : callOptions.timeout;
92
+ if (isValidTimeout(perCall)) return perCall;
93
+ if (isValidTimeout(loadOptions.timeout)) return loadOptions.timeout;
94
+ return DEFAULT_TIMEOUT;
95
+ }
96
+ function withTimeLeft(callOptions, total, startedAt) {
97
+ const raw = callOptions;
98
+ if (raw != null && !isObject(raw)) return callOptions;
99
+ if ((callOptions == null ? void 0 : callOptions.timeout) !== void 0 && !isValidTimeout(callOptions.timeout)) return callOptions;
100
+ const left = total - (Date.now() - startedAt);
101
+ return { ...callOptions, timeout: Math.min(total, Math.max(1, left)) };
102
+ }
103
+ function createAgentLoader(initialOptions, autoLoad) {
104
+ let options = initialOptions;
105
+ let slot = null;
106
+ let listener = null;
107
+ let latest = null;
108
+ let allowed = autoLoad;
109
+ let allowedPromise = null;
110
+ let resolveAllowed = null;
111
+ const running = /* @__PURE__ */ new Map();
112
+ const currentSlot = () => {
113
+ const key = keyOf(options);
114
+ const previous = slot;
115
+ if ((previous == null ? void 0 : previous.key) === key && !canRetry(previous)) return previous;
116
+ const next = { key, promise: startLoad(options), agent: null, error: null };
117
+ slot = next;
118
+ latest = null;
119
+ const publish = (state) => {
120
+ if (slot !== next) return;
121
+ latest = state;
122
+ if (listener) listener(state);
123
+ };
124
+ if ((previous == null ? void 0 : previous.key) === key) publish({ key, status: "loading", error: null });
125
+ next.promise.then(
126
+ (agent) => {
127
+ next.agent = agent;
128
+ publish({ key, status: "ready", error: null });
129
+ },
130
+ (error) => {
131
+ next.error = asShieldLabsError(error, "load_failed", LOAD_FAILED);
132
+ if (slot === next) warnSetupProblem(next.error);
133
+ publish({ key, status: "error", error: next.error });
134
+ }
135
+ );
136
+ return next;
137
+ };
138
+ const allow = () => {
139
+ if (allowed) return;
140
+ allowed = true;
141
+ if (resolveAllowed) resolveAllowed();
142
+ allowedPromise = null;
143
+ resolveAllowed = null;
144
+ };
145
+ const whenAllowed = () => allowedPromise != null ? allowedPromise : allowedPromise = new Promise((resolve) => {
146
+ resolveAllowed = resolve;
147
+ });
148
+ const withAgent = (callOptions, call) => {
149
+ const current = currentSlot();
150
+ if (current.agent) return Promise.resolve(current.agent).then((agent) => call(agent, callOptions));
151
+ const ms = callTimeout(callOptions, options);
152
+ const startedAt = Date.now();
153
+ return withTimeout(current.promise, ms, "The ShieldLabs agent did not load within " + String(ms) + " ms.").then(
154
+ (agent) => call(agent, withTimeLeft(callOptions, ms, startedAt))
155
+ );
156
+ };
157
+ const track = (callOptions, promise) => {
158
+ var _a;
159
+ const userId = userIdOf(callOptions);
160
+ running.set(userId, ((_a = running.get(userId)) != null ? _a : 0) + 1);
161
+ return promise.finally(() => {
162
+ var _a2;
163
+ const left = ((_a2 = running.get(userId)) != null ? _a2 : 1) - 1;
164
+ if (left > 0) running.set(userId, left);
165
+ else running.delete(userId);
166
+ });
167
+ };
168
+ return {
169
+ update(nextOptions, nextAutoLoad) {
170
+ options = nextOptions;
171
+ if (nextAutoLoad) allow();
172
+ if (allowed) currentSlot();
173
+ },
174
+ subscribe(nextListener) {
175
+ listener = nextListener;
176
+ if (latest) nextListener(latest);
177
+ return () => {
178
+ if (listener === nextListener) listener = null;
179
+ };
180
+ },
181
+ isRunning(userId) {
182
+ return running.has(userId);
183
+ },
184
+ defaultTimeout: () => callTimeout(void 0, options),
185
+ load: () => {
186
+ allow();
187
+ currentSlot();
188
+ },
189
+ getAgent: () => allowed ? currentSlot().promise : whenAllowed().then(() => currentSlot().promise),
190
+ identify: (callOptions) => allowed ? track(callOptions, withAgent(callOptions, (agent, agentOptions) => agent.identify(agentOptions))) : Promise.reject(new import_js2.ShieldLabsError("not_initialized", NOT_LOADED)),
191
+ check: (callOptions) => allowed ? track(callOptions, withAgent(callOptions, (agent, agentOptions) => agent.check(agentOptions))) : Promise.resolve(null)
192
+ };
193
+ }
194
+
195
+ // src/provider.ts
196
+ var ShieldLabsContext = (0, import_react.createContext)(null);
197
+ ShieldLabsContext.displayName = "ShieldLabsContext";
198
+ function loadOptionsOf(publicKey, environment, scriptUrl, timeout) {
199
+ const options = { publicKey };
200
+ if (environment !== void 0) options.environment = environment;
201
+ if (scriptUrl !== void 0) options.scriptUrl = scriptUrl;
202
+ if (timeout !== void 0) options.timeout = timeout;
203
+ return options;
204
+ }
205
+ function warnCheckOnLoad(error) {
206
+ if (error instanceof import_js3.ShieldLabsError && error.code === "invalid_options") {
207
+ console.warn("[ShieldLabs] checkOnLoad: " + error.message);
208
+ }
209
+ }
210
+ function ShieldLabsProvider(props) {
211
+ const { publicKey, environment, scriptUrl, timeout, autoLoad, checkOnLoad = false, children } = props;
212
+ const loadsByItself = autoLoad !== false;
213
+ const key = keyOf(loadOptionsOf(publicKey, environment, scriptUrl, timeout));
214
+ const [loader] = (0, import_react.useState)(
215
+ () => createAgentLoader(loadOptionsOf(publicKey, environment, scriptUrl, timeout), loadsByItself)
216
+ );
217
+ const [loadState, setLoadState] = (0, import_react.useState)(() => ({ key, status: "loading", error: null }));
218
+ const checkedRef = (0, import_react.useRef)(false);
219
+ (0, import_react.useEffect)(() => {
220
+ const unsubscribe = loader.subscribe(setLoadState);
221
+ loader.update(loadOptionsOf(publicKey, environment, scriptUrl, timeout), loadsByItself);
222
+ return unsubscribe;
223
+ }, [loader, publicKey, environment, scriptUrl, timeout, loadsByItself]);
224
+ const current = loadState.key === key ? loadState : null;
225
+ const status = current ? current.status : "loading";
226
+ const error = current ? current.error : null;
227
+ const checkEnabled = checkOnLoad === true || isObject(checkOnLoad);
228
+ const checkUserId = isObject(checkOnLoad) ? checkOnLoad.userId : void 0;
229
+ (0, import_react.useEffect)(() => {
230
+ if (status !== "ready" || !checkEnabled || checkedRef.current) return;
231
+ checkedRef.current = true;
232
+ const checkOptions = checkUserId === void 0 ? {} : { userId: checkUserId };
233
+ if (loader.isRunning(userIdOf(checkOptions))) return;
234
+ loader.check(checkOptions).then(ignore, warnCheckOnLoad);
235
+ }, [loader, status, checkEnabled, checkUserId]);
236
+ const shieldLabs = (0, import_react.useMemo)(
237
+ () => ({
238
+ status,
239
+ error,
240
+ identify: loader.identify,
241
+ check: loader.check,
242
+ load: loader.load,
243
+ getAgent: loader.getAgent
244
+ }),
245
+ [loader, status, error]
246
+ );
247
+ const value = (0, import_react.useMemo)(
248
+ () => ({ shieldLabs, defaultTimeout: loader.defaultTimeout }),
249
+ [loader, shieldLabs]
250
+ );
251
+ return (0, import_react.createElement)(ShieldLabsContext.Provider, { value }, children);
252
+ }
253
+ function useShieldLabsContext(hook) {
254
+ const value = (0, import_react.useContext)(ShieldLabsContext);
255
+ if (value === null) {
256
+ throw new Error(
257
+ "[ShieldLabs] " + hook + '() must be called inside <ShieldLabsProvider>. Render <ShieldLabsProvider publicKey="..."> above the component that calls it.'
258
+ );
259
+ }
260
+ return value;
261
+ }
262
+ function useShieldLabs() {
263
+ return useShieldLabsContext("useShieldLabs").shieldLabs;
264
+ }
265
+
266
+ // src/use-identify.ts
267
+ var import_react2 = require("react");
268
+ function agentOptionsOf(callOptions, userId) {
269
+ const raw = callOptions;
270
+ if (raw != null && !isObject(raw)) return callOptions;
271
+ const { userId: ownUserId, ...rest } = callOptions != null ? callOptions : {};
272
+ const effectiveUserId = callOptions != null && "userId" in callOptions ? ownUserId : userId;
273
+ return effectiveUserId == null ? rest : { ...rest, userId: effectiveUserId };
274
+ }
275
+ function timeoutOf(options, defaultTimeout) {
276
+ const timeout = options == null ? void 0 : options.timeout;
277
+ return timeout === void 0 ? defaultTimeout : timeout;
278
+ }
279
+ function isSameCall(running, options, timeout) {
280
+ const raw = options;
281
+ return isObject(raw) && running.userId === (options == null ? void 0 : options.userId) && running.timeout === timeout;
282
+ }
283
+ var IDLE = { result: null, isLoading: false, error: null };
284
+ var LOADING = { result: null, isLoading: true, error: null };
285
+ function useIdentify(options = {}) {
286
+ const { shieldLabs, defaultTimeout } = useShieldLabsContext("useIdentify");
287
+ const identifyWithAgent = shieldLabs.identify;
288
+ const { userId, runOnMount = false } = options;
289
+ const [state, setState] = (0, import_react2.useState)(runOnMount ? LOADING : IDLE);
290
+ const connectedRef = (0, import_react2.useRef)(false);
291
+ const queuedRef = (0, import_react2.useRef)(null);
292
+ const latestRef = (0, import_react2.useRef)({});
293
+ const runningRef = (0, import_react2.useRef)([]);
294
+ const mountRunRef = (0, import_react2.useRef)(runOnMount);
295
+ const apply = (0, import_react2.useCallback)((next) => {
296
+ if (connectedRef.current) setState(next);
297
+ else queuedRef.current = next;
298
+ }, []);
299
+ (0, import_react2.useEffect)(() => {
300
+ connectedRef.current = true;
301
+ const queued = queuedRef.current;
302
+ queuedRef.current = null;
303
+ if (queued) apply(queued);
304
+ return () => {
305
+ connectedRef.current = false;
306
+ };
307
+ }, [apply]);
308
+ const identify = (0, import_react2.useCallback)(
309
+ (callOptions) => {
310
+ const agentOptions = agentOptionsOf(callOptions, userId);
311
+ const timeout = timeoutOf(agentOptions, defaultTimeout());
312
+ const shared = runningRef.current.find((running) => isSameCall(running, agentOptions, timeout));
313
+ if (shared) {
314
+ if (latestRef.current !== shared.token) {
315
+ latestRef.current = shared.token;
316
+ apply(LOADING);
317
+ }
318
+ return shared.promise;
319
+ }
320
+ const token = {};
321
+ latestRef.current = token;
322
+ const publish = (next) => {
323
+ if (latestRef.current === token) apply(next);
324
+ };
325
+ let entry = null;
326
+ const settle = (next) => {
327
+ runningRef.current = runningRef.current.filter((running) => running !== entry);
328
+ publish(next);
329
+ };
330
+ publish(LOADING);
331
+ const promise = new Promise((resolve) => {
332
+ resolve(identifyWithAgent(agentOptions));
333
+ }).then(
334
+ (result) => {
335
+ settle({ result, isLoading: false, error: null });
336
+ return result;
337
+ },
338
+ (error) => {
339
+ settle({
340
+ result: null,
341
+ isLoading: false,
342
+ error: asShieldLabsError(error, "not_initialized", "The identification did not complete.")
343
+ });
344
+ return null;
345
+ }
346
+ );
347
+ const raw = agentOptions;
348
+ if (isObject(raw)) {
349
+ entry = { userId: agentOptions == null ? void 0 : agentOptions.userId, timeout, promise, token };
350
+ runningRef.current = [...runningRef.current, entry];
351
+ }
352
+ return promise;
353
+ },
354
+ [identifyWithAgent, defaultTimeout, userId, apply]
355
+ );
356
+ const reset = (0, import_react2.useCallback)(() => {
357
+ latestRef.current = {};
358
+ runningRef.current = [];
359
+ apply(IDLE);
360
+ }, [apply]);
361
+ (0, import_react2.useEffect)(() => {
362
+ if (!mountRunRef.current) return;
363
+ mountRunRef.current = false;
364
+ void identify();
365
+ }, [identify]);
366
+ return (0, import_react2.useMemo)(
367
+ () => ({ identify, result: state.result, isLoading: state.isLoading, error: state.error, reset }),
368
+ [identify, state, reset]
369
+ );
370
+ }
371
+
372
+ // src/index.ts
373
+ var import_js4 = require("@shieldlabs-ai/js");
374
+ // Annotate the CommonJS export names for ESM import in node:
375
+ 0 && (module.exports = {
376
+ ShieldLabsError,
377
+ ShieldLabsProvider,
378
+ useIdentify,
379
+ useShieldLabs
380
+ });
@@ -0,0 +1,118 @@
1
+ import { ReactNode, ReactElement } from 'react';
2
+ import { LoadOptions, ShieldLabsError, IdentifyOptions, IdentifyResult, ShieldLabsAgent } from '@shieldlabs-ai/js';
3
+ export { IdentifyOptions, IdentifyResult, InteractionIdentifier, LoadOptions, ShieldLabsAgent, ShieldLabsError, ShieldLabsErrorCode } from '@shieldlabs-ai/js';
4
+
5
+ /** Where the agent is: `'loading'`, `'ready'`, or `'error'` when it could not be loaded. */
6
+ type ShieldLabsStatus = 'loading' | 'ready' | 'error';
7
+
8
+ /**
9
+ * Props of {@link ShieldLabsProvider}: the `load()` options of `@shieldlabs-ai/js` plus `autoLoad` and
10
+ * `checkOnLoad`.
11
+ */
12
+ interface ShieldLabsProviderProps extends LoadOptions {
13
+ /**
14
+ * Loads the agent after the first render in the browser. With `false`, nothing loads until `load()`
15
+ * from `useShieldLabs()` is called or `autoLoad` becomes `true`, for example once the user has given
16
+ * consent. Default `true`.
17
+ */
18
+ autoLoad?: boolean;
19
+ /**
20
+ * Runs `check()` once per provider mount when the agent is ready, for passive monitoring of the
21
+ * visit, unless an `identify()` or `check()` for the same User HID is running at that moment. `true`
22
+ * checks anonymously, `{ userId }` passes a User HID. Default `false`.
23
+ */
24
+ checkOnLoad?: boolean | {
25
+ userId?: string;
26
+ };
27
+ children?: ReactNode;
28
+ }
29
+ /** What {@link useShieldLabs} returns. */
30
+ interface UseShieldLabsResult {
31
+ /** `'loading'` until the agent has loaded, then `'ready'`, or `'error'` when loading failed. */
32
+ status: ShieldLabsStatus;
33
+ /** Why loading failed while `status` is `'error'`, otherwise `null`. */
34
+ error: ShieldLabsError | null;
35
+ /**
36
+ * Runs a fresh identification: a new request ID on every call. Waits for the agent while it is
37
+ * loading; the call's timeout covers that wait and the agent's answer. Rejects with a
38
+ * `ShieldLabsError` when there is no identification, with `not_initialized` at once while
39
+ * `autoLoad={false}` and `load()` has not been called. For protected actions, `useIdentify()` adds
40
+ * state and never rejects.
41
+ */
42
+ identify: (options?: IdentifyOptions) => Promise<IdentifyResult>;
43
+ /**
44
+ * Background check, limited by the agent to one per visit every five minutes. Resolves `null` when
45
+ * the agent skipped it, and at once while `autoLoad={false}` and `load()` has not been called. Waits
46
+ * for the agent while it is loading, within the call's timeout.
47
+ */
48
+ check: (options?: IdentifyOptions) => Promise<IdentifyResult | null>;
49
+ /**
50
+ * Starts loading the agent: needed only with `autoLoad={false}`, for example once the user has given
51
+ * consent. Also loads again after a failed load. Safe to call more than once. Call it from an event
52
+ * handler or an effect, never during render.
53
+ */
54
+ load: () => void;
55
+ /**
56
+ * The loaded agent of `@shieldlabs-ai/js`, for example for `agent.identifyOnInteraction(form)`. Waits
57
+ * while the agent loads, and with `autoLoad={false}` until loading starts, with no timeout of its
58
+ * own. Rejects with the load error when the agent cannot load; the next call loads again when that
59
+ * can help.
60
+ */
61
+ getAgent: () => Promise<ShieldLabsAgent>;
62
+ }
63
+ /**
64
+ * Loads the ShieldLabs agent once, after the first render in the browser (or once `load()` is called
65
+ * with `autoLoad={false}`), and gives the components below it `useShieldLabs()` and `useIdentify()`.
66
+ * Renders only its children. Nothing runs during server-side rendering.
67
+ */
68
+ declare function ShieldLabsProvider(props: ShieldLabsProviderProps): ReactElement;
69
+ /**
70
+ * The status of the ShieldLabs agent in the closest {@link ShieldLabsProvider}, its `identify()` and
71
+ * `check()`, `load()` for deferred loading and `getAgent()`.
72
+ * Throws when there is no provider above the component.
73
+ */
74
+ declare function useShieldLabs(): UseShieldLabsResult;
75
+
76
+ /** Options of {@link useIdentify}. */
77
+ interface UseIdentifyOptions {
78
+ /**
79
+ * User HID for every identification of this hook: a hashed or pseudonymous account ID computed on
80
+ * your server. Omit it for anonymous visitors. Options of `identify()` with a `userId` key override
81
+ * it, also when the value is `undefined` or `null`, which both identify anonymously.
82
+ */
83
+ userId?: string;
84
+ /**
85
+ * Runs `identify()` once when the component mounts, as soon as the agent is ready. With
86
+ * `autoLoad={false}`, a mount before `load()` ends at once with a `not_initialized` error and does
87
+ * not run again after `load()`. Every run is a billable identification, so use it sparingly.
88
+ * Default `false`.
89
+ */
90
+ runOnMount?: boolean;
91
+ }
92
+ /** What {@link useIdentify} returns. */
93
+ interface UseIdentifyResult {
94
+ /**
95
+ * Runs a fresh identification (a new request ID on every call) and resolves its result, or `null`
96
+ * when there is no identification: the reason is then in `error`. Never rejects. While a call of
97
+ * this hook with the same User HID and `timeout` is running (a double submit), returns that call
98
+ * instead of starting another identification. The User HID of a call is its own `userId` when the
99
+ * options have that key (`undefined` and `null` both mean anonymous), else the hook's. A call
100
+ * without `timeout` counts as one with the provider `timeout` (10000 ms by default).
101
+ */
102
+ identify: (options?: IdentifyOptions) => Promise<IdentifyResult | null>;
103
+ /** The result of the latest identification, `null` before it resolves, when it failed or after `reset()`. */
104
+ result: IdentifyResult | null;
105
+ /** `true` while the latest identification is running. */
106
+ isLoading: boolean;
107
+ /** Why the latest identification failed, otherwise `null`. */
108
+ error: ShieldLabsError | null;
109
+ /** Clears `result` and `error`. A running identification no longer updates the state. */
110
+ reset: () => void;
111
+ }
112
+ /**
113
+ * Identification with loading and error state, for protected actions such as signup, login or
114
+ * checkout. Must be called inside a {@link ShieldLabsProvider}.
115
+ */
116
+ declare function useIdentify(options?: UseIdentifyOptions): UseIdentifyResult;
117
+
118
+ export { ShieldLabsProvider, type ShieldLabsProviderProps, type ShieldLabsStatus, type UseIdentifyOptions, type UseIdentifyResult, type UseShieldLabsResult, useIdentify, useShieldLabs };
@@ -0,0 +1,118 @@
1
+ import { ReactNode, ReactElement } from 'react';
2
+ import { LoadOptions, ShieldLabsError, IdentifyOptions, IdentifyResult, ShieldLabsAgent } from '@shieldlabs-ai/js';
3
+ export { IdentifyOptions, IdentifyResult, InteractionIdentifier, LoadOptions, ShieldLabsAgent, ShieldLabsError, ShieldLabsErrorCode } from '@shieldlabs-ai/js';
4
+
5
+ /** Where the agent is: `'loading'`, `'ready'`, or `'error'` when it could not be loaded. */
6
+ type ShieldLabsStatus = 'loading' | 'ready' | 'error';
7
+
8
+ /**
9
+ * Props of {@link ShieldLabsProvider}: the `load()` options of `@shieldlabs-ai/js` plus `autoLoad` and
10
+ * `checkOnLoad`.
11
+ */
12
+ interface ShieldLabsProviderProps extends LoadOptions {
13
+ /**
14
+ * Loads the agent after the first render in the browser. With `false`, nothing loads until `load()`
15
+ * from `useShieldLabs()` is called or `autoLoad` becomes `true`, for example once the user has given
16
+ * consent. Default `true`.
17
+ */
18
+ autoLoad?: boolean;
19
+ /**
20
+ * Runs `check()` once per provider mount when the agent is ready, for passive monitoring of the
21
+ * visit, unless an `identify()` or `check()` for the same User HID is running at that moment. `true`
22
+ * checks anonymously, `{ userId }` passes a User HID. Default `false`.
23
+ */
24
+ checkOnLoad?: boolean | {
25
+ userId?: string;
26
+ };
27
+ children?: ReactNode;
28
+ }
29
+ /** What {@link useShieldLabs} returns. */
30
+ interface UseShieldLabsResult {
31
+ /** `'loading'` until the agent has loaded, then `'ready'`, or `'error'` when loading failed. */
32
+ status: ShieldLabsStatus;
33
+ /** Why loading failed while `status` is `'error'`, otherwise `null`. */
34
+ error: ShieldLabsError | null;
35
+ /**
36
+ * Runs a fresh identification: a new request ID on every call. Waits for the agent while it is
37
+ * loading; the call's timeout covers that wait and the agent's answer. Rejects with a
38
+ * `ShieldLabsError` when there is no identification, with `not_initialized` at once while
39
+ * `autoLoad={false}` and `load()` has not been called. For protected actions, `useIdentify()` adds
40
+ * state and never rejects.
41
+ */
42
+ identify: (options?: IdentifyOptions) => Promise<IdentifyResult>;
43
+ /**
44
+ * Background check, limited by the agent to one per visit every five minutes. Resolves `null` when
45
+ * the agent skipped it, and at once while `autoLoad={false}` and `load()` has not been called. Waits
46
+ * for the agent while it is loading, within the call's timeout.
47
+ */
48
+ check: (options?: IdentifyOptions) => Promise<IdentifyResult | null>;
49
+ /**
50
+ * Starts loading the agent: needed only with `autoLoad={false}`, for example once the user has given
51
+ * consent. Also loads again after a failed load. Safe to call more than once. Call it from an event
52
+ * handler or an effect, never during render.
53
+ */
54
+ load: () => void;
55
+ /**
56
+ * The loaded agent of `@shieldlabs-ai/js`, for example for `agent.identifyOnInteraction(form)`. Waits
57
+ * while the agent loads, and with `autoLoad={false}` until loading starts, with no timeout of its
58
+ * own. Rejects with the load error when the agent cannot load; the next call loads again when that
59
+ * can help.
60
+ */
61
+ getAgent: () => Promise<ShieldLabsAgent>;
62
+ }
63
+ /**
64
+ * Loads the ShieldLabs agent once, after the first render in the browser (or once `load()` is called
65
+ * with `autoLoad={false}`), and gives the components below it `useShieldLabs()` and `useIdentify()`.
66
+ * Renders only its children. Nothing runs during server-side rendering.
67
+ */
68
+ declare function ShieldLabsProvider(props: ShieldLabsProviderProps): ReactElement;
69
+ /**
70
+ * The status of the ShieldLabs agent in the closest {@link ShieldLabsProvider}, its `identify()` and
71
+ * `check()`, `load()` for deferred loading and `getAgent()`.
72
+ * Throws when there is no provider above the component.
73
+ */
74
+ declare function useShieldLabs(): UseShieldLabsResult;
75
+
76
+ /** Options of {@link useIdentify}. */
77
+ interface UseIdentifyOptions {
78
+ /**
79
+ * User HID for every identification of this hook: a hashed or pseudonymous account ID computed on
80
+ * your server. Omit it for anonymous visitors. Options of `identify()` with a `userId` key override
81
+ * it, also when the value is `undefined` or `null`, which both identify anonymously.
82
+ */
83
+ userId?: string;
84
+ /**
85
+ * Runs `identify()` once when the component mounts, as soon as the agent is ready. With
86
+ * `autoLoad={false}`, a mount before `load()` ends at once with a `not_initialized` error and does
87
+ * not run again after `load()`. Every run is a billable identification, so use it sparingly.
88
+ * Default `false`.
89
+ */
90
+ runOnMount?: boolean;
91
+ }
92
+ /** What {@link useIdentify} returns. */
93
+ interface UseIdentifyResult {
94
+ /**
95
+ * Runs a fresh identification (a new request ID on every call) and resolves its result, or `null`
96
+ * when there is no identification: the reason is then in `error`. Never rejects. While a call of
97
+ * this hook with the same User HID and `timeout` is running (a double submit), returns that call
98
+ * instead of starting another identification. The User HID of a call is its own `userId` when the
99
+ * options have that key (`undefined` and `null` both mean anonymous), else the hook's. A call
100
+ * without `timeout` counts as one with the provider `timeout` (10000 ms by default).
101
+ */
102
+ identify: (options?: IdentifyOptions) => Promise<IdentifyResult | null>;
103
+ /** The result of the latest identification, `null` before it resolves, when it failed or after `reset()`. */
104
+ result: IdentifyResult | null;
105
+ /** `true` while the latest identification is running. */
106
+ isLoading: boolean;
107
+ /** Why the latest identification failed, otherwise `null`. */
108
+ error: ShieldLabsError | null;
109
+ /** Clears `result` and `error`. A running identification no longer updates the state. */
110
+ reset: () => void;
111
+ }
112
+ /**
113
+ * Identification with loading and error state, for protected actions such as signup, login or
114
+ * checkout. Must be called inside a {@link ShieldLabsProvider}.
115
+ */
116
+ declare function useIdentify(options?: UseIdentifyOptions): UseIdentifyResult;
117
+
118
+ export { ShieldLabsProvider, type ShieldLabsProviderProps, type ShieldLabsStatus, type UseIdentifyOptions, type UseIdentifyResult, type UseShieldLabsResult, useIdentify, useShieldLabs };