@trustsig/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/README.md +54 -0
- package/package.json +10 -0
- package/src/TrustSigProvider.tsx +80 -0
- package/src/index.ts +2 -0
- package/src/useTrustSig.ts +5 -0
- package/tests/react.test.tsx +45 -0
- package/tsup.config.ts +2 -0
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# @trustsig/react
|
|
2
|
+
|
|
3
|
+
React Context Provider and hooks for TrustSig bot protection.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @trustsig/react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Wrap your application or specific routes with the provider.
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { TrustSigProvider } from '@trustsig/react';
|
|
17
|
+
|
|
18
|
+
export default function RootLayout({ children }) {
|
|
19
|
+
return (
|
|
20
|
+
<TrustSigProvider siteKey="YOUR_PUBLIC_KEY" interceptRequests={true}>
|
|
21
|
+
{children}
|
|
22
|
+
</TrustSigProvider>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
Use the hook inside any component nested under the provider.
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import { useTrustSig } from '@trustsig/react';
|
|
33
|
+
|
|
34
|
+
export function LoginForm() {
|
|
35
|
+
const { getResponse } = useTrustSig();
|
|
36
|
+
|
|
37
|
+
const handleSubmit = async (e) => {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
const token = await getResponse();
|
|
40
|
+
|
|
41
|
+
await fetch('/api/login', {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: { 'X-TrustSig-Response': token || '' },
|
|
44
|
+
body: JSON.stringify({ email: "user@example.com" })
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<form onSubmit={handleSubmit}>
|
|
50
|
+
<button type="submit">Login</button>
|
|
51
|
+
</form>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@trustsig/react",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "./dist/index.js",
|
|
5
|
+
"module": "./dist/index.mjs",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"scripts": { "build": "tsup" },
|
|
8
|
+
"dependencies": { "@trustsig/client": "*", "@trustsig/types": "*" },
|
|
9
|
+
"peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }
|
|
10
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React, { createContext, useContext, useEffect, useState, useMemo } from 'react';
|
|
2
|
+
import { TrustSigClient, ClientOptions } from '@trustsig/client';
|
|
3
|
+
|
|
4
|
+
export interface TrustSigContextValue {
|
|
5
|
+
isLoaded: boolean;
|
|
6
|
+
error: Error | null;
|
|
7
|
+
getResponse: () => Promise<string | null>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const TrustSigContext = createContext<TrustSigContextValue | null>(null);
|
|
11
|
+
|
|
12
|
+
export interface TrustSigProviderProps extends ClientOptions {
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const TrustSigProvider: React.FC<TrustSigProviderProps> = ({
|
|
17
|
+
siteKey,
|
|
18
|
+
endpoint,
|
|
19
|
+
wasmUrl,
|
|
20
|
+
interceptRequests,
|
|
21
|
+
debug,
|
|
22
|
+
nonce,
|
|
23
|
+
children,
|
|
24
|
+
}) => {
|
|
25
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
26
|
+
const [error, setError] = useState<Error | null>(null);
|
|
27
|
+
|
|
28
|
+
const client = useMemo(
|
|
29
|
+
() =>
|
|
30
|
+
new TrustSigClient({
|
|
31
|
+
siteKey,
|
|
32
|
+
endpoint,
|
|
33
|
+
wasmUrl,
|
|
34
|
+
interceptRequests,
|
|
35
|
+
debug,
|
|
36
|
+
nonce,
|
|
37
|
+
}),
|
|
38
|
+
[siteKey, endpoint, wasmUrl, interceptRequests, debug, nonce]
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
let mounted = true;
|
|
43
|
+
|
|
44
|
+
client
|
|
45
|
+
.load()
|
|
46
|
+
.then(() => {
|
|
47
|
+
if (mounted) {
|
|
48
|
+
setIsLoaded(true);
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
.catch((err) => {
|
|
52
|
+
if (mounted) {
|
|
53
|
+
setError(err);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return () => {
|
|
58
|
+
mounted = false;
|
|
59
|
+
};
|
|
60
|
+
}, [client]);
|
|
61
|
+
|
|
62
|
+
const value = useMemo(
|
|
63
|
+
() => ({
|
|
64
|
+
isLoaded,
|
|
65
|
+
error,
|
|
66
|
+
getResponse: () => client.getResponse(),
|
|
67
|
+
}),
|
|
68
|
+
[isLoaded, error, client]
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
return React.createElement(TrustSigContext.Provider, { value }, children);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const useTrustSigContext = () => {
|
|
75
|
+
const context = useContext(TrustSigContext);
|
|
76
|
+
if (!context) {
|
|
77
|
+
throw new Error("USE_TRUSTSIG_CONTEXT_ERROR");
|
|
78
|
+
}
|
|
79
|
+
return context;
|
|
80
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { TrustSigProvider, useTrustSig } from '../src/index';
|
|
5
|
+
|
|
6
|
+
const TestComponent = () => {
|
|
7
|
+
const { isLoaded, getResponse } = useTrustSig();
|
|
8
|
+
return React.createElement(
|
|
9
|
+
'div',
|
|
10
|
+
null,
|
|
11
|
+
isLoaded ? 'Loaded' : 'Loading',
|
|
12
|
+
React.createElement('button', { onClick: getResponse }, 'Get')
|
|
13
|
+
);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
describe('TrustSig React Provider', () => {
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
document.head.innerHTML = '';
|
|
19
|
+
delete (window as any).TrustSig;
|
|
20
|
+
|
|
21
|
+
// Prevent happy-dom from actually trying to download the remote script
|
|
22
|
+
vi.spyOn(document.head, 'appendChild').mockImplementation((node) => {
|
|
23
|
+
if (node instanceof HTMLScriptElement) {
|
|
24
|
+
setTimeout(() => {
|
|
25
|
+
if (node.onload) node.onload(new Event('load'));
|
|
26
|
+
}, 10);
|
|
27
|
+
}
|
|
28
|
+
return node;
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('renders children and provides context', async () => {
|
|
33
|
+
render(
|
|
34
|
+
React.createElement(
|
|
35
|
+
TrustSigProvider,
|
|
36
|
+
{ siteKey: 'TEST' },
|
|
37
|
+
React.createElement(TestComponent)
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
expect(screen.getByText('Loading')).toBeDefined();
|
|
41
|
+
|
|
42
|
+
const appendCall = (document.head.appendChild as any).mock.calls[0][0];
|
|
43
|
+
expect(appendCall.getAttribute('data-site-key')).toBe('TEST');
|
|
44
|
+
});
|
|
45
|
+
});
|
package/tsup.config.ts
ADDED