@cowliss/sdk 0.16.0 → 0.18.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 +19 -0
- package/README.md +22 -4
- package/dist/index.d.ts +15 -4
- package/dist/index.js +16 -3
- package/dist/types.d.ts +32 -8
- package/dist/version.autogenerated.d.ts +1 -1
- package/dist/version.autogenerated.js +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
<!-- GENERATED by `pnpm release` from the commit log (apps/docs/scripts/changelog.ts). Do not edit. -->
|
|
4
|
+
|
|
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
|
+
|
|
7
|
+
## 0.18.0 (2026-10-01)
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
- cow.preferences.link asks for one profile's email preferences page
|
|
12
|
+
|
|
13
|
+
## 0.17.0 (2026-10-01)
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
- **Emails:** cow.emails.send can address a profile instead of an address
|
|
18
|
+
- Identify takes consent by purpose path, such as "marketing.newsletter"
|
|
19
|
+
- A changelog in each package and on the docs site
|
package/README.md
CHANGED
|
@@ -36,19 +36,37 @@ await cow.track({
|
|
|
36
36
|
});
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Send a
|
|
40
|
-
|
|
39
|
+
Send a message from your own code, with a template you pushed or a body
|
|
40
|
+
written inline. Address an email address for mail nobody can turn off, such
|
|
41
|
+
as a receipt, or a profile for mail its recipient can, such as a weekly
|
|
42
|
+
report:
|
|
41
43
|
|
|
42
44
|
```ts
|
|
43
45
|
await cow.emails.send({
|
|
44
46
|
to: "ada@example.com",
|
|
47
|
+
from: "Acme <hello@acme.com>",
|
|
45
48
|
template: { key: "receipt", props: { orderId: "A-2291" } },
|
|
46
49
|
});
|
|
50
|
+
|
|
51
|
+
await cow.emails.send({
|
|
52
|
+
to: { userId: "shop_1" },
|
|
53
|
+
from: "Acme <hello@acme.com>",
|
|
54
|
+
template: { key: "weekly-report", props: { visits: 120 } },
|
|
55
|
+
});
|
|
47
56
|
```
|
|
48
57
|
|
|
49
58
|
It resolves once the message has been handed over, and answers with the
|
|
50
|
-
delivery id.
|
|
51
|
-
|
|
59
|
+
delivery id. A message to a profile goes to its `email` trait, skips anyone
|
|
60
|
+
who turned that purpose off, and carries an unsubscribe link. Mail that
|
|
61
|
+
follows a rule or a wait belongs in a journey.
|
|
62
|
+
|
|
63
|
+
Send someone to their hosted email preferences page from your own "Manage
|
|
64
|
+
email preferences" button. The link works for an hour, so ask for it on the
|
|
65
|
+
click:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const { url, expiresAt } = await cow.preferences.link({ to: { userId: "shop_1" } });
|
|
69
|
+
```
|
|
52
70
|
|
|
53
71
|
Every call carries `identifiers`, a map from kind to value. Cowliss generates
|
|
54
72
|
the profile id and resolves the map to it, so a call that carries two
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BatchBody, BatchResultDto, ErrorCode, EventDto, IdentifyInput, ProfileDto, SendEmailInput, SendEmailResult, TrackInput } from "./types.js";
|
|
1
|
+
import type { BatchBody, BatchResultDto, ErrorCode, EventDto, IdentifyInput, PreferencesLink, PreferencesLinkInput, ProfileDto, SendEmailInput, SendEmailResult, 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:
|
|
@@ -90,9 +90,11 @@ export declare class Cow {
|
|
|
90
90
|
*/
|
|
91
91
|
track(input: WithDefaultSource<TrackInput>): Promise<EventDto>;
|
|
92
92
|
/**
|
|
93
|
-
* The
|
|
94
|
-
*
|
|
95
|
-
*
|
|
93
|
+
* The send a developer's own code makes: a receipt, a password reset, an
|
|
94
|
+
* export that is ready, a weekly report. Address an address for mail
|
|
95
|
+
* nobody can turn off, or a profile (`to: { userId }`) for mail its
|
|
96
|
+
* recipient can, which then asks their consent and carries an unsubscribe
|
|
97
|
+
* link. Mail that follows a rule or a wait belongs in a journey.
|
|
96
98
|
*
|
|
97
99
|
* Synchronous like the rest of the client: the promise resolves once the
|
|
98
100
|
* message has been handed over, and `deliveryId` is the row that records
|
|
@@ -101,6 +103,15 @@ export declare class Cow {
|
|
|
101
103
|
emails: {
|
|
102
104
|
send: (input: WithDefaultSource<SendEmailInput>) => Promise<SendEmailResult>;
|
|
103
105
|
};
|
|
106
|
+
/**
|
|
107
|
+
* A link to one person's hosted email preferences page, for your app's own
|
|
108
|
+
* "Manage email preferences" button: `to` is one identifier naming them,
|
|
109
|
+
* as in `emails.send`. The page lists every purpose their app declares as
|
|
110
|
+
* a switch, and the link works for an hour, so ask for it when they click.
|
|
111
|
+
*/
|
|
112
|
+
preferences: {
|
|
113
|
+
link: (input: WithDefaultSource<PreferencesLinkInput>) => Promise<PreferencesLink>;
|
|
114
|
+
};
|
|
104
115
|
/**
|
|
105
116
|
* Batch import: one source's identify and track calls in one request.
|
|
106
117
|
* Track items must carry an explicit messageId: the API requires it and
|
package/dist/index.js
CHANGED
|
@@ -112,9 +112,11 @@ export class Cow {
|
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
114
|
/**
|
|
115
|
-
* The
|
|
116
|
-
*
|
|
117
|
-
*
|
|
115
|
+
* The send a developer's own code makes: a receipt, a password reset, an
|
|
116
|
+
* export that is ready, a weekly report. Address an address for mail
|
|
117
|
+
* nobody can turn off, or a profile (`to: { userId }`) for mail its
|
|
118
|
+
* recipient can, which then asks their consent and carries an unsubscribe
|
|
119
|
+
* link. Mail that follows a rule or a wait belongs in a journey.
|
|
118
120
|
*
|
|
119
121
|
* Synchronous like the rest of the client: the promise resolves once the
|
|
120
122
|
* message has been handed over, and `deliveryId` is the row that records
|
|
@@ -125,6 +127,17 @@ export class Cow {
|
|
|
125
127
|
data: { ...input, sourceId: this.#sourceFor(input) },
|
|
126
128
|
})),
|
|
127
129
|
};
|
|
130
|
+
/**
|
|
131
|
+
* A link to one person's hosted email preferences page, for your app's own
|
|
132
|
+
* "Manage email preferences" button: `to` is one identifier naming them,
|
|
133
|
+
* as in `emails.send`. The page lists every purpose their app declares as
|
|
134
|
+
* a switch, and the link works for an hour, so ask for it when they click.
|
|
135
|
+
*/
|
|
136
|
+
preferences = {
|
|
137
|
+
link: (input) => this.#watch(async () => this.#post("/v1/preferences-links", {
|
|
138
|
+
data: { ...input, sourceId: this.#sourceFor(input) },
|
|
139
|
+
})),
|
|
140
|
+
};
|
|
128
141
|
/**
|
|
129
142
|
* Batch import: one source's identify and track calls in one request.
|
|
130
143
|
* Track items must carry an explicit messageId: the API requires it and
|
package/dist/types.d.ts
CHANGED
|
@@ -57,10 +57,13 @@ export type EventDto = {
|
|
|
57
57
|
receivedAt: string;
|
|
58
58
|
messageId: string | null;
|
|
59
59
|
};
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
/**
|
|
61
|
+
* A purpose path: one of the two roots, or a name your app's `cow.json`
|
|
62
|
+
* declares under one, such as `"marketing.newsletter"`.
|
|
63
|
+
*/
|
|
64
|
+
export type PurposePath = "marketing" | "transactional" | `marketing.${string}` | `transactional.${string}`;
|
|
65
|
+
/** What a person agreed to, per purpose path, as a caller patches it. */
|
|
66
|
+
export type ConsentPatch = Partial<Record<PurposePath, boolean>>;
|
|
64
67
|
export type IdentifyInput = {
|
|
65
68
|
sourceId: string;
|
|
66
69
|
identifiers: Identifiers;
|
|
@@ -69,8 +72,9 @@ export type IdentifyInput = {
|
|
|
69
72
|
* What this person agreed to, as a merge patch: a purpose the call omits
|
|
70
73
|
* keeps the value it had, so a later identify is never an accidental
|
|
71
74
|
* revocation. Omitting it entirely leaves consent untouched, which on a
|
|
72
|
-
* first write means marketing
|
|
73
|
-
* one
|
|
75
|
+
* first write means every marketing purpose off and every transactional
|
|
76
|
+
* one on. A name your app does not declare is refused. At least one
|
|
77
|
+
* purpose when present.
|
|
74
78
|
*/
|
|
75
79
|
consent?: ConsentPatch;
|
|
76
80
|
/** ISO 8601 UTC. A past timestamp backdates a first-write profile. */
|
|
@@ -125,10 +129,18 @@ export type BatchItemResult = {
|
|
|
125
129
|
export type BatchResultDto = {
|
|
126
130
|
results: BatchItemResult[];
|
|
127
131
|
};
|
|
128
|
-
/** One
|
|
132
|
+
/** One email: a pushed template, or a body written inline. */
|
|
129
133
|
export type SendEmailInput = {
|
|
130
134
|
sourceId: string;
|
|
131
|
-
|
|
135
|
+
/**
|
|
136
|
+
* An address or a list of them, or exactly one identifier naming a profile
|
|
137
|
+
* in the source's app, such as `{ userId: "shop_1" }`. A profile is mailed at
|
|
138
|
+
* its `email` trait and is the only recipient a template with a purpose
|
|
139
|
+
* they can turn off may go to; a bare address takes bare `transactional`
|
|
140
|
+
* templates and inline bodies alone. `cc` and `bcc` are refused beside a
|
|
141
|
+
* profile.
|
|
142
|
+
*/
|
|
143
|
+
to: string | string[] | Identifiers;
|
|
132
144
|
cc?: string | string[];
|
|
133
145
|
bcc?: string | string[];
|
|
134
146
|
replyTo?: string | string[];
|
|
@@ -149,6 +161,18 @@ export type SendEmailResult = {
|
|
|
149
161
|
/** The delivery this send left behind: the row in Deliveries. */
|
|
150
162
|
deliveryId: string;
|
|
151
163
|
};
|
|
164
|
+
/** One profile, named the way a send to a profile names it. */
|
|
165
|
+
export type PreferencesLinkInput = {
|
|
166
|
+
sourceId: string;
|
|
167
|
+
/** Exactly one identifier naming a profile in the source's app. */
|
|
168
|
+
to: Identifiers;
|
|
169
|
+
};
|
|
170
|
+
export type PreferencesLink = {
|
|
171
|
+
/** The hosted preferences page for that profile. */
|
|
172
|
+
url: string;
|
|
173
|
+
/** ISO 8601: when the link stops working, an hour after it was minted. */
|
|
174
|
+
expiresAt: string;
|
|
175
|
+
};
|
|
152
176
|
/**
|
|
153
177
|
* The two runtime constants in this file, and the reason they live beside
|
|
154
178
|
* the types rather than in `@cowliss/shared`: this module is the SDK's one
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "0.
|
|
1
|
+
export declare const SDK_VERSION = "0.18.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.18.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cowliss/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
"files": [
|
|
31
31
|
"dist",
|
|
32
32
|
"LICENSE",
|
|
33
|
-
"README.md"
|
|
33
|
+
"README.md",
|
|
34
|
+
"CHANGELOG.md"
|
|
34
35
|
],
|
|
35
36
|
"scripts": {
|
|
36
37
|
"build": "tsx scripts/version.ts && tsc -b tsconfig.json --force",
|