@leadping/consent 0.0.0-stage → 1.0.1

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.
@@ -0,0 +1,10 @@
1
+ /** Serial, bounded retry transport. A resolved request means durable server acknowledgment. */
2
+ export declare class CaptureTransport {
3
+ private readonly baseUrl;
4
+ private readonly token;
5
+ private readonly abort;
6
+ constructor(baseUrl: string, token: string);
7
+ put(path: string, json: string): Promise<void>;
8
+ dispose(): void;
9
+ private delay;
10
+ }
@@ -0,0 +1,51 @@
1
+ import { CaptureRejectedError } from './capture-rejected-error.js';
2
+ /** Serial, bounded retry transport. A resolved request means durable server acknowledgment. */
3
+ export class CaptureTransport {
4
+ baseUrl;
5
+ token;
6
+ abort = new AbortController();
7
+ constructor(baseUrl, token) {
8
+ this.baseUrl = baseUrl;
9
+ this.token = token;
10
+ }
11
+ async put(path, json) {
12
+ let body = json;
13
+ const headers = {
14
+ 'Content-Type': 'application/json', 'X-Leadping-Capture-Token': this.token,
15
+ };
16
+ // Compress once per batch, then reuse the same bytes for retries.
17
+ if (json.length > 4096 && typeof CompressionStream !== 'undefined') {
18
+ body = await new Response(new Blob([json]).stream().pipeThrough(new CompressionStream('gzip'))).arrayBuffer();
19
+ headers['Content-Encoding'] = 'gzip';
20
+ }
21
+ for (let attempt = 0; attempt < 5; attempt++) {
22
+ try {
23
+ const response = await fetch(this.baseUrl + path, {
24
+ method: 'PUT', headers, body, credentials: 'omit', redirect: 'error',
25
+ signal: AbortSignal.any([this.abort.signal, AbortSignal.timeout(15000)]),
26
+ });
27
+ if (response.ok)
28
+ return;
29
+ if (response.status < 500 && response.status !== 408 && response.status !== 429)
30
+ throw new CaptureRejectedError(`Capture rejected (${response.status}).`);
31
+ }
32
+ catch (error) {
33
+ if (error instanceof CaptureRejectedError || this.abort.signal.aborted)
34
+ throw error;
35
+ }
36
+ if (attempt === 4)
37
+ break;
38
+ await this.delay(Math.min(8000, 500 * 2 ** attempt) + Math.random() * 250);
39
+ }
40
+ throw new Error('Capture upload could not be acknowledged.');
41
+ }
42
+ dispose() { this.abort.abort(); }
43
+ delay(ms) {
44
+ return new Promise((resolve, reject) => {
45
+ this.abort.signal.throwIfAborted();
46
+ const onAbort = () => { clearTimeout(timer); reject(this.abort.signal.reason); };
47
+ const timer = setTimeout(() => { this.abort.signal.removeEventListener('abort', onAbort); resolve(); }, ms);
48
+ this.abort.signal.addEventListener('abort', onAbort, { once: true });
49
+ });
50
+ }
51
+ }
@@ -0,0 +1,42 @@
1
+ export interface ConsentForm {
2
+ id: string;
3
+ sourceId?: string;
4
+ origin: string;
5
+ disclosure: string;
6
+ sellers?: string[];
7
+ channels?: string[];
8
+ approvedForContact?: boolean;
9
+ }
10
+ /** Obtain from your backend. Never put a Leadping source API key in the browser. */
11
+ export interface CaptureSession {
12
+ sessionId: string;
13
+ uploadToken: string;
14
+ expiresAt: string;
15
+ form: ConsentForm;
16
+ }
17
+ export interface Recipient {
18
+ firstName?: string;
19
+ lastName?: string;
20
+ email?: string;
21
+ phone?: string;
22
+ }
23
+ export interface CaptureReference {
24
+ sessionId: string;
25
+ uploadToken: string;
26
+ }
27
+ export interface CaptureOptions {
28
+ /** Absolute HTTPS API origin; no credentials or query string. */
29
+ apiUrl: string;
30
+ session: CaptureSession;
31
+ form: HTMLFormElement;
32
+ disclosure: HTMLElement;
33
+ checkbox: HTMLInputElement;
34
+ /** Called on terminal capture failures; never includes captured values. */
35
+ onError?: (error: Error) => void;
36
+ }
37
+ export interface SealedBatch {
38
+ number: number;
39
+ firstEventNumber: number;
40
+ lastEventNumber: number;
41
+ body: string;
42
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,37 @@
1
1
  {
2
2
  "name": "@leadping/consent",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.1",
4
+ "description": "Leadping consent capture SDK for browser forms.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/leadpingai/leadping-consent-typescript.git"
8
+ },
9
+ "publishConfig": {
10
+ "access": "public",
11
+ "registry": "https://registry.npmjs.org"
12
+ },
13
+ "type": "module",
14
+ "sideEffects": false,
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js"
22
+ }
23
+ },
24
+ "scripts": {
25
+ "build": "tsc && node build.mjs",
26
+ "test": "node --test test/*.test.mjs",
27
+ "benchmark": "node test/benchmark.mjs"
28
+ },
29
+ "dependencies": {
30
+ "rrweb": "2.1.7",
31
+ "@rrweb/types": "2.1.7"
32
+ },
33
+ "devDependencies": {
34
+ "esbuild": "0.28.2",
35
+ "typescript": "7.0.2"
36
+ }
37
+ }