@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/CHANGELOG.md +55 -0
- package/LICENSE +21 -0
- package/README.md +514 -0
- package/dist/index.cjs +380 -0
- package/dist/index.d.cts +118 -0
- package/dist/index.d.ts +118 -0
- package/dist/index.js +364 -0
- package/package.json +86 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/provider.ts
|
|
4
|
+
import {
|
|
5
|
+
createContext,
|
|
6
|
+
createElement,
|
|
7
|
+
useContext,
|
|
8
|
+
useEffect,
|
|
9
|
+
useMemo,
|
|
10
|
+
useRef,
|
|
11
|
+
useState
|
|
12
|
+
} from "react";
|
|
13
|
+
import {
|
|
14
|
+
ShieldLabsError as ShieldLabsError3
|
|
15
|
+
} from "@shieldlabs-ai/js";
|
|
16
|
+
|
|
17
|
+
// src/internal.ts
|
|
18
|
+
import { ShieldLabsError } from "@shieldlabs-ai/js";
|
|
19
|
+
var DEFAULT_TIMEOUT = 1e4;
|
|
20
|
+
var MAX_TIMEOUT = 2147483647;
|
|
21
|
+
function isObject(value) {
|
|
22
|
+
return typeof value === "object" && value !== null;
|
|
23
|
+
}
|
|
24
|
+
function isValidTimeout(value) {
|
|
25
|
+
return typeof value === "number" && value > 0 && value <= MAX_TIMEOUT;
|
|
26
|
+
}
|
|
27
|
+
function asShieldLabsError(error, code, message) {
|
|
28
|
+
return error instanceof ShieldLabsError ? error : new ShieldLabsError(code, message, error);
|
|
29
|
+
}
|
|
30
|
+
function withTimeout(promise, ms, message) {
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
const timer = setTimeout(() => {
|
|
33
|
+
reject(new ShieldLabsError("timeout", message));
|
|
34
|
+
}, ms);
|
|
35
|
+
const clear = () => {
|
|
36
|
+
clearTimeout(timer);
|
|
37
|
+
};
|
|
38
|
+
promise.then(clear, clear);
|
|
39
|
+
promise.then(resolve, reject);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function ignore() {
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/loader.ts
|
|
46
|
+
import {
|
|
47
|
+
load,
|
|
48
|
+
ShieldLabsError as ShieldLabsError2
|
|
49
|
+
} from "@shieldlabs-ai/js";
|
|
50
|
+
var LOAD_FAILED = "Could not load the ShieldLabs agent.";
|
|
51
|
+
var NOT_LOADED = "The ShieldLabs agent is not loaded: ShieldLabsProvider has autoLoad={false} and load() from useShieldLabs() has not been called.";
|
|
52
|
+
function keyOf(options) {
|
|
53
|
+
return [options.publicKey, options.environment, options.scriptUrl, options.timeout].map((value) => typeof value + ":" + String(value)).join("|");
|
|
54
|
+
}
|
|
55
|
+
function userIdOf(options) {
|
|
56
|
+
return isObject(options) && typeof options.userId === "string" ? options.userId : null;
|
|
57
|
+
}
|
|
58
|
+
function startLoad(options) {
|
|
59
|
+
return new Promise((resolve) => {
|
|
60
|
+
resolve(load(options));
|
|
61
|
+
}).catch((error) => {
|
|
62
|
+
throw asShieldLabsError(error, "load_failed", LOAD_FAILED);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function canRetry(slot) {
|
|
66
|
+
var _a;
|
|
67
|
+
const code = (_a = slot.error) == null ? void 0 : _a.code;
|
|
68
|
+
return code === "load_failed" || code === "timeout";
|
|
69
|
+
}
|
|
70
|
+
function warnSetupProblem(error) {
|
|
71
|
+
if (error.code === "invalid_options" || error.code === "unsupported_environment") {
|
|
72
|
+
console.warn("[ShieldLabs] ShieldLabsProvider could not load the agent: " + error.message);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function callTimeout(callOptions, loadOptions) {
|
|
76
|
+
const perCall = callOptions == null ? void 0 : callOptions.timeout;
|
|
77
|
+
if (isValidTimeout(perCall)) return perCall;
|
|
78
|
+
if (isValidTimeout(loadOptions.timeout)) return loadOptions.timeout;
|
|
79
|
+
return DEFAULT_TIMEOUT;
|
|
80
|
+
}
|
|
81
|
+
function withTimeLeft(callOptions, total, startedAt) {
|
|
82
|
+
const raw = callOptions;
|
|
83
|
+
if (raw != null && !isObject(raw)) return callOptions;
|
|
84
|
+
if ((callOptions == null ? void 0 : callOptions.timeout) !== void 0 && !isValidTimeout(callOptions.timeout)) return callOptions;
|
|
85
|
+
const left = total - (Date.now() - startedAt);
|
|
86
|
+
return { ...callOptions, timeout: Math.min(total, Math.max(1, left)) };
|
|
87
|
+
}
|
|
88
|
+
function createAgentLoader(initialOptions, autoLoad) {
|
|
89
|
+
let options = initialOptions;
|
|
90
|
+
let slot = null;
|
|
91
|
+
let listener = null;
|
|
92
|
+
let latest = null;
|
|
93
|
+
let allowed = autoLoad;
|
|
94
|
+
let allowedPromise = null;
|
|
95
|
+
let resolveAllowed = null;
|
|
96
|
+
const running = /* @__PURE__ */ new Map();
|
|
97
|
+
const currentSlot = () => {
|
|
98
|
+
const key = keyOf(options);
|
|
99
|
+
const previous = slot;
|
|
100
|
+
if ((previous == null ? void 0 : previous.key) === key && !canRetry(previous)) return previous;
|
|
101
|
+
const next = { key, promise: startLoad(options), agent: null, error: null };
|
|
102
|
+
slot = next;
|
|
103
|
+
latest = null;
|
|
104
|
+
const publish = (state) => {
|
|
105
|
+
if (slot !== next) return;
|
|
106
|
+
latest = state;
|
|
107
|
+
if (listener) listener(state);
|
|
108
|
+
};
|
|
109
|
+
if ((previous == null ? void 0 : previous.key) === key) publish({ key, status: "loading", error: null });
|
|
110
|
+
next.promise.then(
|
|
111
|
+
(agent) => {
|
|
112
|
+
next.agent = agent;
|
|
113
|
+
publish({ key, status: "ready", error: null });
|
|
114
|
+
},
|
|
115
|
+
(error) => {
|
|
116
|
+
next.error = asShieldLabsError(error, "load_failed", LOAD_FAILED);
|
|
117
|
+
if (slot === next) warnSetupProblem(next.error);
|
|
118
|
+
publish({ key, status: "error", error: next.error });
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
return next;
|
|
122
|
+
};
|
|
123
|
+
const allow = () => {
|
|
124
|
+
if (allowed) return;
|
|
125
|
+
allowed = true;
|
|
126
|
+
if (resolveAllowed) resolveAllowed();
|
|
127
|
+
allowedPromise = null;
|
|
128
|
+
resolveAllowed = null;
|
|
129
|
+
};
|
|
130
|
+
const whenAllowed = () => allowedPromise != null ? allowedPromise : allowedPromise = new Promise((resolve) => {
|
|
131
|
+
resolveAllowed = resolve;
|
|
132
|
+
});
|
|
133
|
+
const withAgent = (callOptions, call) => {
|
|
134
|
+
const current = currentSlot();
|
|
135
|
+
if (current.agent) return Promise.resolve(current.agent).then((agent) => call(agent, callOptions));
|
|
136
|
+
const ms = callTimeout(callOptions, options);
|
|
137
|
+
const startedAt = Date.now();
|
|
138
|
+
return withTimeout(current.promise, ms, "The ShieldLabs agent did not load within " + String(ms) + " ms.").then(
|
|
139
|
+
(agent) => call(agent, withTimeLeft(callOptions, ms, startedAt))
|
|
140
|
+
);
|
|
141
|
+
};
|
|
142
|
+
const track = (callOptions, promise) => {
|
|
143
|
+
var _a;
|
|
144
|
+
const userId = userIdOf(callOptions);
|
|
145
|
+
running.set(userId, ((_a = running.get(userId)) != null ? _a : 0) + 1);
|
|
146
|
+
return promise.finally(() => {
|
|
147
|
+
var _a2;
|
|
148
|
+
const left = ((_a2 = running.get(userId)) != null ? _a2 : 1) - 1;
|
|
149
|
+
if (left > 0) running.set(userId, left);
|
|
150
|
+
else running.delete(userId);
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
return {
|
|
154
|
+
update(nextOptions, nextAutoLoad) {
|
|
155
|
+
options = nextOptions;
|
|
156
|
+
if (nextAutoLoad) allow();
|
|
157
|
+
if (allowed) currentSlot();
|
|
158
|
+
},
|
|
159
|
+
subscribe(nextListener) {
|
|
160
|
+
listener = nextListener;
|
|
161
|
+
if (latest) nextListener(latest);
|
|
162
|
+
return () => {
|
|
163
|
+
if (listener === nextListener) listener = null;
|
|
164
|
+
};
|
|
165
|
+
},
|
|
166
|
+
isRunning(userId) {
|
|
167
|
+
return running.has(userId);
|
|
168
|
+
},
|
|
169
|
+
defaultTimeout: () => callTimeout(void 0, options),
|
|
170
|
+
load: () => {
|
|
171
|
+
allow();
|
|
172
|
+
currentSlot();
|
|
173
|
+
},
|
|
174
|
+
getAgent: () => allowed ? currentSlot().promise : whenAllowed().then(() => currentSlot().promise),
|
|
175
|
+
identify: (callOptions) => allowed ? track(callOptions, withAgent(callOptions, (agent, agentOptions) => agent.identify(agentOptions))) : Promise.reject(new ShieldLabsError2("not_initialized", NOT_LOADED)),
|
|
176
|
+
check: (callOptions) => allowed ? track(callOptions, withAgent(callOptions, (agent, agentOptions) => agent.check(agentOptions))) : Promise.resolve(null)
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/provider.ts
|
|
181
|
+
var ShieldLabsContext = createContext(null);
|
|
182
|
+
ShieldLabsContext.displayName = "ShieldLabsContext";
|
|
183
|
+
function loadOptionsOf(publicKey, environment, scriptUrl, timeout) {
|
|
184
|
+
const options = { publicKey };
|
|
185
|
+
if (environment !== void 0) options.environment = environment;
|
|
186
|
+
if (scriptUrl !== void 0) options.scriptUrl = scriptUrl;
|
|
187
|
+
if (timeout !== void 0) options.timeout = timeout;
|
|
188
|
+
return options;
|
|
189
|
+
}
|
|
190
|
+
function warnCheckOnLoad(error) {
|
|
191
|
+
if (error instanceof ShieldLabsError3 && error.code === "invalid_options") {
|
|
192
|
+
console.warn("[ShieldLabs] checkOnLoad: " + error.message);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function ShieldLabsProvider(props) {
|
|
196
|
+
const { publicKey, environment, scriptUrl, timeout, autoLoad, checkOnLoad = false, children } = props;
|
|
197
|
+
const loadsByItself = autoLoad !== false;
|
|
198
|
+
const key = keyOf(loadOptionsOf(publicKey, environment, scriptUrl, timeout));
|
|
199
|
+
const [loader] = useState(
|
|
200
|
+
() => createAgentLoader(loadOptionsOf(publicKey, environment, scriptUrl, timeout), loadsByItself)
|
|
201
|
+
);
|
|
202
|
+
const [loadState, setLoadState] = useState(() => ({ key, status: "loading", error: null }));
|
|
203
|
+
const checkedRef = useRef(false);
|
|
204
|
+
useEffect(() => {
|
|
205
|
+
const unsubscribe = loader.subscribe(setLoadState);
|
|
206
|
+
loader.update(loadOptionsOf(publicKey, environment, scriptUrl, timeout), loadsByItself);
|
|
207
|
+
return unsubscribe;
|
|
208
|
+
}, [loader, publicKey, environment, scriptUrl, timeout, loadsByItself]);
|
|
209
|
+
const current = loadState.key === key ? loadState : null;
|
|
210
|
+
const status = current ? current.status : "loading";
|
|
211
|
+
const error = current ? current.error : null;
|
|
212
|
+
const checkEnabled = checkOnLoad === true || isObject(checkOnLoad);
|
|
213
|
+
const checkUserId = isObject(checkOnLoad) ? checkOnLoad.userId : void 0;
|
|
214
|
+
useEffect(() => {
|
|
215
|
+
if (status !== "ready" || !checkEnabled || checkedRef.current) return;
|
|
216
|
+
checkedRef.current = true;
|
|
217
|
+
const checkOptions = checkUserId === void 0 ? {} : { userId: checkUserId };
|
|
218
|
+
if (loader.isRunning(userIdOf(checkOptions))) return;
|
|
219
|
+
loader.check(checkOptions).then(ignore, warnCheckOnLoad);
|
|
220
|
+
}, [loader, status, checkEnabled, checkUserId]);
|
|
221
|
+
const shieldLabs = useMemo(
|
|
222
|
+
() => ({
|
|
223
|
+
status,
|
|
224
|
+
error,
|
|
225
|
+
identify: loader.identify,
|
|
226
|
+
check: loader.check,
|
|
227
|
+
load: loader.load,
|
|
228
|
+
getAgent: loader.getAgent
|
|
229
|
+
}),
|
|
230
|
+
[loader, status, error]
|
|
231
|
+
);
|
|
232
|
+
const value = useMemo(
|
|
233
|
+
() => ({ shieldLabs, defaultTimeout: loader.defaultTimeout }),
|
|
234
|
+
[loader, shieldLabs]
|
|
235
|
+
);
|
|
236
|
+
return createElement(ShieldLabsContext.Provider, { value }, children);
|
|
237
|
+
}
|
|
238
|
+
function useShieldLabsContext(hook) {
|
|
239
|
+
const value = useContext(ShieldLabsContext);
|
|
240
|
+
if (value === null) {
|
|
241
|
+
throw new Error(
|
|
242
|
+
"[ShieldLabs] " + hook + '() must be called inside <ShieldLabsProvider>. Render <ShieldLabsProvider publicKey="..."> above the component that calls it.'
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
return value;
|
|
246
|
+
}
|
|
247
|
+
function useShieldLabs() {
|
|
248
|
+
return useShieldLabsContext("useShieldLabs").shieldLabs;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// src/use-identify.ts
|
|
252
|
+
import { useCallback, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
253
|
+
function agentOptionsOf(callOptions, userId) {
|
|
254
|
+
const raw = callOptions;
|
|
255
|
+
if (raw != null && !isObject(raw)) return callOptions;
|
|
256
|
+
const { userId: ownUserId, ...rest } = callOptions != null ? callOptions : {};
|
|
257
|
+
const effectiveUserId = callOptions != null && "userId" in callOptions ? ownUserId : userId;
|
|
258
|
+
return effectiveUserId == null ? rest : { ...rest, userId: effectiveUserId };
|
|
259
|
+
}
|
|
260
|
+
function timeoutOf(options, defaultTimeout) {
|
|
261
|
+
const timeout = options == null ? void 0 : options.timeout;
|
|
262
|
+
return timeout === void 0 ? defaultTimeout : timeout;
|
|
263
|
+
}
|
|
264
|
+
function isSameCall(running, options, timeout) {
|
|
265
|
+
const raw = options;
|
|
266
|
+
return isObject(raw) && running.userId === (options == null ? void 0 : options.userId) && running.timeout === timeout;
|
|
267
|
+
}
|
|
268
|
+
var IDLE = { result: null, isLoading: false, error: null };
|
|
269
|
+
var LOADING = { result: null, isLoading: true, error: null };
|
|
270
|
+
function useIdentify(options = {}) {
|
|
271
|
+
const { shieldLabs, defaultTimeout } = useShieldLabsContext("useIdentify");
|
|
272
|
+
const identifyWithAgent = shieldLabs.identify;
|
|
273
|
+
const { userId, runOnMount = false } = options;
|
|
274
|
+
const [state, setState] = useState2(runOnMount ? LOADING : IDLE);
|
|
275
|
+
const connectedRef = useRef2(false);
|
|
276
|
+
const queuedRef = useRef2(null);
|
|
277
|
+
const latestRef = useRef2({});
|
|
278
|
+
const runningRef = useRef2([]);
|
|
279
|
+
const mountRunRef = useRef2(runOnMount);
|
|
280
|
+
const apply = useCallback((next) => {
|
|
281
|
+
if (connectedRef.current) setState(next);
|
|
282
|
+
else queuedRef.current = next;
|
|
283
|
+
}, []);
|
|
284
|
+
useEffect2(() => {
|
|
285
|
+
connectedRef.current = true;
|
|
286
|
+
const queued = queuedRef.current;
|
|
287
|
+
queuedRef.current = null;
|
|
288
|
+
if (queued) apply(queued);
|
|
289
|
+
return () => {
|
|
290
|
+
connectedRef.current = false;
|
|
291
|
+
};
|
|
292
|
+
}, [apply]);
|
|
293
|
+
const identify = useCallback(
|
|
294
|
+
(callOptions) => {
|
|
295
|
+
const agentOptions = agentOptionsOf(callOptions, userId);
|
|
296
|
+
const timeout = timeoutOf(agentOptions, defaultTimeout());
|
|
297
|
+
const shared = runningRef.current.find((running) => isSameCall(running, agentOptions, timeout));
|
|
298
|
+
if (shared) {
|
|
299
|
+
if (latestRef.current !== shared.token) {
|
|
300
|
+
latestRef.current = shared.token;
|
|
301
|
+
apply(LOADING);
|
|
302
|
+
}
|
|
303
|
+
return shared.promise;
|
|
304
|
+
}
|
|
305
|
+
const token = {};
|
|
306
|
+
latestRef.current = token;
|
|
307
|
+
const publish = (next) => {
|
|
308
|
+
if (latestRef.current === token) apply(next);
|
|
309
|
+
};
|
|
310
|
+
let entry = null;
|
|
311
|
+
const settle = (next) => {
|
|
312
|
+
runningRef.current = runningRef.current.filter((running) => running !== entry);
|
|
313
|
+
publish(next);
|
|
314
|
+
};
|
|
315
|
+
publish(LOADING);
|
|
316
|
+
const promise = new Promise((resolve) => {
|
|
317
|
+
resolve(identifyWithAgent(agentOptions));
|
|
318
|
+
}).then(
|
|
319
|
+
(result) => {
|
|
320
|
+
settle({ result, isLoading: false, error: null });
|
|
321
|
+
return result;
|
|
322
|
+
},
|
|
323
|
+
(error) => {
|
|
324
|
+
settle({
|
|
325
|
+
result: null,
|
|
326
|
+
isLoading: false,
|
|
327
|
+
error: asShieldLabsError(error, "not_initialized", "The identification did not complete.")
|
|
328
|
+
});
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
);
|
|
332
|
+
const raw = agentOptions;
|
|
333
|
+
if (isObject(raw)) {
|
|
334
|
+
entry = { userId: agentOptions == null ? void 0 : agentOptions.userId, timeout, promise, token };
|
|
335
|
+
runningRef.current = [...runningRef.current, entry];
|
|
336
|
+
}
|
|
337
|
+
return promise;
|
|
338
|
+
},
|
|
339
|
+
[identifyWithAgent, defaultTimeout, userId, apply]
|
|
340
|
+
);
|
|
341
|
+
const reset = useCallback(() => {
|
|
342
|
+
latestRef.current = {};
|
|
343
|
+
runningRef.current = [];
|
|
344
|
+
apply(IDLE);
|
|
345
|
+
}, [apply]);
|
|
346
|
+
useEffect2(() => {
|
|
347
|
+
if (!mountRunRef.current) return;
|
|
348
|
+
mountRunRef.current = false;
|
|
349
|
+
void identify();
|
|
350
|
+
}, [identify]);
|
|
351
|
+
return useMemo2(
|
|
352
|
+
() => ({ identify, result: state.result, isLoading: state.isLoading, error: state.error, reset }),
|
|
353
|
+
[identify, state, reset]
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// src/index.ts
|
|
358
|
+
import { ShieldLabsError as ShieldLabsError4 } from "@shieldlabs-ai/js";
|
|
359
|
+
export {
|
|
360
|
+
ShieldLabsError4 as ShieldLabsError,
|
|
361
|
+
ShieldLabsProvider,
|
|
362
|
+
useIdentify,
|
|
363
|
+
useShieldLabs
|
|
364
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@shieldlabs-ai/react",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "React bindings for ShieldLabs device intelligence: a provider that loads the agent once and hooks that return a request ID for every identification.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"shieldlabs",
|
|
7
|
+
"react",
|
|
8
|
+
"react-hooks",
|
|
9
|
+
"device-intelligence",
|
|
10
|
+
"fraud-detection",
|
|
11
|
+
"risk-score",
|
|
12
|
+
"identification"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://docs.shieldlabs.ai",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/ShieldLabs-ai/shieldlabs-react/issues",
|
|
17
|
+
"email": "contact@shieldlabs.ai"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/ShieldLabs-ai/shieldlabs-react.git"
|
|
22
|
+
},
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"author": "ShieldLabs Inc. <contact@shieldlabs.ai>",
|
|
25
|
+
"type": "module",
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"main": "./dist/index.cjs",
|
|
28
|
+
"module": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"import": {
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"default": "./dist/index.js"
|
|
35
|
+
},
|
|
36
|
+
"require": {
|
|
37
|
+
"types": "./dist/index.d.cts",
|
|
38
|
+
"default": "./dist/index.cjs"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"./package.json": "./package.json"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"CHANGELOG.md"
|
|
46
|
+
],
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"prebuild": "node scripts/check-core.mjs",
|
|
55
|
+
"build": "tsup",
|
|
56
|
+
"pretypecheck": "node scripts/check-core.mjs",
|
|
57
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.build.json",
|
|
58
|
+
"prelint": "node scripts/check-core.mjs",
|
|
59
|
+
"lint": "eslint .",
|
|
60
|
+
"pretest": "npm run build",
|
|
61
|
+
"test": "vitest run",
|
|
62
|
+
"prepublishOnly": "npm run build"
|
|
63
|
+
},
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"@shieldlabs-ai/js": "^1.0.0",
|
|
66
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@eslint/js": "~9.39.5",
|
|
70
|
+
"@testing-library/dom": "^10.4.2",
|
|
71
|
+
"@testing-library/react": "^16.3.3",
|
|
72
|
+
"@types/node": "^22.0.0",
|
|
73
|
+
"@types/react": "^19.3.0",
|
|
74
|
+
"@types/react-dom": "^19.3.0",
|
|
75
|
+
"@vitest/coverage-v8": "~3.2.7",
|
|
76
|
+
"eslint": "~9.39.5",
|
|
77
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
78
|
+
"happy-dom": "^20.14.5",
|
|
79
|
+
"react": "^19.3.0",
|
|
80
|
+
"react-dom": "^19.3.0",
|
|
81
|
+
"tsup": "^8.5.1",
|
|
82
|
+
"typescript": "~5.9.3",
|
|
83
|
+
"typescript-eslint": "^8.71.0",
|
|
84
|
+
"vitest": "~3.2.7"
|
|
85
|
+
}
|
|
86
|
+
}
|