@solutiondesk/legal 0.0.0 → 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/LICENSE +21 -0
- package/README.md +176 -27
- package/dist/index.cjs +309 -0
- package/dist/index.d.cts +456 -0
- package/dist/index.d.ts +456 -0
- package/dist/index.js +298 -0
- package/package.json +58 -7
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The HTTP part shared by the public SolutionDesk SDKs. Runs on any runtime with
|
|
3
|
+
* a WHATWG `fetch` (Node ≥ 18, Deno, Bun, edge runtimes, browsers) — and on
|
|
4
|
+
* purpose names no DOM or Node type, so the published `.d.ts` files need neither
|
|
5
|
+
* `lib: ["dom"]` nor `@types/node`.
|
|
6
|
+
*/
|
|
7
|
+
/** The production API. */
|
|
8
|
+
declare const DEFAULT_BASE_URL = "https://api.solutiondesk.io";
|
|
9
|
+
/** The response parts the SDK reads — what every `fetch` implementation returns. */
|
|
10
|
+
interface FetchResponseLike {
|
|
11
|
+
readonly status: number;
|
|
12
|
+
readonly ok: boolean;
|
|
13
|
+
readonly headers: {
|
|
14
|
+
get(name: string): string | null;
|
|
15
|
+
};
|
|
16
|
+
text(): Promise<string>;
|
|
17
|
+
}
|
|
18
|
+
/** What the SDK passes to `fetch` (plus whatever you set in `fetchOptions`). */
|
|
19
|
+
interface FetchInitLike {
|
|
20
|
+
method: string;
|
|
21
|
+
headers: Record<string, string>;
|
|
22
|
+
body?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A `fetch` implementation. The global `fetch` fits, so do `undici`, `node-fetch`
|
|
26
|
+
* and wrappers (e.g. one that adds tracing). Declared bivariantly so a fetch with
|
|
27
|
+
* a richer `init` type is accepted.
|
|
28
|
+
*/
|
|
29
|
+
type FetchLike = {
|
|
30
|
+
bivarianceHack(input: string, init?: FetchInitLike): Promise<FetchResponseLike>;
|
|
31
|
+
}["bivarianceHack"];
|
|
32
|
+
/** A response kept for `If-None-Match` revalidation. */
|
|
33
|
+
interface CachedResponse {
|
|
34
|
+
etag: string;
|
|
35
|
+
body: unknown;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Where the client keeps answers for ETag revalidation. Any `Map` fits; bring
|
|
39
|
+
* your own to share it between clients or to bound it differently.
|
|
40
|
+
*/
|
|
41
|
+
interface EtagCache {
|
|
42
|
+
get(key: string): CachedResponse | undefined;
|
|
43
|
+
set(key: string, value: CachedResponse): unknown;
|
|
44
|
+
}
|
|
45
|
+
/** Options every client factory takes. */
|
|
46
|
+
interface BaseClientOptions {
|
|
47
|
+
/** The API origin, without `/v1`. Defaults to `https://api.solutiondesk.io`. */
|
|
48
|
+
baseUrl?: string;
|
|
49
|
+
/** A `fetch` implementation; defaults to the global one. */
|
|
50
|
+
fetch?: FetchLike;
|
|
51
|
+
/** Headers sent with every request (e.g. `accept-language` forwarded from your visitor). */
|
|
52
|
+
headers?: Record<string, string>;
|
|
53
|
+
/**
|
|
54
|
+
* Revalidate with `If-None-Match`: the client remembers each answer's `ETag`
|
|
55
|
+
* and, when the API answers `304 Not Modified`, returns the remembered body.
|
|
56
|
+
* `true` keeps up to 500 answers in memory; or pass your own {@link EtagCache}.
|
|
57
|
+
* Off by default (your framework's fetch cache may already do this).
|
|
58
|
+
*/
|
|
59
|
+
etagCache?: boolean | EtagCache;
|
|
60
|
+
}
|
|
61
|
+
/** Per-call options. */
|
|
62
|
+
interface RequestOptions {
|
|
63
|
+
/** Cancels the request (an `AbortSignal`). */
|
|
64
|
+
signal?: unknown;
|
|
65
|
+
/** Extra headers for this request. */
|
|
66
|
+
headers?: Record<string, string>;
|
|
67
|
+
/**
|
|
68
|
+
* Extra `fetch` options for this request, passed through unchanged — e.g.
|
|
69
|
+
* Next.js `{ next: { revalidate: 60, tags: ["legal"] } }` or `{ cache: "no-store" }`.
|
|
70
|
+
*/
|
|
71
|
+
fetchOptions?: Record<string, unknown>;
|
|
72
|
+
}
|
|
73
|
+
/** Any non-2xx answer of the API (and a failed network request, with `status` 0). */
|
|
74
|
+
declare class SolutionDeskError extends Error {
|
|
75
|
+
/** The HTTP status; `0` when no answer arrived (network error, aborted). */
|
|
76
|
+
readonly status: number;
|
|
77
|
+
/** The parsed JSON body of the error answer (usually `{ error: string }`), else its text. */
|
|
78
|
+
readonly body: unknown;
|
|
79
|
+
/** The requested URL. */
|
|
80
|
+
readonly url: string;
|
|
81
|
+
/** Messages per input field on a `400` (e.g. `{ email: "Enter a valid email address." }`). */
|
|
82
|
+
readonly fields: Record<string, string>;
|
|
83
|
+
constructor(message: string, init: {
|
|
84
|
+
status: number;
|
|
85
|
+
body?: unknown;
|
|
86
|
+
url: string;
|
|
87
|
+
cause?: unknown;
|
|
88
|
+
});
|
|
89
|
+
/** `404`: unknown workspace, module turned off or unknown item — on purpose indistinguishable. */
|
|
90
|
+
get isNotFound(): boolean;
|
|
91
|
+
/** `429`: over the rate limit; try again later. */
|
|
92
|
+
get isRateLimited(): boolean;
|
|
93
|
+
}
|
|
94
|
+
/** A bounded in-memory {@link EtagCache} (oldest entry dropped first). */
|
|
95
|
+
declare function createMemoryEtagCache(maxEntries?: number): EtagCache;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Webhook signature check with Web Crypto only — the same code runs in Node,
|
|
99
|
+
* Deno, Bun, edge runtimes and browsers. The header SolutionDesk sends is
|
|
100
|
+
* `X-SolutionDesk-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>`.
|
|
101
|
+
*/
|
|
102
|
+
/** The header that carries the signature. */
|
|
103
|
+
declare const SIGNATURE_HEADER = "x-solutiondesk-signature";
|
|
104
|
+
/** The header that names the event (also in the body as `event`). */
|
|
105
|
+
declare const EVENT_HEADER = "x-solutiondesk-event";
|
|
106
|
+
interface VerifyWebhookOptions {
|
|
107
|
+
/** How old (or how far in the future) the signed time may be. Default 300 (5 minutes). */
|
|
108
|
+
toleranceSeconds?: number;
|
|
109
|
+
/** "Now" in milliseconds (or a `Date`) — for tests. Default `Date.now()`. */
|
|
110
|
+
now?: number | Date;
|
|
111
|
+
/**
|
|
112
|
+
* A Web Crypto implementation. Default `globalThis.crypto`. On Node 18 pass
|
|
113
|
+
* `require("node:crypto").webcrypto` (Node 19+ has it globally).
|
|
114
|
+
*/
|
|
115
|
+
crypto?: {
|
|
116
|
+
subtle: object;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/** The raw request body, exactly as received. */
|
|
120
|
+
type WebhookBody = string | Uint8Array | ArrayBuffer;
|
|
121
|
+
/**
|
|
122
|
+
* Check a SolutionDesk webhook signature. `true` only when the header is well
|
|
123
|
+
* formed, its time lies within the tolerance and the HMAC matches — anything
|
|
124
|
+
* else (missing, tampered, expired, malformed) is `false`, never an exception.
|
|
125
|
+
*
|
|
126
|
+
* @param secret The webhook's signing secret (`whsec_…`), shown once in SolutionDesk.
|
|
127
|
+
* @param rawBody The request body exactly as received — not re-serialized JSON.
|
|
128
|
+
* @param header The `X-SolutionDesk-Signature` header.
|
|
129
|
+
*/
|
|
130
|
+
declare function verifyWebhookSignature(secret: string, rawBody: WebhookBody, header: string | null | undefined, options?: VerifyWebhookOptions): Promise<boolean>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* The answers of the public Legal Hub API (`GET /v1/legal/{workspace}/…`), the
|
|
134
|
+
* host integration (`/v1/integration/legal/…`) and the webhook. Written by hand
|
|
135
|
+
* so the package has no dependencies; a drift test in the SolutionDesk
|
|
136
|
+
* repository keeps them in line with the API's own contracts.
|
|
137
|
+
*/
|
|
138
|
+
/** What a legal text is. */
|
|
139
|
+
type LegalDocumentKind = "imprint" | "privacy" | "terms" | "dpa" | "subprocessors" | "custom";
|
|
140
|
+
/** Where a version stands at the time of the request (decided by date). */
|
|
141
|
+
type PublicLegalVersionStatus = "draft" | "upcoming" | "current" | "earlier";
|
|
142
|
+
/** A heading of the text, for a table of contents. */
|
|
143
|
+
interface LegalHeading {
|
|
144
|
+
/** 1–6. */
|
|
145
|
+
level: number;
|
|
146
|
+
text: string;
|
|
147
|
+
/** Unique within the text; `#<id>` links to the heading. */
|
|
148
|
+
id: string;
|
|
149
|
+
}
|
|
150
|
+
/** A version in short: its number, when it applies, what changed. */
|
|
151
|
+
interface PublicLegalVersionRef {
|
|
152
|
+
number: number;
|
|
153
|
+
effectiveAt: string;
|
|
154
|
+
summary: string;
|
|
155
|
+
}
|
|
156
|
+
/** One sub-processor as your website shows it (entries marked internal are never included). */
|
|
157
|
+
interface PublicLegalSubprocessor {
|
|
158
|
+
/** Stable across versions (`azure`, `postmark`). */
|
|
159
|
+
key: string;
|
|
160
|
+
name: string;
|
|
161
|
+
website: string | null;
|
|
162
|
+
/** What they do for you (in the requested language). */
|
|
163
|
+
purpose: string;
|
|
164
|
+
/** Which data they process (in the requested language). */
|
|
165
|
+
data: string;
|
|
166
|
+
/** ISO 3166-1 alpha-2 country codes (`DE`, `IE`, `US`) and an optional note. */
|
|
167
|
+
location: {
|
|
168
|
+
countries: string[];
|
|
169
|
+
note: string | null;
|
|
170
|
+
};
|
|
171
|
+
/** For a country outside the EU/EEA: `adequacy`, `scc`, `bcr` or `other`. */
|
|
172
|
+
transferSafeguard: {
|
|
173
|
+
kind: string;
|
|
174
|
+
note: string | null;
|
|
175
|
+
} | null;
|
|
176
|
+
}
|
|
177
|
+
/** A field of a sub-processor entry that changed. */
|
|
178
|
+
type PublicLegalSubprocessorField = "name" | "website" | "purpose" | "data" | "location" | "transferSafeguard";
|
|
179
|
+
/** What an announced sub-processor list changes against the one in force. */
|
|
180
|
+
interface PublicLegalSubprocessorChanges {
|
|
181
|
+
added: PublicLegalSubprocessor[];
|
|
182
|
+
removed: PublicLegalSubprocessor[];
|
|
183
|
+
changed: {
|
|
184
|
+
key: string;
|
|
185
|
+
fields: PublicLegalSubprocessorField[];
|
|
186
|
+
before: PublicLegalSubprocessor;
|
|
187
|
+
after: PublicLegalSubprocessor;
|
|
188
|
+
}[];
|
|
189
|
+
}
|
|
190
|
+
/** The announced next version. */
|
|
191
|
+
interface PublicLegalUpcoming extends PublicLegalVersionRef {
|
|
192
|
+
/** Only for the sub-processor list. */
|
|
193
|
+
changes?: PublicLegalSubprocessorChanges;
|
|
194
|
+
}
|
|
195
|
+
/** One entry of `GET …/documents`. */
|
|
196
|
+
interface PublicLegalDocumentSummary {
|
|
197
|
+
slug: string;
|
|
198
|
+
kind: LegalDocumentKind;
|
|
199
|
+
title: string;
|
|
200
|
+
/** The language of `title` and `current.summary`. */
|
|
201
|
+
locale: string;
|
|
202
|
+
/** Every language the version in force is offered in, its main one first. */
|
|
203
|
+
languages: string[];
|
|
204
|
+
current: PublicLegalVersionRef;
|
|
205
|
+
upcoming: PublicLegalVersionRef | null;
|
|
206
|
+
}
|
|
207
|
+
/** `GET …/documents`. */
|
|
208
|
+
interface PublicLegalDocumentsPayload {
|
|
209
|
+
documents: PublicLegalDocumentSummary[];
|
|
210
|
+
}
|
|
211
|
+
/** One version in full (`documents/{slug}`, `…/versions/{number}`, `preview`). */
|
|
212
|
+
interface PublicLegalDocument {
|
|
213
|
+
slug: string;
|
|
214
|
+
kind: LegalDocumentKind;
|
|
215
|
+
title: string;
|
|
216
|
+
status: PublicLegalVersionStatus;
|
|
217
|
+
/** Null only for a draft that was never published. */
|
|
218
|
+
number: number | null;
|
|
219
|
+
effectiveAt: string | null;
|
|
220
|
+
summary: string;
|
|
221
|
+
/** The language the text is really in. */
|
|
222
|
+
locale: string;
|
|
223
|
+
languages: string[];
|
|
224
|
+
markdown: string;
|
|
225
|
+
/** Safe to insert as it is: no scripts, no images, links only to web addresses. */
|
|
226
|
+
html: string;
|
|
227
|
+
headings: LegalHeading[];
|
|
228
|
+
/** The sub-processor list (internal entries removed); null for other kinds. */
|
|
229
|
+
subprocessors: PublicLegalSubprocessor[] | null;
|
|
230
|
+
/** The announced next version — only on the version in force. */
|
|
231
|
+
upcoming: PublicLegalUpcoming | null;
|
|
232
|
+
}
|
|
233
|
+
/** `GET …/documents/{slug}`, `…/versions/{number}` and `…/preview`. */
|
|
234
|
+
interface PublicLegalDocumentPayload {
|
|
235
|
+
document: PublicLegalDocument;
|
|
236
|
+
}
|
|
237
|
+
/** One entry of the archive. `until` is when a later version replaced it. */
|
|
238
|
+
interface PublicLegalArchiveEntry extends PublicLegalVersionRef {
|
|
239
|
+
status: Exclude<PublicLegalVersionStatus, "draft">;
|
|
240
|
+
until: string | null;
|
|
241
|
+
}
|
|
242
|
+
/** `GET …/documents/{slug}/versions`. */
|
|
243
|
+
interface PublicLegalVersionsPayload {
|
|
244
|
+
document: {
|
|
245
|
+
slug: string;
|
|
246
|
+
kind: LegalDocumentKind;
|
|
247
|
+
title: string;
|
|
248
|
+
locale: string;
|
|
249
|
+
};
|
|
250
|
+
versions: PublicLegalArchiveEntry[];
|
|
251
|
+
}
|
|
252
|
+
/** `GET …/subprocessors`: the list in force and what the announced one changes. */
|
|
253
|
+
interface PublicLegalSubprocessorsPayload {
|
|
254
|
+
document: {
|
|
255
|
+
slug: string;
|
|
256
|
+
title: string;
|
|
257
|
+
number: number;
|
|
258
|
+
effectiveAt: string;
|
|
259
|
+
locale: string;
|
|
260
|
+
languages: string[];
|
|
261
|
+
};
|
|
262
|
+
subprocessors: PublicLegalSubprocessor[];
|
|
263
|
+
upcoming: PublicLegalUpcoming | null;
|
|
264
|
+
}
|
|
265
|
+
/** How an agreement was given. */
|
|
266
|
+
type LegalAcceptanceChannel = "host" | "portal" | "email_link";
|
|
267
|
+
/** One version an end user still has to agree to. */
|
|
268
|
+
interface LegalHostPendingItem {
|
|
269
|
+
/** Document slug — what {@link LegalHostAcceptanceInput.document} takes. */
|
|
270
|
+
document: string;
|
|
271
|
+
kind: LegalDocumentKind;
|
|
272
|
+
/** Title in the requested language (else the main one). */
|
|
273
|
+
title: string;
|
|
274
|
+
number: number;
|
|
275
|
+
/** When the version takes (or took) effect. */
|
|
276
|
+
effectiveAt: string;
|
|
277
|
+
/** Already in force (false: announced, takes effect at `effectiveAt`). */
|
|
278
|
+
inForce: boolean;
|
|
279
|
+
/** What changed, in the requested language (else the main one). */
|
|
280
|
+
summary: string;
|
|
281
|
+
/** Where the full text can be read (in `locale`). */
|
|
282
|
+
url: string;
|
|
283
|
+
/** The language of `title`, `summary` and `url`. */
|
|
284
|
+
locale: string;
|
|
285
|
+
/** Agreed per company by an administrator: the company (your id) this agreement is for. */
|
|
286
|
+
companyExternalId: string | null;
|
|
287
|
+
}
|
|
288
|
+
/** `GET /v1/integration/legal/pending`. */
|
|
289
|
+
interface LegalHostPendingPayload {
|
|
290
|
+
pending: LegalHostPendingItem[];
|
|
291
|
+
}
|
|
292
|
+
/** `POST /v1/integration/legal/acceptances` — your user agreed in your own dialog. */
|
|
293
|
+
interface LegalHostAcceptanceInput {
|
|
294
|
+
/** The end user's id in your app. */
|
|
295
|
+
externalId: string;
|
|
296
|
+
/** The document's slug, e.g. `terms`. */
|
|
297
|
+
document: string;
|
|
298
|
+
/** The version number the user agreed to. */
|
|
299
|
+
number: number;
|
|
300
|
+
/** When the user agreed (ISO 8601 with offset or `Z`); defaults to now. Never in the future. */
|
|
301
|
+
acceptedAt?: string;
|
|
302
|
+
/** The user's IP address, kept as proof. */
|
|
303
|
+
ip?: string;
|
|
304
|
+
/** The user's browser, kept as proof. */
|
|
305
|
+
userAgent?: string;
|
|
306
|
+
/**
|
|
307
|
+
* The company the user agreed for (texts agreed per company by an
|
|
308
|
+
* administrator) — also the company a new end user is created in.
|
|
309
|
+
*/
|
|
310
|
+
companyExternalId?: string;
|
|
311
|
+
/** With `name` and `companyExternalId`: creates an end user SolutionDesk doesn't know yet. */
|
|
312
|
+
email?: string;
|
|
313
|
+
name?: string;
|
|
314
|
+
}
|
|
315
|
+
/** The answer to a reported agreement. */
|
|
316
|
+
interface LegalHostAcceptanceRecordedPayload {
|
|
317
|
+
ok: true;
|
|
318
|
+
/** False when nothing new was stored: the same agreement, or one that already covers it. */
|
|
319
|
+
created: boolean;
|
|
320
|
+
acceptance: {
|
|
321
|
+
id: string;
|
|
322
|
+
document: string;
|
|
323
|
+
/** The version the stored agreement is for (an earlier one covers an editorial change). */
|
|
324
|
+
number: number;
|
|
325
|
+
channel: LegalAcceptanceChannel;
|
|
326
|
+
acceptedAt: string;
|
|
327
|
+
/** Agreed for a company: its id in your app. */
|
|
328
|
+
companyExternalId: string | null;
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
/** What a legal webhook announces. */
|
|
332
|
+
type LegalWebhookEvent = "version.published" | "version.effective" | "version.withdrawn" | "acceptance.recorded" | "ping";
|
|
333
|
+
/** Who agreed, in your app's own ids (`acceptance.recorded`). */
|
|
334
|
+
interface LegalWebhookAcceptance {
|
|
335
|
+
/** The end user's id in your app (null for a user without one). */
|
|
336
|
+
externalId: string | null;
|
|
337
|
+
/** The company's id in your app, when one administrator agreed for it. */
|
|
338
|
+
company: string | null;
|
|
339
|
+
channel: LegalAcceptanceChannel;
|
|
340
|
+
acceptedAt: string;
|
|
341
|
+
}
|
|
342
|
+
/** The body of a legal webhook call (verify it first — see `parseLegalWebhook`). */
|
|
343
|
+
interface LegalWebhookBody {
|
|
344
|
+
event: LegalWebhookEvent;
|
|
345
|
+
/** The workspace slug, as in the public API path. */
|
|
346
|
+
workspace: string;
|
|
347
|
+
/** Document slug (null for `ping`). */
|
|
348
|
+
document: string | null;
|
|
349
|
+
kind: string | null;
|
|
350
|
+
number: number | null;
|
|
351
|
+
effectiveAt: string | null;
|
|
352
|
+
/** Languages the version is offered in (empty for `acceptance.recorded`). */
|
|
353
|
+
locales: string[];
|
|
354
|
+
occurredAt: string;
|
|
355
|
+
/** Only on `acceptance.recorded`. */
|
|
356
|
+
acceptance?: LegalWebhookAcceptance;
|
|
357
|
+
}
|
|
358
|
+
/** The body of an `acceptance.recorded` call. */
|
|
359
|
+
type LegalAcceptanceRecordedWebhook = LegalWebhookBody & {
|
|
360
|
+
event: "acceptance.recorded";
|
|
361
|
+
document: string;
|
|
362
|
+
kind: string;
|
|
363
|
+
acceptance: LegalWebhookAcceptance;
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
interface LegalClientOptions extends BaseClientOptions {
|
|
367
|
+
/** Your workspace's slug — the `acme` in `https://api.solutiondesk.io/v1/legal/acme`. */
|
|
368
|
+
workspace: string;
|
|
369
|
+
/**
|
|
370
|
+
* The language to ask for by default. You get exactly it if the text exists
|
|
371
|
+
* in it, else the same language of another region (`de-AT` → `de`), else the
|
|
372
|
+
* main language — `locale` in each answer says which. Override per call.
|
|
373
|
+
*/
|
|
374
|
+
lang?: string;
|
|
375
|
+
}
|
|
376
|
+
interface LangParams {
|
|
377
|
+
/** The language to ask for; overrides the client's `lang`. */
|
|
378
|
+
lang?: string;
|
|
379
|
+
}
|
|
380
|
+
interface LegalClient {
|
|
381
|
+
/** The workspace this client reads. */
|
|
382
|
+
readonly workspace: string;
|
|
383
|
+
/** Every text with the version that applies today and, if announced, the next one. */
|
|
384
|
+
listDocuments(params?: LangParams, options?: RequestOptions): Promise<PublicLegalDocumentsPayload>;
|
|
385
|
+
/**
|
|
386
|
+
* The version of a text that applies today, in full (`GET …/documents/{slug}`).
|
|
387
|
+
* Throws a `SolutionDeskError` with status 404 for an unknown slug, a
|
|
388
|
+
* workspace without legal texts and a text without a published version alike.
|
|
389
|
+
*/
|
|
390
|
+
getDocument(slug: string, params?: LangParams, options?: RequestOptions): Promise<PublicLegalDocumentPayload>;
|
|
391
|
+
/**
|
|
392
|
+
* Every published version of a text — earlier, current and announced. Only
|
|
393
|
+
* while "Show earlier versions on your website" is on (else 404).
|
|
394
|
+
*/
|
|
395
|
+
listVersions(slug: string, params?: LangParams, options?: RequestOptions): Promise<PublicLegalVersionsPayload>;
|
|
396
|
+
/** One version in full: the current one, the announced one, or an earlier one (when shown). */
|
|
397
|
+
getVersion(slug: string, number: number, params?: LangParams, options?: RequestOptions): Promise<PublicLegalDocumentPayload>;
|
|
398
|
+
/** The list of sub-processors in force and what the announced list changes. */
|
|
399
|
+
getSubprocessors(params?: LangParams, options?: RequestOptions): Promise<PublicLegalSubprocessorsPayload>;
|
|
400
|
+
/**
|
|
401
|
+
* Any version (also a draft) for your preview route — the `token` from your
|
|
402
|
+
* preview address (valid for one hour). The API sends it with
|
|
403
|
+
* `Cache-Control: no-store`; in Next.js also pass `fetchOptions: { cache: "no-store" }`.
|
|
404
|
+
*/
|
|
405
|
+
getPreview(token: string, params?: LangParams, options?: RequestOptions): Promise<PublicLegalDocumentPayload>;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* A client for the public Legal Hub API — no key, no login; only published
|
|
409
|
+
* versions. Load legal texts on the server or at build time and keep the last
|
|
410
|
+
* answer, so your imprint stays up even when SolutionDesk can't be reached.
|
|
411
|
+
*
|
|
412
|
+
* @example
|
|
413
|
+
* const legal = createLegalClient({ workspace: "acme", lang: "en" });
|
|
414
|
+
* const { document } = await legal.getDocument("imprint");
|
|
415
|
+
*/
|
|
416
|
+
declare function createLegalClient(options: LegalClientOptions): LegalClient;
|
|
417
|
+
interface LegalHostClientOptions extends Omit<BaseClientOptions, "etagCache"> {
|
|
418
|
+
/** An API key of your workspace (Settings → API keys). Keep it on your server. */
|
|
419
|
+
apiKey: string;
|
|
420
|
+
}
|
|
421
|
+
interface PendingParams {
|
|
422
|
+
/** The end user's id in your app. */
|
|
423
|
+
externalId: string;
|
|
424
|
+
/** The language for `title`, `summary` and `url`. */
|
|
425
|
+
lang?: string;
|
|
426
|
+
}
|
|
427
|
+
interface LegalHostClient {
|
|
428
|
+
/**
|
|
429
|
+
* The versions an end user still has to agree to
|
|
430
|
+
* (`GET /v1/integration/legal/pending`) — show them in your own dialog.
|
|
431
|
+
* Throws 404 for an unknown end user or with legal texts turned off.
|
|
432
|
+
*/
|
|
433
|
+
pending(params: PendingParams, options?: RequestOptions): Promise<LegalHostPendingPayload>;
|
|
434
|
+
/**
|
|
435
|
+
* Report that an end user agreed in your app
|
|
436
|
+
* (`POST /v1/integration/legal/acceptances`). Repeating it is harmless:
|
|
437
|
+
* `created` is false when nothing new was stored.
|
|
438
|
+
*/
|
|
439
|
+
recordAcceptance(input: LegalHostAcceptanceInput, options?: RequestOptions): Promise<LegalHostAcceptanceRecordedPayload>;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* **Server only.** A client for the legal part of the host API, authenticated
|
|
443
|
+
* with your workspace's API key (`Authorization: Bearer …`). Never ship the key
|
|
444
|
+
* to a browser.
|
|
445
|
+
*/
|
|
446
|
+
declare function createLegalHostClient(options: LegalHostClientOptions): LegalHostClient;
|
|
447
|
+
/**
|
|
448
|
+
* Verify a legal webhook call and return its body — or `null` when the
|
|
449
|
+
* `X-SolutionDesk-Signature` header doesn't match (wrong secret, changed body,
|
|
450
|
+
* older than 5 minutes, malformed). Pass the raw body exactly as received.
|
|
451
|
+
*/
|
|
452
|
+
declare function parseLegalWebhook(secret: string, rawBody: WebhookBody, signatureHeader: string | null | undefined, options?: VerifyWebhookOptions): Promise<LegalWebhookBody | null>;
|
|
453
|
+
/** Narrows a verified webhook body to `acceptance.recorded`. */
|
|
454
|
+
declare function isAcceptanceRecorded(body: LegalWebhookBody): body is LegalAcceptanceRecordedWebhook;
|
|
455
|
+
|
|
456
|
+
export { type BaseClientOptions, type CachedResponse, DEFAULT_BASE_URL, EVENT_HEADER, type EtagCache, type FetchInitLike, type FetchLike, type FetchResponseLike, type LangParams, type LegalAcceptanceChannel, type LegalAcceptanceRecordedWebhook, type LegalClient, type LegalClientOptions, type LegalDocumentKind, type LegalHeading, type LegalHostAcceptanceInput, type LegalHostAcceptanceRecordedPayload, type LegalHostClient, type LegalHostClientOptions, type LegalHostPendingItem, type LegalHostPendingPayload, type LegalWebhookAcceptance, type LegalWebhookBody, type LegalWebhookEvent, type PendingParams, type PublicLegalArchiveEntry, type PublicLegalDocument, type PublicLegalDocumentPayload, type PublicLegalDocumentSummary, type PublicLegalDocumentsPayload, type PublicLegalSubprocessor, type PublicLegalSubprocessorChanges, type PublicLegalSubprocessorField, type PublicLegalSubprocessorsPayload, type PublicLegalUpcoming, type PublicLegalVersionRef, type PublicLegalVersionStatus, type PublicLegalVersionsPayload, type RequestOptions, SIGNATURE_HEADER, SolutionDeskError, type VerifyWebhookOptions, type WebhookBody, createLegalClient, createLegalHostClient, createMemoryEtagCache, isAcceptanceRecorded, parseLegalWebhook, verifyWebhookSignature };
|