@dataships/sdk 0.0.0-stage → 2.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.
- package/LICENSE +202 -0
- package/README.md +330 -2
- package/dist/adapters/custom-platform-checkout/index.d.ts +139 -0
- package/dist/adapters/custom-platform-checkout/index.js +354 -0
- package/dist/adapters/custom-platform-checkout/index.js.map +1 -0
- package/dist/adapters/custom-platform-signup/index.d.ts +119 -0
- package/dist/adapters/custom-platform-signup/index.js +338 -0
- package/dist/adapters/custom-platform-signup/index.js.map +1 -0
- package/dist/adapters/salesforce/index.d.ts +100 -0
- package/dist/adapters/salesforce/index.js +328 -0
- package/dist/adapters/salesforce/index.js.map +1 -0
- package/dist/adapters/shopify-checkout/index.d.ts +102 -0
- package/dist/adapters/shopify-checkout/index.js +228 -0
- package/dist/adapters/shopify-checkout/index.js.map +1 -0
- package/dist/beacon-B8v41O8P.d.ts +4 -0
- package/dist/dataships.min.js +6 -0
- package/dist/dataships.min.js.map +1 -0
- package/dist/index.d.ts +190 -0
- package/dist/index.js +763 -0
- package/dist/index.js.map +1 -0
- package/dist/integrity.json +9 -0
- package/dist/locale-B1o0kX7n.d.ts +9 -0
- package/dist/retry-CGwSrbz_.d.ts +130 -0
- package/dist/server.d.ts +72 -0
- package/dist/server.js +455 -0
- package/dist/server.js.map +1 -0
- package/dist/types-vPJjFMJw.d.ts +236 -0
- package/package.json +83 -4
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
type Channel = "EMAIL" | "SMS" | "WHATSAPP";
|
|
2
|
+
/** Consent type of a v2 consent entry. `PENDING_IDENTITY` and `NO_WIDGET_DISPLAYED` never reach the client. */
|
|
3
|
+
type ConsentType = "OPT_IN" | "OPT_OUT" | "NO_OPT_IN" | "NO_OPT_OUT" | "NONE" | "OPT_IN_PRE_TICKED" | "PENDING_IDENTITY" | "NO_WIDGET_DISPLAYED";
|
|
4
|
+
declare const SUPPORTED_LOCALES: readonly ["en", "es", "de", "pt", "ro", "hr", "da", "fi", "fr", "hu", "it", "nb", "pl", "sk", "sv", "nl", "el", "cs", "zh", "ja", "is"];
|
|
5
|
+
type SupportedLocale = (typeof SUPPORTED_LOCALES)[number];
|
|
6
|
+
/**
|
|
7
|
+
* Which contact the consent-session envelope carries at the top
|
|
8
|
+
* level. `EMAIL` ⇒ email address, `PHONE` ⇒ phone number.
|
|
9
|
+
*/
|
|
10
|
+
type IdentifierType = "EMAIL" | "PHONE";
|
|
11
|
+
type Environment = "production" | "staging" | "local";
|
|
12
|
+
/** The consent-session handle `saveConsent` and `startHeartbeat` operate on. */
|
|
13
|
+
interface SessionIds {
|
|
14
|
+
consentSessionId: string | null;
|
|
15
|
+
}
|
|
16
|
+
/** Resolved top-level identifier for the consent-session envelope. */
|
|
17
|
+
interface ConsentSessionIdentifier {
|
|
18
|
+
identifier: string | null;
|
|
19
|
+
identifierType: IdentifierType;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Browser credentials for the consent-session protocol: the merchant's public
|
|
23
|
+
* key (`X-Api-Key`) and the JWT their server minted for this page, sent
|
|
24
|
+
* verbatim as `Authorization: Bearer`. The SDK never decodes or refreshes it;
|
|
25
|
+
* rotate it with {@link DatashipsClient.setToken}, or pass a
|
|
26
|
+
* {@link TokenProviderAuth} instead when the platform hands out short-lived
|
|
27
|
+
* tokens on demand.
|
|
28
|
+
*/
|
|
29
|
+
interface PublicKeyAuth {
|
|
30
|
+
publicKey: string;
|
|
31
|
+
token: string;
|
|
32
|
+
getToken?: never;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Browser credentials whose token is fetched before every request, retries and
|
|
36
|
+
* heartbeats included, for platforms that mint short-lived tokens on demand
|
|
37
|
+
* (Shopify's `shopify.sessionToken.get()`). The SDK never caches the result.
|
|
38
|
+
* Exclusive with {@link PublicKeyAuth.token}; `setToken()` does not apply.
|
|
39
|
+
*/
|
|
40
|
+
interface TokenProviderAuth {
|
|
41
|
+
publicKey: string;
|
|
42
|
+
getToken: () => string | Promise<string>;
|
|
43
|
+
token?: never;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Server-to-server credentials: the merchant's server key alone (`X-Api-Key`,
|
|
47
|
+
* no token). Only accepted by `DatashipsServerClient` from `@dataships/sdk/server`.
|
|
48
|
+
*/
|
|
49
|
+
interface ServerKeyAuth {
|
|
50
|
+
serverKey: string;
|
|
51
|
+
}
|
|
52
|
+
type CustomerApiAuth = PublicKeyAuth | ServerKeyAuth;
|
|
53
|
+
/**
|
|
54
|
+
* UNSAFE escape hatch for a merchant with no server to mint tokens: the server
|
|
55
|
+
* key itself in the page, sent alone as `X-Api-Key`. Anyone who views source
|
|
56
|
+
* can then open sessions, save consent and submit orders as that merchant
|
|
57
|
+
* until the key is revoked; revocation is the only remedy. The SDK warns once
|
|
58
|
+
* at construction and tags every request so the exposure is never silent.
|
|
59
|
+
* Prefer `PublicKeyAuth` wherever a token can be minted.
|
|
60
|
+
*/
|
|
61
|
+
interface UnsafeServerKeyAuth {
|
|
62
|
+
unsafeServerKey: string;
|
|
63
|
+
}
|
|
64
|
+
/** Credentials the browser client accepts: the safe pair (fixed or provided token), or the explicit unsafe escape hatch. */
|
|
65
|
+
type BrowserAuth = PublicKeyAuth | TokenProviderAuth | UnsafeServerKeyAuth;
|
|
66
|
+
interface UpsertSessionInput {
|
|
67
|
+
/** The only channel-related input: PHONE covers SMS and WhatsApp, the server picks the channels. */
|
|
68
|
+
identifierType: IdentifierType;
|
|
69
|
+
/** Contact for that type. Omit (or pass null) to let the adapter resolve the server-known value. */
|
|
70
|
+
identifier?: string | null;
|
|
71
|
+
/** Trusted as the geolocation source when present; otherwise the connection IP is used. */
|
|
72
|
+
userIp?: string;
|
|
73
|
+
/**
|
|
74
|
+
* How the copy comes back: `json` (the API default) leaves plain strings to
|
|
75
|
+
* format client-side, `html` applies links and emphasis to `text` and
|
|
76
|
+
* `consentDescription`.
|
|
77
|
+
*/
|
|
78
|
+
format?: ConsentCopyFormat;
|
|
79
|
+
}
|
|
80
|
+
type ConsentCopyFormat = "json" | "html";
|
|
81
|
+
/**
|
|
82
|
+
* Server-side upsert input: the connection IP is the merchant's server, so the
|
|
83
|
+
* user's IP must always be supplied for geolocation.
|
|
84
|
+
*/
|
|
85
|
+
interface ServerUpsertSessionInput extends UpsertSessionInput {
|
|
86
|
+
userIp: string;
|
|
87
|
+
}
|
|
88
|
+
/** Widget copy for one channel. Every field may be null; render what is present. */
|
|
89
|
+
interface ConsentWidgetConfig {
|
|
90
|
+
text: string | null;
|
|
91
|
+
consentDescription: string | null;
|
|
92
|
+
marketingInformation: string | null;
|
|
93
|
+
policyURL: string | null;
|
|
94
|
+
mobileTermsOfServiceURL: string | null;
|
|
95
|
+
privacyEmail: string | null;
|
|
96
|
+
/**
|
|
97
|
+
* What the copy's placeholders resolve to; null when it uses none. In `json` copy,
|
|
98
|
+
* render `{{MARKETING_PREFERENCES}}` as the marketing modal link showing
|
|
99
|
+
* `MARKETING_PREFERENCES` as is. `html` copy has it rendered already.
|
|
100
|
+
*/
|
|
101
|
+
placeholderValues?: WidgetCopyPlaceholderValues | null;
|
|
102
|
+
}
|
|
103
|
+
interface WidgetCopyPlaceholderValues {
|
|
104
|
+
MARKETING_PREFERENCES?: string;
|
|
105
|
+
}
|
|
106
|
+
/** One channel that renders a widget: its consent record plus the copy. */
|
|
107
|
+
interface ConsentItem {
|
|
108
|
+
channel: Channel;
|
|
109
|
+
consentType: ConsentType;
|
|
110
|
+
checked: boolean;
|
|
111
|
+
widgetConfig: ConsentWidgetConfig;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* `POST /v1/consent-session` response. An empty `consents` means there is
|
|
115
|
+
* nothing to render; `consentSessionId` is null only in that normalised
|
|
116
|
+
* nothing-to-render case (see `upsertSession`).
|
|
117
|
+
*/
|
|
118
|
+
interface UpsertSessionResponse {
|
|
119
|
+
consentSessionId: string | null;
|
|
120
|
+
consents: ConsentItem[];
|
|
121
|
+
/** Phone sessions only: whether the user must verify with a one-time code. Null for EMAIL. */
|
|
122
|
+
userVerificationRequired: boolean | null;
|
|
123
|
+
lastHeartbeat: string | null;
|
|
124
|
+
/**
|
|
125
|
+
* The identifier the session holds for the requested type, so a widget that
|
|
126
|
+
* lost what the user typed (a reload, a remount) can refill its field. Null
|
|
127
|
+
* while the session has none; absent from a core-api that predates it.
|
|
128
|
+
*/
|
|
129
|
+
identifier?: string | null;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Platform adapter for the `/v1/consent-session` protocol. It declares the
|
|
133
|
+
* `integration.type` discriminator, resolves the top-level identifier and
|
|
134
|
+
* returns the integration-specific fields from `getSessionContext()` (the
|
|
135
|
+
* client injects `type` under `integration` and `locale` at the top level; the
|
|
136
|
+
* merchant comes from the `X-Api-Key` header, never from the body).
|
|
137
|
+
*/
|
|
138
|
+
interface ConsentSessionAdapter<TContext = unknown> {
|
|
139
|
+
/**
|
|
140
|
+
* Adapter identifier reported via `X-Dataships-App` (e.g. "SalesforceAdapter").
|
|
141
|
+
* Used to distinguish which SDK adapter sourced the request.
|
|
142
|
+
*/
|
|
143
|
+
readonly name: string;
|
|
144
|
+
/**
|
|
145
|
+
* Always `"consent-session"`, the only protocol the SDK speaks. Kept as a
|
|
146
|
+
* constant marker because integrations check it to recognise an SDK adapter.
|
|
147
|
+
*/
|
|
148
|
+
readonly sessionApi: "consent-session";
|
|
149
|
+
/** ISO 639-1 locale code from the SupportedLocale union. */
|
|
150
|
+
getLocale(): SupportedLocale;
|
|
151
|
+
/** The integration-specific fields merged under `integration` on every upsert. */
|
|
152
|
+
getSessionContext(): Promise<TContext>;
|
|
153
|
+
/**
|
|
154
|
+
* When true, the client serves synthetic responses instead of making live
|
|
155
|
+
* network calls: `upsertSession` returns
|
|
156
|
+
* {@link getPreviewUpsertResponse}; `saveConsent`, the heartbeat, the OTP
|
|
157
|
+
* calls and `submitSession` resolve without a request. No credentials are
|
|
158
|
+
* needed. Used to style a widget in an editor or sandbox without hitting the
|
|
159
|
+
* API. Defaults to live behaviour when absent.
|
|
160
|
+
*/
|
|
161
|
+
previewMode?: boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Synthetic upsert response served when {@link previewMode} is true, for the
|
|
164
|
+
* requested identifier type, with the copy in the requested format.
|
|
165
|
+
*/
|
|
166
|
+
getPreviewUpsertResponse?(identifierType: IdentifierType, format?: ConsentCopyFormat): UpsertSessionResponse;
|
|
167
|
+
/** `integration.type` discriminator, e.g. "SALESFORCE_SNIPPET". */
|
|
168
|
+
readonly integrationType: string;
|
|
169
|
+
/**
|
|
170
|
+
* Resolves the top-level `identifier` / `identifierType` for `upsertSession`
|
|
171
|
+
* from the adapter's own data. An explicit `upsertSession({ identifier })`
|
|
172
|
+
* takes precedence, e.g. an email the buyer types mid-checkout.
|
|
173
|
+
*/
|
|
174
|
+
getIdentifier(identifierType: IdentifierType): ConsentSessionIdentifier | Promise<ConsentSessionIdentifier>;
|
|
175
|
+
/**
|
|
176
|
+
* The `datashipsSessionId` beacon the adapter sent on its upserts, when it
|
|
177
|
+
* owns one. `submitSession` uses it as the default id to complete, so a
|
|
178
|
+
* browser integration never has to carry the beacon itself. Adapters that
|
|
179
|
+
* have no beacon (server-side, Salesforce) leave this undefined and callers
|
|
180
|
+
* pass `datashipsSessionId` explicitly.
|
|
181
|
+
*/
|
|
182
|
+
getDatashipsSessionId?(): string;
|
|
183
|
+
/**
|
|
184
|
+
* Discard the beacon after a completed submit so the next collection on this
|
|
185
|
+
* browser opens a new session instead of touching the completed one.
|
|
186
|
+
*/
|
|
187
|
+
resetDatashipsSessionId?(): void;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* The shopper as the merchant knows them at completion. Both names are
|
|
191
|
+
* required and non-blank (core-api validates `NotBlank`). Contact details never
|
|
192
|
+
* travel here: the identifier is what the widget collected on the upsert.
|
|
193
|
+
*/
|
|
194
|
+
interface SubmitConsentSessionUser {
|
|
195
|
+
firstName: string;
|
|
196
|
+
lastName: string;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* `integration` details of a `CUSTOM_PLATFORM_CHECKOUT` submit: the order the
|
|
200
|
+
* shopper placed. Amounts are in the merchant integration's currency.
|
|
201
|
+
*/
|
|
202
|
+
interface CustomPlatformCheckoutSubmitDetails {
|
|
203
|
+
/** Merchant order id (max 255). */
|
|
204
|
+
id: string;
|
|
205
|
+
/** Order total as a number, zero allowed. */
|
|
206
|
+
total: number;
|
|
207
|
+
/** Billing country, ISO 3166-1 alpha-2; drives the legal basis. Case-insensitive here, sent uppercased. */
|
|
208
|
+
billingCountryCode: string;
|
|
209
|
+
/** When the order was placed; defaults server-side to the time the submit arrives. */
|
|
210
|
+
submittedAt?: string | Date;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Input to `submitSession`: the completion signal for every session opened
|
|
214
|
+
* under one beacon. `details` is the flow-specific payload merged under
|
|
215
|
+
* `integration` next to the adapter's `type`; for a checkout that is the
|
|
216
|
+
* order ({@link CustomPlatformCheckoutSubmitDetails}).
|
|
217
|
+
*/
|
|
218
|
+
interface SubmitSessionInput<TDetails = CustomPlatformCheckoutSubmitDetails> {
|
|
219
|
+
/**
|
|
220
|
+
* The beacon sent on the upserts. Browser clients default to the adapter's
|
|
221
|
+
* own beacon; the server client requires it, since a server holds none.
|
|
222
|
+
*/
|
|
223
|
+
datashipsSessionId?: string;
|
|
224
|
+
/** The shopper's names; required by core-api. */
|
|
225
|
+
user: SubmitConsentSessionUser;
|
|
226
|
+
details: TDetails;
|
|
227
|
+
/**
|
|
228
|
+
* Discard the adapter's beacon once the submit is accepted, so the next
|
|
229
|
+
* collection on this browser starts a new session. Defaults to true; has no
|
|
230
|
+
* effect when `datashipsSessionId` was passed explicitly.
|
|
231
|
+
*/
|
|
232
|
+
resetBeacon?: boolean;
|
|
233
|
+
}
|
|
234
|
+
type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
235
|
+
|
|
236
|
+
export { type BrowserAuth as B, type ConsentSessionAdapter as C, type Environment as E, type FetchLike as F, type IdentifierType as I, type PublicKeyAuth as P, type SupportedLocale as S, type TokenProviderAuth as T, type UpsertSessionResponse as U, type WidgetCopyPlaceholderValues as W, type ConsentCopyFormat as a, type ConsentSessionIdentifier as b, type UpsertSessionInput as c, type Channel as d, type SessionIds as e, type SubmitSessionInput as f, type CustomerApiAuth as g, type UnsafeServerKeyAuth as h, type ConsentItem as i, type ConsentType as j, type ConsentWidgetConfig as k, type CustomPlatformCheckoutSubmitDetails as l, SUPPORTED_LOCALES as m, type ServerKeyAuth as n, type SubmitConsentSessionUser as o, type ServerUpsertSessionInput as p };
|
package/package.json
CHANGED
|
@@ -1,6 +1,85 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dataships/sdk",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "Dataships client SDK — transport and consent-session lifecycle for the Dataships consent-session API. Platform-agnostic core with adapters per integration (Shopify checkout, Salesforce, custom platform, …).",
|
|
5
|
+
"private": false,
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"author": "Dataships",
|
|
8
|
+
"homepage": "https://dataships.io",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://gitlab.com/dataships/platform/dataships-sdk.git"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"sideEffects": false,
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"LICENSE",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"main": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"unpkg": "./dist/dataships.min.js",
|
|
23
|
+
"jsdelivr": "./dist/dataships.min.js",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./server": {
|
|
30
|
+
"types": "./dist/server.d.ts",
|
|
31
|
+
"import": "./dist/server.js"
|
|
32
|
+
},
|
|
33
|
+
"./adapters/shopify-checkout": {
|
|
34
|
+
"types": "./dist/adapters/shopify-checkout/index.d.ts",
|
|
35
|
+
"import": "./dist/adapters/shopify-checkout/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./adapters/salesforce": {
|
|
38
|
+
"types": "./dist/adapters/salesforce/index.d.ts",
|
|
39
|
+
"import": "./dist/adapters/salesforce/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./adapters/custom-platform-checkout": {
|
|
42
|
+
"types": "./dist/adapters/custom-platform-checkout/index.d.ts",
|
|
43
|
+
"import": "./dist/adapters/custom-platform-checkout/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./adapters/custom-platform-signup": {
|
|
46
|
+
"types": "./dist/adapters/custom-platform-signup/index.d.ts",
|
|
47
|
+
"import": "./dist/adapters/custom-platform-signup/index.js"
|
|
48
|
+
},
|
|
49
|
+
"./package.json": "./package.json"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "rm -rf dist && tsup && node scripts/integrity.mjs",
|
|
53
|
+
"dev": "tsup --watch",
|
|
54
|
+
"typecheck": "tsc --noEmit",
|
|
55
|
+
"lint": "eslint \"src/**/*.ts\" \"tests/**/*.ts\"",
|
|
56
|
+
"test": "vitest",
|
|
57
|
+
"test:once": "vitest run",
|
|
58
|
+
"test:ci": "vitest run --coverage.enabled --reporter=junit --outputFile=./junit.xml",
|
|
59
|
+
"prepublishOnly": "yarn build",
|
|
60
|
+
"check:package": "sh scripts/check-package.sh",
|
|
61
|
+
"smoke:cdn": "node scripts/smoke-cdn.mjs",
|
|
62
|
+
"verify:npm": "sh scripts/verify-npm.sh"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@arethetypeswrong/cli": "^0.18.5",
|
|
66
|
+
"@types/node": "^20.12.11",
|
|
67
|
+
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
|
68
|
+
"@typescript-eslint/parser": "^7.0.0",
|
|
69
|
+
"@vitest/coverage-v8": "^3.2.6",
|
|
70
|
+
"eslint": "^8.57.0",
|
|
71
|
+
"jsdom": "^24.0.0",
|
|
72
|
+
"msw": "^2.4.0",
|
|
73
|
+
"publint": "^0.3.25",
|
|
74
|
+
"tsup": "^8.3.0",
|
|
75
|
+
"typescript": "^5.4.0",
|
|
76
|
+
"vitest": "^3.2.6"
|
|
77
|
+
},
|
|
78
|
+
"packageManager": "yarn@1.22.22",
|
|
79
|
+
"engines": {
|
|
80
|
+
"node": ">=20"
|
|
81
|
+
},
|
|
82
|
+
"publishConfig": {
|
|
83
|
+
"access": "public"
|
|
84
|
+
}
|
|
85
|
+
}
|