@trustsig/client 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 +38 -0
- package/package.json +9 -0
- package/src/index.ts +69 -0
- package/tests/client.test.ts +44 -0
- package/tsup.config.ts +2 -0
package/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# @trustsig/client
|
|
2
|
+
|
|
3
|
+
Vanilla JavaScript client for TrustSig bot protection. Handles dynamic script injection and token retrieval.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @trustsig/client
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
import { TrustSigClient } from '@trustsig/client';
|
|
15
|
+
|
|
16
|
+
const client = new TrustSigClient({
|
|
17
|
+
siteKey: "YOUR_PUBLIC_KEY"
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
await client.load();
|
|
21
|
+
const token = await client.getResponse();
|
|
22
|
+
|
|
23
|
+
await fetch('/api/action', {
|
|
24
|
+
method: 'POST',
|
|
25
|
+
headers: { 'X-TrustSig-Response': token || '' }
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Options
|
|
30
|
+
|
|
31
|
+
| Option | Type | Required | Description |
|
|
32
|
+
| --- | --- | --- | --- |
|
|
33
|
+
| `siteKey` | string | Yes | Your public site key. |
|
|
34
|
+
| `endpoint` | string | No | Override edge URL. |
|
|
35
|
+
| `wasmUrl` | string | No | Override wasm binary URL. |
|
|
36
|
+
| `interceptRequests`| boolean | No | Auto-inject headers on fetch/XHR. |
|
|
37
|
+
| `debug` | boolean | No | Enable verbose console logs. |
|
|
38
|
+
| `nonce` | string | No | CSP nonce for script injection. |
|
package/package.json
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import "@trustsig/types";
|
|
2
|
+
|
|
3
|
+
export interface ClientOptions {
|
|
4
|
+
siteKey: string;
|
|
5
|
+
endpoint?: string;
|
|
6
|
+
wasmUrl?: string;
|
|
7
|
+
interceptRequests?: boolean;
|
|
8
|
+
debug?: boolean;
|
|
9
|
+
nonce?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class TrustSigClient {
|
|
13
|
+
private options: ClientOptions;
|
|
14
|
+
private scriptPromise: Promise<void> | null = null;
|
|
15
|
+
|
|
16
|
+
constructor(options: ClientOptions) {
|
|
17
|
+
if (!options.siteKey) {
|
|
18
|
+
throw new Error("SITE_KEY_REQUIRED");
|
|
19
|
+
}
|
|
20
|
+
this.options = options;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public async load(): Promise<void> {
|
|
24
|
+
if (this.scriptPromise) {
|
|
25
|
+
return this.scriptPromise;
|
|
26
|
+
}
|
|
27
|
+
if (typeof window === 'undefined') {
|
|
28
|
+
return Promise.resolve();
|
|
29
|
+
}
|
|
30
|
+
if (window.TrustSig && typeof window.TrustSig.getResponse === 'function') {
|
|
31
|
+
this.scriptPromise = Promise.resolve();
|
|
32
|
+
return this.scriptPromise;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.scriptPromise = new Promise((resolve, reject) => {
|
|
36
|
+
const script = document.createElement('script');
|
|
37
|
+
script.src = 'https://sdk.trustsig.com/trustsig.js';
|
|
38
|
+
script.setAttribute('data-site-key', this.options.siteKey);
|
|
39
|
+
|
|
40
|
+
if (this.options.endpoint) script.setAttribute('data-endpoint', this.options.endpoint);
|
|
41
|
+
if (this.options.wasmUrl) script.setAttribute('data-wasm-url', this.options.wasmUrl);
|
|
42
|
+
if (this.options.interceptRequests) script.setAttribute('data-intercept-requests', 'true');
|
|
43
|
+
if (this.options.debug) script.setAttribute('data-debug', 'true');
|
|
44
|
+
if (this.options.nonce) script.setAttribute('nonce', this.options.nonce);
|
|
45
|
+
|
|
46
|
+
script.onload = () => resolve();
|
|
47
|
+
script.onerror = () => {
|
|
48
|
+
this.scriptPromise = null;
|
|
49
|
+
reject(new Error("SCRIPT_LOAD_FAIL"));
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
document.head.appendChild(script);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return this.scriptPromise;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public async getResponse(): Promise<string | null> {
|
|
59
|
+
await this.load();
|
|
60
|
+
if (typeof window !== 'undefined' && window.TrustSig) {
|
|
61
|
+
try {
|
|
62
|
+
return await window.TrustSig.getResponse();
|
|
63
|
+
} catch (e) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
+
import { TrustSigClient } from '../src/index';
|
|
3
|
+
|
|
4
|
+
describe('TrustSig Client', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
document.head.innerHTML = '';
|
|
7
|
+
delete (window as any).TrustSig;
|
|
8
|
+
// Prevent happy-dom from actually trying to download the remote script
|
|
9
|
+
vi.spyOn(document.head, 'appendChild').mockImplementation((node) => {
|
|
10
|
+
if (node instanceof HTMLScriptElement) {
|
|
11
|
+
// Trigger onload manually
|
|
12
|
+
setTimeout(() => {
|
|
13
|
+
if (node.onload) node.onload(new Event('load'));
|
|
14
|
+
}, 10);
|
|
15
|
+
}
|
|
16
|
+
return node;
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('requires siteKey', () => {
|
|
21
|
+
expect(() => new TrustSigClient({ siteKey: '' })).toThrow('SITE_KEY_REQUIRED');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('injects script tag', async () => {
|
|
25
|
+
const client = new TrustSigClient({ siteKey: 'TEST_KEY' });
|
|
26
|
+
const loadPromise = client.load();
|
|
27
|
+
const appendCall = (document.head.appendChild as any).mock.calls[0][0];
|
|
28
|
+
|
|
29
|
+
expect(appendCall).not.toBeNull();
|
|
30
|
+
expect(appendCall.getAttribute('data-site-key')).toBe('TEST_KEY');
|
|
31
|
+
expect(appendCall.src).toBe('https://sdk.trustsig.com/trustsig.js');
|
|
32
|
+
await loadPromise;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('returns response from window when loaded', async () => {
|
|
36
|
+
const client = new TrustSigClient({ siteKey: 'TEST_KEY' });
|
|
37
|
+
(window as any).TrustSig = {
|
|
38
|
+
getResponse: vi.fn().mockResolvedValue('test-token')
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const token = await client.getResponse();
|
|
42
|
+
expect(token).toBe('test-token');
|
|
43
|
+
});
|
|
44
|
+
});
|
package/tsup.config.ts
ADDED