@ingram-tech/nk-marketing 0.2.3 → 0.3.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/dist/client.d.ts.map +1 -1
- package/dist/client.js +21 -4
- package/dist/client.js.map +1 -1
- package/dist/db.d.ts +2 -0
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +11 -0
- package/dist/db.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +4 -1
- package/dist/render.js.map +1 -1
- package/dist/wire.d.ts +35 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +45 -0
- package/dist/wire.js.map +1 -0
- package/package.json +3 -3
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAA+C,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AACtF,OAAO,EAEN,KAAK,oBAAoB,EAGzB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACX,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,OAAO,EACP,eAAe,EACf,gBAAgB,EAChB,eAAe,EAEf,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,eAAe;IAC/B,+EAA+E;IAC/E,EAAE,EAAE,SAAS,CAAC;IACd,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACzE;AAKD,eAAO,MAAM,eAAe,GAAI,QAAQ,eAAe;wBAiBrB,eAAe,KAAG,OAAO,CAAC,OAAO,CAAC;8BAmB5B,MAAM,KAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;yBAoBtC,gBAAgB,KAAG,OAAO,CAAC,YAAY,CAAC;yBA4CxC,MAAM,KAAG,OAAO,CAAC,iBAAiB,CAAC;6BA8F3D,gBAAgB,KACvB,OAAO,CAAC,eAAe,CAAC;6BA2FjB,gBAAgB,KACvB,OAAO,CAAC,eAAe,CAAC;CAgD3B,CAAC"}
|
package/dist/client.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* unsubscribe, and rendering. The site never re-implements those.
|
|
14
14
|
*/
|
|
15
15
|
import { fromAddress, sendEmail } from "@ingram-tech/nk-email";
|
|
16
|
-
import { generateToken, normalizeEmail } from "./db.js";
|
|
16
|
+
import { generateToken, normalizeEmail, requireEmail } from "./db.js";
|
|
17
17
|
import { derivePreviewText, renderMarketingHtml, renderMarketingText, } from "./render.js";
|
|
18
18
|
/** The bare address inside a "Name <addr>" string (or the string itself). */
|
|
19
19
|
const bareAddress = (from) => from.match(/<([^>]+)>/)?.[1] ?? from;
|
|
@@ -32,7 +32,9 @@ export const createMarketing = (config) => {
|
|
|
32
32
|
* the token. The unit every other call resolves to.
|
|
33
33
|
*/
|
|
34
34
|
const identify = async (options) => {
|
|
35
|
-
|
|
35
|
+
// Validate up front: identify/subscribe emails come straight from user
|
|
36
|
+
// forms, and a raw check-constraint violation is unactionable upstream.
|
|
37
|
+
const email = requireEmail(options.email);
|
|
36
38
|
const { rows } = await db.query(`insert into marketing_contacts (email, user_id, locale, unsubscribe_token)
|
|
37
39
|
values ($1, $2, $3, $4)
|
|
38
40
|
on conflict (email) do update set
|
|
@@ -70,6 +72,15 @@ export const createMarketing = (config) => {
|
|
|
70
72
|
email: options.email,
|
|
71
73
|
userId: options.userId,
|
|
72
74
|
});
|
|
75
|
+
if (contact.unsubscribed_all_at) {
|
|
76
|
+
// An explicit re-subscribe is fresh consent. Without clearing the
|
|
77
|
+
// global opt-out the new subscription looks successful but every
|
|
78
|
+
// broadcast silently excludes the contact forever — undetectable by
|
|
79
|
+
// caller and user alike.
|
|
80
|
+
await db.query(`update marketing_contacts
|
|
81
|
+
set unsubscribed_all_at = null, updated_at = now()
|
|
82
|
+
where id = $1`, [contact.id]);
|
|
83
|
+
}
|
|
73
84
|
const { rows } = await db.query(`insert into marketing_subscriptions (audience_id, contact_id, unsubscribe_token, source)
|
|
74
85
|
values ($1, $2, $3, $4)
|
|
75
86
|
on conflict (audience_id, contact_id) do update set
|
|
@@ -195,7 +206,11 @@ export const createMarketing = (config) => {
|
|
|
195
206
|
}
|
|
196
207
|
catch (err) {
|
|
197
208
|
if (options.campaignKey) {
|
|
198
|
-
|
|
209
|
+
// Best-effort: a throwing release (DB blip) must not escape the
|
|
210
|
+
// per-recipient catch and abort the rest of the batch. If it does
|
|
211
|
+
// fail, the claim wrongly persists and later re-runs will skip
|
|
212
|
+
// this contact — surfaced via the failures list either way.
|
|
213
|
+
await releaseDelivery(options.campaignKey, r.contact_id).catch(() => { });
|
|
199
214
|
}
|
|
200
215
|
result.failedCount += 1;
|
|
201
216
|
result.failures.push({
|
|
@@ -249,7 +264,9 @@ export const createMarketing = (config) => {
|
|
|
249
264
|
});
|
|
250
265
|
}
|
|
251
266
|
catch (err) {
|
|
252
|
-
|
|
267
|
+
// Best-effort: if the release itself throws, the send error (the one
|
|
268
|
+
// the caller can act on) must still propagate, not be masked.
|
|
269
|
+
await releaseDelivery(options.campaignKey, contact.id).catch(() => { });
|
|
253
270
|
throw err;
|
|
254
271
|
}
|
|
255
272
|
return { status: "sent" };
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAkB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/db.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export interface Queryable {
|
|
|
11
11
|
}
|
|
12
12
|
/** Normalise an email for storage and lookup — trimmed + lowercased. */
|
|
13
13
|
export declare const normalizeEmail: (email: string) => string;
|
|
14
|
+
/** Normalise + validate an email; throws a descriptive error on junk input. */
|
|
15
|
+
export declare const requireEmail: (email: string) => string;
|
|
14
16
|
/**
|
|
15
17
|
* A 256-bit random token, hex-encoded, for an unsubscribe link. Generated in
|
|
16
18
|
* app code (not via a pgcrypto column default) so the migration stays
|
package/dist/db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,SAAS;IAGzB,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,GAChB,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,EAAE,CAAA;KAAE,CAAC,CAAC;CAC1B;AAED,wEAAwE;AACxE,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,SAAS;IAGzB,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,GAChB,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,EAAE,CAAA;KAAE,CAAC,CAAC;CAC1B;AAED,wEAAwE;AACxE,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MAAoC,CAAC;AAMpF,+EAA+E;AAC/E,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,MAM5C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,QAAO,MAAyC,CAAC"}
|
package/dist/db.js
CHANGED
|
@@ -7,6 +7,17 @@
|
|
|
7
7
|
import { randomBytes } from "node:crypto";
|
|
8
8
|
/** Normalise an email for storage and lookup — trimmed + lowercased. */
|
|
9
9
|
export const normalizeEmail = (email) => email.trim().toLowerCase();
|
|
10
|
+
// Mirrors the migration's marketing_contacts_email_format check, so form input
|
|
11
|
+
// fails with a clear error here instead of a raw Postgres constraint violation.
|
|
12
|
+
const EMAIL_PATTERN = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
|
13
|
+
/** Normalise + validate an email; throws a descriptive error on junk input. */
|
|
14
|
+
export const requireEmail = (email) => {
|
|
15
|
+
const normalized = normalizeEmail(email);
|
|
16
|
+
if (!EMAIL_PATTERN.test(normalized)) {
|
|
17
|
+
throw new Error(`nk-marketing: invalid email address "${email}"`);
|
|
18
|
+
}
|
|
19
|
+
return normalized;
|
|
20
|
+
};
|
|
10
21
|
/**
|
|
11
22
|
* A 256-bit random token, hex-encoded, for an unsubscribe link. Generated in
|
|
12
23
|
* app code (not via a pgcrypto column default) so the migration stays
|
package/dist/db.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAW1C,wEAAwE;AACxE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAEpF;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAW,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAW1C,wEAAwE;AACxE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAEpF,+EAA+E;AAC/E,gFAAgF;AAChF,MAAM,aAAa,GAAG,4BAA4B,CAAC;AAEnD,+EAA+E;AAC/E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAa,EAAU,EAAE;IACrD,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACzC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,wCAAwC,KAAK,GAAG,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,UAAU,CAAC;AACnB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAW,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { createMarketing, type MarketingConfig } from "./client.js";
|
|
2
2
|
export { type Queryable } from "./db.js";
|
|
3
3
|
export { derivePreviewText, type MarketingRenderInput, renderMarketingHtml, renderMarketingText, } from "./render.js";
|
|
4
|
+
export { subscribeToWire, type WireSubscribeOptions, type WireSubscribeStatus, } from "./wire.js";
|
|
4
5
|
export type { Audience, BroadcastOptions, BroadcastResult, Contact, Cta, IdentifyOptions, LifecycleOptions, LifecycleResult, Sender, SubscribeOptions, Subscription, UnsubscribeResult, } from "./types.js";
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EACN,iBAAiB,EACjB,KAAK,oBAAoB,EACzB,mBAAmB,EACnB,mBAAmB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EACX,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,OAAO,EACP,GAAG,EACH,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,MAAM,EACN,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,GACjB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EACN,iBAAiB,EACjB,KAAK,oBAAoB,EACzB,mBAAmB,EACnB,mBAAmB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,GACxB,MAAM,WAAW,CAAC;AACnB,YAAY,EACX,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,OAAO,EACP,GAAG,EACH,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,MAAM,EACN,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,GACjB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAwB,MAAM,aAAa,CAAC;AAEpE,OAAO,EACN,iBAAiB,EAEjB,mBAAmB,EACnB,mBAAmB,GACnB,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAwB,MAAM,aAAa,CAAC;AAEpE,OAAO,EACN,iBAAiB,EAEjB,mBAAmB,EACnB,mBAAmB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,eAAe,GAGf,MAAM,WAAW,CAAC"}
|
package/dist/render.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEtC,4EAA4E;AAC5E,MAAM,WAAW,oBAAoB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;IACjB,6DAA6D;IAC7D,cAAc,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,2CAA2C;AAC3C,eAAO,MAAM,mBAAmB,GAAI,OAAO,oBAAoB,KAAG,MAuBjE,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,mBAAmB,GAAI,OAAO,oBAAoB,KAAG,MAGgC,CAAC;AAEnG,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,KAAG,
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEtC,4EAA4E;AAC5E,MAAM,WAAW,oBAAoB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;IACjB,6DAA6D;IAC7D,cAAc,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,2CAA2C;AAC3C,eAAO,MAAM,mBAAmB,GAAI,OAAO,oBAAoB,KAAG,MAuBjE,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,mBAAmB,GAAI,OAAO,oBAAoB,KAAG,MAGgC,CAAC;AAEnG,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,KAAG,MAUnD,CAAC"}
|
package/dist/render.js
CHANGED
|
@@ -35,6 +35,9 @@ export const derivePreviewText = (content) => {
|
|
|
35
35
|
.find((line) => line.length > 0);
|
|
36
36
|
if (!first)
|
|
37
37
|
return "";
|
|
38
|
-
|
|
38
|
+
// Slice by code points, not UTF-16 units — a cut inside an emoji's
|
|
39
|
+
// surrogate pair would put U+FFFD in the inbox preview.
|
|
40
|
+
const points = [...first];
|
|
41
|
+
return points.length > 140 ? `${points.slice(0, 137).join("")}…` : first;
|
|
39
42
|
};
|
|
40
43
|
//# sourceMappingURL=render.js.map
|
package/dist/render.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAqBnD,2CAA2C;AAC3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAA2B,EAAU,EAAE;IAC1E,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO;SAC9B,KAAK,CAAC,SAAS,CAAC;SAChB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CACH,CAAC,CAAC,EAAE,EAAE,CACL,+CAA+C,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAC3F;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG;QACpB,CAAC,CAAC,sCAAsC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,uHAAuH,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU;QAC9N,CAAC,CAAC,EAAE,CAAC;IAEN,OAAO;0DACkD,UAAU,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC;8CAC/C,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC;EACrE,UAAU;EACV,GAAG;;sEAEiE,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,UAAU,CAAC,KAAK,CAAC,cAAc,CAAC;eACnI,CAAC;AAChB,CAAC,CAAC;AAEF,6DAA6D;AAC7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAA2B,EAAU,EAAE,CAC1E,GAAG,KAAK,CAAC,OAAO,OAAO,KAAK,CAAC,OAAO,OACnC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAC3D,sCAAsC,KAAK,CAAC,YAAY,mBAAmB,KAAK,CAAC,cAAc,EAAE,CAAC;AAEnG,gFAAgF;AAChF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAe,EAAU,EAAE;IAC5D,MAAM,KAAK,GAAG,OAAO;SACnB,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAqBnD,2CAA2C;AAC3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAA2B,EAAU,EAAE;IAC1E,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO;SAC9B,KAAK,CAAC,SAAS,CAAC;SAChB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CACH,CAAC,CAAC,EAAE,EAAE,CACL,+CAA+C,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAC3F;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG;QACpB,CAAC,CAAC,sCAAsC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,uHAAuH,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU;QAC9N,CAAC,CAAC,EAAE,CAAC;IAEN,OAAO;0DACkD,UAAU,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC;8CAC/C,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC;EACrE,UAAU;EACV,GAAG;;sEAEiE,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,UAAU,CAAC,KAAK,CAAC,cAAc,CAAC;eACnI,CAAC;AAChB,CAAC,CAAC;AAEF,6DAA6D;AAC7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAA2B,EAAU,EAAE,CAC1E,GAAG,KAAK,CAAC,OAAO,OAAO,KAAK,CAAC,OAAO,OACnC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAC3D,sCAAsC,KAAK,CAAC,YAAY,mBAAmB,KAAK,CAAC,cAAc,EAAE,CAAC;AAEnG,gFAAgF;AAChF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAe,EAAU,EAAE;IAC5D,MAAM,KAAK,GAAG,OAAO;SACnB,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,mEAAmE;IACnE,wDAAwD;IACxD,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IAC1B,OAAO,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;AAC1E,CAAC,CAAC"}
|
package/dist/wire.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client for Wire (wire.ingram.tech) — the central multi-tenant newsletter
|
|
3
|
+
* service. A site forwards a signup to Wire with its tenant API key
|
|
4
|
+
* (`WIRE_API_KEY`, server-side only); the key resolves the tenant, and the
|
|
5
|
+
* signup lands on that tenant's list. Zero-dependency (global `fetch`), so any
|
|
6
|
+
* consumer can call it without pulling Wire's own stack.
|
|
7
|
+
*
|
|
8
|
+
* Keep the send best-effort at the call site — a Wire outage must never break
|
|
9
|
+
* the site's own signup flow:
|
|
10
|
+
*
|
|
11
|
+
* import { subscribeToWire } from "@ingram-tech/nk-marketing";
|
|
12
|
+
* await subscribeToWire({ email, source: "ingram.tech" }).catch((e) =>
|
|
13
|
+
* console.error("Wire forward failed:", e));
|
|
14
|
+
*/
|
|
15
|
+
export interface WireSubscribeOptions {
|
|
16
|
+
email: string;
|
|
17
|
+
/** List slug within the tenant. Defaults to `WIRE_LIST`, then "newsletter". */
|
|
18
|
+
list?: string;
|
|
19
|
+
/** Attribution for where the signup came from. */
|
|
20
|
+
source?: string;
|
|
21
|
+
/** Hold the subscription pending an emailed confirm link (double opt-in). */
|
|
22
|
+
doubleOptIn?: boolean;
|
|
23
|
+
/** Tenant API key. Defaults to `process.env.WIRE_API_KEY`. */
|
|
24
|
+
apiKey?: string;
|
|
25
|
+
/** Wire base URL. Defaults to `WIRE_BASE_URL`, then https://wire.ingram.tech. */
|
|
26
|
+
baseUrl?: string;
|
|
27
|
+
}
|
|
28
|
+
export type WireSubscribeStatus = "subscribed" | "pending" | "already";
|
|
29
|
+
/**
|
|
30
|
+
* Forward a signup to Wire. Returns the resulting status, or `null` when no API
|
|
31
|
+
* key is configured (so a site with Wire unset simply no-ops). Throws on a
|
|
32
|
+
* transport/HTTP error — wrap at the call site to keep it best-effort.
|
|
33
|
+
*/
|
|
34
|
+
export declare function subscribeToWire(opts: WireSubscribeOptions): Promise<WireSubscribeStatus | null>;
|
|
35
|
+
//# sourceMappingURL=wire.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../src/wire.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;AAEvE;;;;GAIG;AACH,wBAAsB,eAAe,CACpC,IAAI,EAAE,oBAAoB,GACxB,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CA2BrC"}
|
package/dist/wire.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client for Wire (wire.ingram.tech) — the central multi-tenant newsletter
|
|
3
|
+
* service. A site forwards a signup to Wire with its tenant API key
|
|
4
|
+
* (`WIRE_API_KEY`, server-side only); the key resolves the tenant, and the
|
|
5
|
+
* signup lands on that tenant's list. Zero-dependency (global `fetch`), so any
|
|
6
|
+
* consumer can call it without pulling Wire's own stack.
|
|
7
|
+
*
|
|
8
|
+
* Keep the send best-effort at the call site — a Wire outage must never break
|
|
9
|
+
* the site's own signup flow:
|
|
10
|
+
*
|
|
11
|
+
* import { subscribeToWire } from "@ingram-tech/nk-marketing";
|
|
12
|
+
* await subscribeToWire({ email, source: "ingram.tech" }).catch((e) =>
|
|
13
|
+
* console.error("Wire forward failed:", e));
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Forward a signup to Wire. Returns the resulting status, or `null` when no API
|
|
17
|
+
* key is configured (so a site with Wire unset simply no-ops). Throws on a
|
|
18
|
+
* transport/HTTP error — wrap at the call site to keep it best-effort.
|
|
19
|
+
*/
|
|
20
|
+
export async function subscribeToWire(opts) {
|
|
21
|
+
const apiKey = opts.apiKey ?? process.env.WIRE_API_KEY;
|
|
22
|
+
if (!apiKey)
|
|
23
|
+
return null;
|
|
24
|
+
const baseUrl = opts.baseUrl ?? process.env.WIRE_BASE_URL ?? "https://wire.ingram.tech";
|
|
25
|
+
const res = await fetch(`${baseUrl}/api/subscribe`, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
headers: {
|
|
28
|
+
authorization: `Bearer ${apiKey}`,
|
|
29
|
+
"content-type": "application/json",
|
|
30
|
+
},
|
|
31
|
+
body: JSON.stringify({
|
|
32
|
+
email: opts.email,
|
|
33
|
+
list: opts.list ?? process.env.WIRE_LIST,
|
|
34
|
+
source: opts.source,
|
|
35
|
+
doubleOptIn: opts.doubleOptIn,
|
|
36
|
+
}),
|
|
37
|
+
});
|
|
38
|
+
if (!res.ok) {
|
|
39
|
+
const detail = await res.text().catch(() => "");
|
|
40
|
+
throw new Error(`Wire subscribe failed: ${res.status} ${detail}`.trim());
|
|
41
|
+
}
|
|
42
|
+
const data = (await res.json().catch(() => ({})));
|
|
43
|
+
return data.status ?? null;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=wire.js.map
|
package/dist/wire.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire.js","sourceRoot":"","sources":["../src/wire.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAkBH;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACpC,IAA0B;IAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IACvD,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,OAAO,GACZ,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,0BAA0B,CAAC;IAEzE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,gBAAgB,EAAE;QACnD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACR,aAAa,EAAE,UAAU,MAAM,EAAE;YACjC,cAAc,EAAE,kBAAkB;SAClC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACpB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS;YACxC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC7B,CAAC;KACF,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAE/C,CAAC;IACF,OAAO,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC;AAC5B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ingram-tech/nk-marketing",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Postgres-backed marketing & lifecycle email: contacts, consent, newsletter audiences, and idempotent triggered campaigns with RFC 8058 one-click unsubscribe. Sends via @ingram-tech/nk-email.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
"test": "vitest run"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@ingram-tech/nk-email": "^0.3.
|
|
32
|
+
"@ingram-tech/nk-email": "^0.3.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@ingram-tech/nk-dev": "0.
|
|
35
|
+
"@ingram-tech/nk-dev": "0.3.0",
|
|
36
36
|
"@types/node": "^26.0.1",
|
|
37
37
|
"typescript": "^6.0.3",
|
|
38
38
|
"vitest": "^4.1.9"
|