@cowliss/sdk 0.18.0 → 0.19.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/CHANGELOG.md +13 -0
- package/dist/index.d.ts +21 -7
- package/dist/index.js +24 -10
- package/dist/types.d.ts +23 -0
- package/dist/version.autogenerated.d.ts +1 -1
- package/dist/version.autogenerated.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@
|
|
|
4
4
|
|
|
5
5
|
What changed in each version of `@cowliss/sdk` after 0.16.0, newest first. Earlier versions are listed on [npm](https://www.npmjs.com/package/@cowliss/sdk?activeTab=versions).
|
|
6
6
|
|
|
7
|
+
## 0.19.0 (2026-10-02)
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
- emails.send takes an idempotencyKey and creates the person it emails
|
|
12
|
+
- cow.preferences.get and set, the hosted preferences page as data
|
|
13
|
+
|
|
14
|
+
## 0.18.1 (2026-10-01)
|
|
15
|
+
|
|
16
|
+
### Fixes
|
|
17
|
+
|
|
18
|
+
- A retried emails.send carries one Idempotency-Key, so it never sends twice
|
|
19
|
+
|
|
7
20
|
## 0.18.0 (2026-10-01)
|
|
8
21
|
|
|
9
22
|
### Features
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BatchBody, BatchResultDto, ErrorCode, EventDto, IdentifyInput, PreferencesLink, PreferencesLinkInput, ProfileDto, SendEmailInput, SendEmailResult, TrackInput } from "./types.js";
|
|
1
|
+
import type { BatchBody, BatchResultDto, ErrorCode, EventDto, GetPreferencesInput, IdentifyInput, Preferences, PreferencesLink, PreferencesLinkInput, ProfileDto, SendEmailInput, SendEmailResult, SetPreferencesInput, TrackInput } from "./types.js";
|
|
2
2
|
export type * from "./types.js";
|
|
3
3
|
/**
|
|
4
4
|
* The Cowliss TS client SDK. Small typed surface over the ingestion API:
|
|
@@ -98,18 +98,32 @@ export declare class Cow {
|
|
|
98
98
|
*
|
|
99
99
|
* Synchronous like the rest of the client: the promise resolves once the
|
|
100
100
|
* message has been handed over, and `deliveryId` is the row that records
|
|
101
|
-
* what happened to it.
|
|
101
|
+
* what happened to it. Each call carries an Idempotency-Key on every
|
|
102
|
+
* attempt, so a retry after a lost reply answers with the first send's
|
|
103
|
+
* `deliveryId` instead of sending again. Pass your own `idempotencyKey`
|
|
104
|
+
* (an order id, a job id) and a second run of your own code dedupes too;
|
|
105
|
+
* without one, each call is a send of its own.
|
|
106
|
+
*
|
|
107
|
+
* Addressed to `{ email }` that no profile in the app holds yet, the send
|
|
108
|
+
* creates that profile first, as `identify` would.
|
|
102
109
|
*/
|
|
103
110
|
emails: {
|
|
104
|
-
send: (input: WithDefaultSource<SendEmailInput>
|
|
111
|
+
send: ({ idempotencyKey, ...input }: WithDefaultSource<SendEmailInput> & {
|
|
112
|
+
idempotencyKey?: string;
|
|
113
|
+
}) => Promise<SendEmailResult>;
|
|
105
114
|
};
|
|
106
115
|
/**
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
116
|
+
* One person's email preferences, `to` naming them as in `emails.send`.
|
|
117
|
+
*
|
|
118
|
+
* `link` is the hosted page, for a "Manage email preferences" button: it
|
|
119
|
+
* lists every purpose their app declares as a switch, and the link works
|
|
120
|
+
* for an hour, so ask for it when they click. `get` and `set` are the same
|
|
121
|
+
* page as data, for an app that draws its own: `set` saves what the person
|
|
122
|
+
* chose, where `identify({ consent })` records what the app decided.
|
|
111
123
|
*/
|
|
112
124
|
preferences: {
|
|
125
|
+
get: (input: WithDefaultSource<GetPreferencesInput>) => Promise<Preferences>;
|
|
126
|
+
set: (input: WithDefaultSource<SetPreferencesInput>) => Promise<Preferences>;
|
|
113
127
|
link: (input: WithDefaultSource<PreferencesLinkInput>) => Promise<PreferencesLink>;
|
|
114
128
|
};
|
|
115
129
|
/**
|
package/dist/index.js
CHANGED
|
@@ -120,20 +120,34 @@ export class Cow {
|
|
|
120
120
|
*
|
|
121
121
|
* Synchronous like the rest of the client: the promise resolves once the
|
|
122
122
|
* message has been handed over, and `deliveryId` is the row that records
|
|
123
|
-
* what happened to it.
|
|
123
|
+
* what happened to it. Each call carries an Idempotency-Key on every
|
|
124
|
+
* attempt, so a retry after a lost reply answers with the first send's
|
|
125
|
+
* `deliveryId` instead of sending again. Pass your own `idempotencyKey`
|
|
126
|
+
* (an order id, a job id) and a second run of your own code dedupes too;
|
|
127
|
+
* without one, each call is a send of its own.
|
|
128
|
+
*
|
|
129
|
+
* Addressed to `{ email }` that no profile in the app holds yet, the send
|
|
130
|
+
* creates that profile first, as `identify` would.
|
|
124
131
|
*/
|
|
125
132
|
emails = {
|
|
126
|
-
send: (input) => this.#watch(async () => this.#post("/v1/emails", {
|
|
127
|
-
data: { ...input, sourceId: this.#sourceFor(input) },
|
|
128
|
-
})),
|
|
133
|
+
send: ({ idempotencyKey, ...input }) => this.#watch(async () => this.#post("/v1/emails", { data: { ...input, sourceId: this.#sourceFor(input) } }, idempotencyKey ?? crypto.randomUUID())),
|
|
129
134
|
};
|
|
130
135
|
/**
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
136
|
+
* One person's email preferences, `to` naming them as in `emails.send`.
|
|
137
|
+
*
|
|
138
|
+
* `link` is the hosted page, for a "Manage email preferences" button: it
|
|
139
|
+
* lists every purpose their app declares as a switch, and the link works
|
|
140
|
+
* for an hour, so ask for it when they click. `get` and `set` are the same
|
|
141
|
+
* page as data, for an app that draws its own: `set` saves what the person
|
|
142
|
+
* chose, where `identify({ consent })` records what the app decided.
|
|
135
143
|
*/
|
|
136
144
|
preferences = {
|
|
145
|
+
get: (input) => this.#watch(async () => this.#post("/v1/profile-preferences/find", {
|
|
146
|
+
data: { ...input, sourceId: this.#sourceFor(input) },
|
|
147
|
+
})),
|
|
148
|
+
set: (input) => this.#watch(async () => this.#post("/v1/profile-preferences", {
|
|
149
|
+
data: { ...input, sourceId: this.#sourceFor(input) },
|
|
150
|
+
})),
|
|
137
151
|
link: (input) => this.#watch(async () => this.#post("/v1/preferences-links", {
|
|
138
152
|
data: { ...input, sourceId: this.#sourceFor(input) },
|
|
139
153
|
})),
|
|
@@ -164,8 +178,8 @@ export class Cow {
|
|
|
164
178
|
});
|
|
165
179
|
// Reading the body is part of the attempt: an abort or a truncated
|
|
166
180
|
// response mid-read is a transport failure like any other, and
|
|
167
|
-
// retrying it is safe (track
|
|
168
|
-
// upserts on identifiers).
|
|
181
|
+
// retrying it is safe (track and emails.send carry an
|
|
182
|
+
// Idempotency-Key, identify upserts on identifiers).
|
|
169
183
|
if (res.ok) {
|
|
170
184
|
return (await res.json()).data;
|
|
171
185
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -167,6 +167,29 @@ export type PreferencesLinkInput = {
|
|
|
167
167
|
/** Exactly one identifier naming a profile in the source's app. */
|
|
168
168
|
to: Identifiers;
|
|
169
169
|
};
|
|
170
|
+
/** One profile's switches, read or saved from your app's own page. */
|
|
171
|
+
export type GetPreferencesInput = PreferencesLinkInput;
|
|
172
|
+
export type SetPreferencesInput = PreferencesLinkInput & {
|
|
173
|
+
/**
|
|
174
|
+
* The switches to change: `marketing` or a purpose your app declares.
|
|
175
|
+
* Keys left out keep their answer.
|
|
176
|
+
*/
|
|
177
|
+
consent: ConsentPatch;
|
|
178
|
+
};
|
|
179
|
+
/** One switch: `marketing`, or a purpose your app declares. */
|
|
180
|
+
export type Preference = {
|
|
181
|
+
key: string;
|
|
182
|
+
label: string;
|
|
183
|
+
description: string | null;
|
|
184
|
+
/** Whether a send under this purpose would reach them now. */
|
|
185
|
+
enabled: boolean;
|
|
186
|
+
/** Whether they hold their own answer, rather than the default. */
|
|
187
|
+
answered: boolean;
|
|
188
|
+
};
|
|
189
|
+
export type Preferences = {
|
|
190
|
+
/** `marketing` first, then your app's purposes by key. */
|
|
191
|
+
purposes: Preference[];
|
|
192
|
+
};
|
|
170
193
|
export type PreferencesLink = {
|
|
171
194
|
/** The hosted preferences page for that profile. */
|
|
172
195
|
url: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "0.
|
|
1
|
+
export declare const SDK_VERSION = "0.19.0";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by scripts/version.ts from package.json. Do not edit.
|
|
2
|
-
export const SDK_VERSION = "0.
|
|
2
|
+
export const SDK_VERSION = "0.19.0";
|