@c15t/node-sdk 3.0.0-alpha.3 → 3.0.0-alpha.5
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 +53 -45
- package/dist/160.js +68 -0
- package/dist/index.js +1016 -349
- package/dist/testing.js +42 -87
- package/dist-types/client.d.ts +112 -705
- package/dist-types/configuration-error.d.ts +17 -0
- package/dist-types/contract.d.ts +868 -0
- package/dist-types/errors.d.ts +143 -0
- package/dist-types/index.d.ts +13 -40
- package/dist-types/options.d.ts +152 -0
- package/dist-types/path.d.ts +24 -0
- package/dist-types/result.d.ts +77 -0
- package/dist-types/testing.d.ts +81 -90
- package/dist-types/transport.d.ts +19 -0
- package/dist-types/version.d.ts +1 -1
- package/package.json +6 -12
- package/dist-types/endpoints/consent.d.ts +0 -16
- package/dist-types/endpoints/index.d.ts +0 -4
- package/dist-types/endpoints/init.d.ts +0 -15
- package/dist-types/endpoints/status.d.ts +0 -15
- package/dist-types/endpoints/subjects.d.ts +0 -45
- package/dist-types/error.d.ts +0 -85
- package/dist-types/fetcher.d.ts +0 -37
- package/dist-types/headers.d.ts +0 -3
- package/dist-types/types.d.ts +0 -234
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</a>
|
|
8
8
|
</p>
|
|
9
9
|
|
|
10
|
-
# @c15t/node-sdk:
|
|
10
|
+
# @c15t/node-sdk: Node.js client for the c15t consent API
|
|
11
11
|
|
|
12
12
|
<p>
|
|
13
13
|
<a href="https://www.npmjs.com/package/@c15t/node-sdk"><picture><source media="(prefers-color-scheme: dark)" srcset="https://shieldcn.dev/npm/%40c15t%2Fnode-sdk.svg?variant=outline&mode=dark"><img src="https://shieldcn.dev/npm/%40c15t%2Fnode-sdk.svg?variant=outline&mode=light" alt="Latest NPM Version"></picture></a>
|
|
@@ -18,71 +18,79 @@
|
|
|
18
18
|
<a href="https://inth.com?utm_source=npm&utm_medium=readme&utm_campaign=oss_readme&utm_content=%40c15t%2Fnode-sdk"><picture><source media="(prefers-color-scheme: dark)" srcset="https://shieldcn.dev/badge/Made%20By-Inth-ffc803.svg?color=ffc803&labelTextColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCAzOTMgNDAwIj48cGF0aCBmaWxsPSIjMDAwIiBkPSJNMTgyLjY2MiAwdjM2Ljg5NWgtNTkuMDMxdjgyLjczM2g1OS4wMzF2MzYuODkzSDI3LjQ4MnYtMzYuODkzaDU5LjAzVjM2Ljg5NWgtNTkuMDNWMHpNMzIxLjk0MSA4OS44NVYwaDM1LjM1NXYxNTYuNTIxaC0yNS43MTNsLTg2LjEzNy05MC4zNjR2OTAuMzY0aC0zNS4zNTVWMGgyNi4zNTV6Ii8%2BPHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzE4LjU3MSAxODUuNzE0aDc0LjI4NlY0MDBIMFYxODUuNzE0aDI3Mi44NTd2LTQ3LjE0M3ptLTI5MS4wOSAyOC45Njl2MzcuMTE4aDU4LjEzN3YxMTkuNjI4aDM2Ljg5NVYyNTEuODAxaDU4LjU4NHYtMzcuMTE4em0xODIuNjEuMjI0djE1Ni41MjJoMzYuODk0VjMxMy41OWg3My4zNDF2NTcuODM5aDM3LjExOFYyMTQuOTA3aC0zNy4xMTh2NjEuNzg4aC03My4zNDF2LTYxLjc4OHoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg%3D%3D&valueColor=000000&mode=dark"><img src="https://shieldcn.dev/badge/Made%20By-Inth-ffc803.svg?color=ffc803&labelTextColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCAzOTMgNDAwIj48cGF0aCBmaWxsPSIjMDAwIiBkPSJNMTgyLjY2MiAwdjM2Ljg5NWgtNTkuMDMxdjgyLjczM2g1OS4wMzF2MzYuODkzSDI3LjQ4MnYtMzYuODkzaDU5LjAzVjM2Ljg5NWgtNTkuMDNWMHpNMzIxLjk0MSA4OS44NVYwaDM1LjM1NXYxNTYuNTIxaC0yNS43MTNsLTg2LjEzNy05MC4zNjR2OTAuMzY0aC0zNS4zNTVWMGgyNi4zNTV6Ii8%2BPHBhdGggZmlsbD0iIzAwMCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzE4LjU3MSAxODUuNzE0aDc0LjI4NlY0MDBIMFYxODUuNzE0aDI3Mi44NTd2LTQ3LjE0M3ptLTI5MS4wOSAyOC45Njl2MzcuMTE4aDU4LjEzN3YxMTkuNjI4aDM2Ljg5NVYyNTEuODAxaDU4LjU4NHYtMzcuMTE4em0xODIuNjEuMjI0djE1Ni41MjJoMzYuODk0VjMxMy41OWg3My4zNDF2NTcuODM5aDM3LjExOFYyMTQuOTA3aC0zNy4xMTh2NjEuNzg4aC03My4zNDF2LTYxLjc4OHoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg%3D%3D&valueColor=000000&mode=light" alt="Made by Inth"></picture></a>
|
|
19
19
|
</p>
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
Typed client for hosted and self-hosted c15t backends. Check consent before sending email, link users after sign-in, export a user's consent records, publish legal document releases from CI and read banner experiment results.
|
|
22
22
|
|
|
23
23
|
## Key Features
|
|
24
24
|
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
- Comprehensive error handling and URL validation
|
|
25
|
+
- One `createC15tClient()` call with an explicit backend URL. No environment variables are read
|
|
26
|
+
- Methods resolve to `{ ok: true, data }` or `{ ok: false, error }` and never reject. Error codes are typed per method
|
|
27
|
+
- Key-only methods (`subjects.list`, `experiments.summary`, `legalDocuments.publish`) exist only on a client created with an API key
|
|
28
|
+
- Input is validated before anything is sent, and response dates are `Date` objects
|
|
29
|
+
- Per-attempt timeouts and retries for network errors, timeouts and 408, 429, 500, 502, 503 and 504, honouring `Retry-After`
|
|
30
|
+
- A typed mock client in `@c15t/node-sdk/testing`
|
|
32
31
|
|
|
33
32
|
## Prerequisites
|
|
34
33
|
|
|
35
|
-
- Node.js 20.19 or later
|
|
36
|
-
- A hosted [c15t instance](https://inth.com)
|
|
34
|
+
- Node.js 20.19 or later, or another runtime with `fetch`, `AbortSignal.any` and `crypto.randomUUID`
|
|
35
|
+
- A hosted [c15t instance](https://inth.com) or a [self-hosted backend](https://c15t.com/docs/self-host/quickstart)
|
|
37
36
|
|
|
38
37
|
## Manual Installation
|
|
39
38
|
|
|
40
39
|
```bash
|
|
41
|
-
pnpm add @c15t/node-sdk
|
|
40
|
+
pnpm add @c15t/node-sdk@alpha
|
|
42
41
|
```
|
|
43
42
|
|
|
44
43
|
## Usage
|
|
45
44
|
|
|
46
|
-
1.
|
|
47
|
-
2.
|
|
48
|
-
3. Call API methods on `client.meta`, `client.subjects`, etc. — every method is fully typed
|
|
45
|
+
1. Create a client with the URL where the backend is mounted, path included. Pass `apiKey` for the key-only methods
|
|
46
|
+
2. Call a method and check `result.ok` before reading `result.data`, or use `unwrap(result)` to throw the error instead
|
|
49
47
|
|
|
50
48
|
```ts
|
|
51
49
|
// server.ts
|
|
52
|
-
import {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
preferences: { analytics: true },
|
|
72
|
-
givenAt: Date.now(),
|
|
73
|
-
})
|
|
74
|
-
console.log('Created subject', subject.id)
|
|
75
|
-
} catch (error) {
|
|
76
|
-
console.error('c15t request failed:', error)
|
|
50
|
+
import { createC15tClient } from '@c15t/node-sdk';
|
|
51
|
+
|
|
52
|
+
const apiKey = process.env.C15T_API_KEY;
|
|
53
|
+
if (!apiKey) throw new Error('Set C15T_API_KEY');
|
|
54
|
+
|
|
55
|
+
const c15t = createC15tClient({
|
|
56
|
+
baseUrl: 'https://app.example.com/api/c15t',
|
|
57
|
+
apiKey,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const result = await c15t.consents.check({
|
|
61
|
+
externalId: user.id,
|
|
62
|
+
types: ['marketing_communications'],
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (result.ok && result.data.results.marketing_communications.hasConsent) {
|
|
66
|
+
await sendNewsletter(user);
|
|
67
|
+
} else if (!result.ok) {
|
|
68
|
+
console.error(result.error.code, result.error.requestId);
|
|
77
69
|
}
|
|
78
70
|
```
|
|
79
71
|
|
|
80
|
-
##
|
|
72
|
+
## Documentation
|
|
73
|
+
|
|
74
|
+
For further information, guides, and examples visit the [reference documentation](https://c15t.com/docs/self-host/api/node-sdk).
|
|
75
|
+
|
|
76
|
+
## Methods
|
|
77
|
+
|
|
78
|
+
| Method | API key |
|
|
79
|
+
| --- | --- |
|
|
80
|
+
| `consents.check({ externalId, types })` | No |
|
|
81
|
+
| `subjects.identify(id, { externalId, identityProvider })` | No |
|
|
82
|
+
| `subjects.get(id, { types })` | No |
|
|
83
|
+
| `subjects.create(input)` | No |
|
|
84
|
+
| `subjects.list({ externalId })` | Required |
|
|
85
|
+
| `legalDocuments.publish(type, { version, hash, effectiveDate })` | Required |
|
|
86
|
+
| `experiments.summary(id, { from, to, domain })` | Required |
|
|
87
|
+
| `status()`, `init()`, `manifest()` | No |
|
|
88
|
+
|
|
89
|
+
Every method takes `{ signal, timeoutMs, headers, retry, requestId }` as its last argument.
|
|
90
|
+
|
|
91
|
+
## Upgrading from v2
|
|
81
92
|
|
|
82
|
-
|
|
83
|
-
- Build admin tooling around hosted or self-hosted consent APIs
|
|
84
|
-
- Automate privacy preference workflows from server-side jobs
|
|
85
|
-
- Integrate c15t consent records with internal data systems
|
|
93
|
+
`c15tClient()` and the `C15TClient` class are replaced by `createC15tClient()`. Results replace `ResponseContext`, `C15TError` is now `C15tError`, and `subjects.patch` is now `subjects.identify`. See the [migration guide](https://c15t.com/docs/upgrade-v3#update-the-nodejs-sdk).
|
|
86
94
|
|
|
87
95
|
## Support
|
|
88
96
|
|
package/dist/160.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const C15T_API_ERROR_CODES = [
|
|
2
|
+
'BAD_REQUEST',
|
|
3
|
+
'CHOICE_OUT_OF_SCOPE',
|
|
4
|
+
'CHOICE_PREFERENCE_MISMATCH',
|
|
5
|
+
'CONFLICT',
|
|
6
|
+
'DATABASE_ERROR',
|
|
7
|
+
'EXTERNAL_ID_REQUIRED',
|
|
8
|
+
'INPUT_VALIDATION_FAILED',
|
|
9
|
+
'NOT_FOUND',
|
|
10
|
+
'POLICY_SNAPSHOT_EXPIRED',
|
|
11
|
+
'POLICY_SNAPSHOT_INVALID',
|
|
12
|
+
'POLICY_SNAPSHOT_REQUIRED',
|
|
13
|
+
'PURPOSE_NOT_ALLOWED',
|
|
14
|
+
'SERVICE_UNAVAILABLE',
|
|
15
|
+
'STALE_POLICY',
|
|
16
|
+
'SUBJECT_CONFLICT',
|
|
17
|
+
'TYPE_REQUIRED',
|
|
18
|
+
'UNAUTHORIZED'
|
|
19
|
+
];
|
|
20
|
+
const C15T_CLIENT_ERROR_CODES = [
|
|
21
|
+
'ABORTED',
|
|
22
|
+
'INVALID_INPUT',
|
|
23
|
+
'MISSING_API_KEY',
|
|
24
|
+
'NETWORK_ERROR',
|
|
25
|
+
'TIMEOUT',
|
|
26
|
+
'UNEXPECTED_RESPONSE'
|
|
27
|
+
];
|
|
28
|
+
const isStalePolicyReason = (value)=>'decision-mismatch' === value || 'incomplete-inputs' === value || 'policy-changed' === value;
|
|
29
|
+
class C15tError extends Error {
|
|
30
|
+
name = 'C15tError';
|
|
31
|
+
code;
|
|
32
|
+
status;
|
|
33
|
+
reason;
|
|
34
|
+
requestId;
|
|
35
|
+
retryable;
|
|
36
|
+
issues;
|
|
37
|
+
serverCode;
|
|
38
|
+
constructor(init){
|
|
39
|
+
super(init.message, void 0 === init.cause ? {} : {
|
|
40
|
+
cause: init.cause
|
|
41
|
+
});
|
|
42
|
+
this.code = init.code;
|
|
43
|
+
this.status = init.status;
|
|
44
|
+
this.reason = 'STALE_POLICY' === init.code && isStalePolicyReason(init.reason) ? init.reason : void 0;
|
|
45
|
+
this.requestId = init.requestId;
|
|
46
|
+
this.retryable = init.retryable ?? false;
|
|
47
|
+
this.issues = init.issues;
|
|
48
|
+
this.serverCode = init.serverCode;
|
|
49
|
+
}
|
|
50
|
+
toJSON() {
|
|
51
|
+
return {
|
|
52
|
+
code: this.code,
|
|
53
|
+
issues: this.issues,
|
|
54
|
+
message: this.message,
|
|
55
|
+
name: this.name,
|
|
56
|
+
reason: this.reason,
|
|
57
|
+
requestId: this.requestId,
|
|
58
|
+
retryable: this.retryable,
|
|
59
|
+
serverCode: this.serverCode,
|
|
60
|
+
status: this.status
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function isC15tError(error, ...codes) {
|
|
65
|
+
if (!(error instanceof C15tError)) return false;
|
|
66
|
+
return 0 === codes.length || codes.includes(error.code);
|
|
67
|
+
}
|
|
68
|
+
export { C15T_API_ERROR_CODES, C15T_CLIENT_ERROR_CODES, C15tError, isC15tError, isStalePolicyReason };
|