@clipboard-health/notifications 0.3.1 → 0.4.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/package.json +1 -1
- package/src/index.d.ts +1 -1
- package/src/index.js +1 -1
- package/src/index.js.map +1 -1
- package/src/lib/createIdempotencyKey.d.ts +15 -0
- package/src/lib/createIdempotencyKey.js +26 -0
- package/src/lib/createIdempotencyKey.js.map +1 -0
- package/src/lib/internal/toKnockBody.js +2 -1
- package/src/lib/internal/toKnockBody.js.map +1 -1
- package/src/lib/types.d.ts +10 -1
- package/src/lib/createDeterministicHash.d.ts +0 -17
- package/src/lib/createDeterministicHash.js +0 -25
- package/src/lib/createDeterministicHash.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clipboard-health/notifications",
|
|
3
3
|
"description": "Send notifications through third-party providers.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"bugs": "https://github.com/ClipboardHealth/core-utils/issues",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@clipboard-health/phone-number": "0.2.2",
|
package/src/index.d.ts
CHANGED
package/src/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
tslib_1.__exportStar(require("./lib/chunkRecipients"), exports);
|
|
5
|
-
tslib_1.__exportStar(require("./lib/
|
|
5
|
+
tslib_1.__exportStar(require("./lib/createIdempotencyKey"), exports);
|
|
6
6
|
tslib_1.__exportStar(require("./lib/errorsInResult"), exports);
|
|
7
7
|
tslib_1.__exportStar(require("./lib/notificationClient"), exports);
|
|
8
8
|
tslib_1.__exportStar(require("./lib/types"), exports);
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/notifications/src/index.ts"],"names":[],"mappings":";;;AAAA,gEAAsC;AACtC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/notifications/src/index.ts"],"names":[],"mappings":";;;AAAA,gEAAsC;AACtC,qEAA2C;AAC3C,+DAAqC;AACrC,mEAAyC;AACzC,sDAA4B"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a deterministic hash for use as an idempotency key.
|
|
3
|
+
*
|
|
4
|
+
* The function sorts `valuesToHash`, generates a SHA-256 hash, prepends the workflow key, and
|
|
5
|
+
* truncates the result to 255 characters maximum.
|
|
6
|
+
*
|
|
7
|
+
* @param params.key - Workflow key to prepend to the hash.
|
|
8
|
+
* @param params.valuesToHash - Array of strings to hash.
|
|
9
|
+
*
|
|
10
|
+
* @returns A hash string prefixed with the workflow key.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createIdempotencyKey(params: {
|
|
13
|
+
key: string;
|
|
14
|
+
valuesToHash: string[];
|
|
15
|
+
}): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createIdempotencyKey = createIdempotencyKey;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const MAX_IDEMPOTENCY_KEY_LENGTH = 255;
|
|
6
|
+
/**
|
|
7
|
+
* Creates a deterministic hash for use as an idempotency key.
|
|
8
|
+
*
|
|
9
|
+
* The function sorts `valuesToHash`, generates a SHA-256 hash, prepends the workflow key, and
|
|
10
|
+
* truncates the result to 255 characters maximum.
|
|
11
|
+
*
|
|
12
|
+
* @param params.key - Workflow key to prepend to the hash.
|
|
13
|
+
* @param params.valuesToHash - Array of strings to hash.
|
|
14
|
+
*
|
|
15
|
+
* @returns A hash string prefixed with the workflow key.
|
|
16
|
+
*/
|
|
17
|
+
function createIdempotencyKey(params) {
|
|
18
|
+
const { key, valuesToHash } = params;
|
|
19
|
+
const hash = (0, node_crypto_1.createHash)("sha256")
|
|
20
|
+
// Unicode code-points for deterministic, locale-independent sorting; don't mutate input array.
|
|
21
|
+
.update(JSON.stringify([...valuesToHash].sort()))
|
|
22
|
+
.digest("hex");
|
|
23
|
+
const result = `${key}${hash}`;
|
|
24
|
+
return result.slice(0, MAX_IDEMPOTENCY_KEY_LENGTH);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=createIdempotencyKey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createIdempotencyKey.js","sourceRoot":"","sources":["../../../../../packages/notifications/src/lib/createIdempotencyKey.ts"],"names":[],"mappings":";;AAeA,oDAUC;AAzBD,6CAAyC;AAEzC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAEvC;;;;;;;;;;GAUG;AACH,SAAgB,oBAAoB,CAAC,MAA+C;IAClF,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAErC,MAAM,IAAI,GAAG,IAAA,wBAAU,EAAC,QAAQ,CAAC;QAC/B,+FAA+F;SAC9F,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;SAChD,MAAM,CAAC,KAAK,CAAC,CAAC;IAEjB,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,IAAI,EAAE,CAAC;IAC/B,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,0BAA0B,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -19,8 +19,9 @@ function toKnockRecipient(recipient) {
|
|
|
19
19
|
return toKnockInlineIdentifyUserRequest(recipient);
|
|
20
20
|
}
|
|
21
21
|
function toKnockInlineIdentifyUserRequest(recipient) {
|
|
22
|
-
const { channelData, createdAt, email, name, phoneNumber, timeZone, userId, ...rest } = recipient;
|
|
22
|
+
const { channelData, createdAt, email, name, phoneNumber, timeZone, userId, customProperties, ...rest } = recipient;
|
|
23
23
|
return {
|
|
24
|
+
...customProperties,
|
|
24
25
|
id: userId,
|
|
25
26
|
...(channelData ? { channel_data: channelData } : {}),
|
|
26
27
|
...(createdAt ? { created_at: createdAt.toISOString() } : {}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toKnockBody.js","sourceRoot":"","sources":["../../../../../../packages/notifications/src/lib/internal/toKnockBody.ts"],"names":[],"mappings":";;AAKA,kCAUC;AAZD,2DAAwD;AAExD,SAAgB,WAAW,CAAC,IAAiB;IAC3C,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;IAE1E,OAAO;QACL,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC;QAC5C,GAAG,IAAI;KACR,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,SAA2B;IACnD,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,gCAAgC,CAAC,SAAS,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,gCAAgC,CACvC,SAAoC;IAEpC,MAAM,
|
|
1
|
+
{"version":3,"file":"toKnockBody.js","sourceRoot":"","sources":["../../../../../../packages/notifications/src/lib/internal/toKnockBody.ts"],"names":[],"mappings":";;AAKA,kCAUC;AAZD,2DAAwD;AAExD,SAAgB,WAAW,CAAC,IAAiB;IAC3C,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;IAE1E,OAAO;QACL,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC;QAC5C,GAAG,IAAI;KACR,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,SAA2B;IACnD,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,gCAAgC,CAAC,SAAS,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,gCAAgC,CACvC,SAAoC;IAEpC,MAAM,EACJ,WAAW,EACX,SAAS,EACT,KAAK,EACL,IAAI,EACJ,WAAW,EACX,QAAQ,EACR,MAAM,EACN,gBAAgB,EAChB,GAAG,IAAI,EACR,GAAG,SAAS,CAAC;IAEd,OAAO;QACL,GAAG,gBAAgB;QACnB,EAAE,EAAE,MAAM;QACV,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAA,qCAAiB,EAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,GAAG,IAAI;KACR,CAAC;AACJ,CAAC"}
|
package/src/lib/types.d.ts
CHANGED
|
@@ -85,6 +85,10 @@ export interface InlineIdentifyUserRequest {
|
|
|
85
85
|
* scheduled notifications.
|
|
86
86
|
*/
|
|
87
87
|
timeZone?: string | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Custom user properties.
|
|
90
|
+
*/
|
|
91
|
+
customProperties?: Record<string, unknown>;
|
|
88
92
|
}
|
|
89
93
|
/**
|
|
90
94
|
* Specifies a recipient in a request. This can either be a user ID or an inline user request.
|
|
@@ -125,7 +129,12 @@ export interface TriggerRequest {
|
|
|
125
129
|
body: TriggerBody;
|
|
126
130
|
/**
|
|
127
131
|
* Key to prevent duplicate requests if provider supports it. It's important it is deterministic
|
|
128
|
-
* and remains the same across any retry logic.
|
|
132
|
+
* ({@link createIdempotencyKey}) and remains the same across any retry logic.
|
|
133
|
+
*
|
|
134
|
+
* Ensure your idempotency key doesn't prevent recipients from receiving notifications. For
|
|
135
|
+
* example, if you use the workflow key and the recipient's ID as the idempotency key, but it's
|
|
136
|
+
* possible the recipient could receive the notification multiple times within the idempotency
|
|
137
|
+
* key's validity window, the recipient will only receive the first notification.
|
|
129
138
|
*/
|
|
130
139
|
idempotencyKey: string;
|
|
131
140
|
/** Array of data keys to redact in logs for privacy. */
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Creates a deterministic hash from `items`.
|
|
3
|
-
*
|
|
4
|
-
* The function sorts the strings, then generates a SHA-256 hash truncated to the specified number
|
|
5
|
-
* of characters.
|
|
6
|
-
*
|
|
7
|
-
* @param params.items - Array of strings or objects with id property to hash.
|
|
8
|
-
* @param params.characters - Number of characters in the resulting hash (default: 32).
|
|
9
|
-
*
|
|
10
|
-
* @returns A hash string of the specified length.
|
|
11
|
-
*/
|
|
12
|
-
export declare function createDeterministicHash(params: {
|
|
13
|
-
items: string[] | Array<{
|
|
14
|
-
id: string;
|
|
15
|
-
}>;
|
|
16
|
-
characters?: number;
|
|
17
|
-
}): string;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createDeterministicHash = createDeterministicHash;
|
|
4
|
-
const node_crypto_1 = require("node:crypto");
|
|
5
|
-
/**
|
|
6
|
-
* Creates a deterministic hash from `items`.
|
|
7
|
-
*
|
|
8
|
-
* The function sorts the strings, then generates a SHA-256 hash truncated to the specified number
|
|
9
|
-
* of characters.
|
|
10
|
-
*
|
|
11
|
-
* @param params.items - Array of strings or objects with id property to hash.
|
|
12
|
-
* @param params.characters - Number of characters in the resulting hash (default: 32).
|
|
13
|
-
*
|
|
14
|
-
* @returns A hash string of the specified length.
|
|
15
|
-
*/
|
|
16
|
-
function createDeterministicHash(params) {
|
|
17
|
-
const { items, characters = 32 } = params;
|
|
18
|
-
const hash = (0, node_crypto_1.createHash)("sha256")
|
|
19
|
-
// Unicode code-points for deterministic, locale-independent sorting.
|
|
20
|
-
.update(JSON.stringify(items.map((item) => (typeof item === "string" ? item : item.id)).sort()))
|
|
21
|
-
.digest("hex");
|
|
22
|
-
const length = Math.max(1, Math.min(characters, hash.length));
|
|
23
|
-
return hash.slice(0, length);
|
|
24
|
-
}
|
|
25
|
-
//# sourceMappingURL=createDeterministicHash.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"createDeterministicHash.js","sourceRoot":"","sources":["../../../../../packages/notifications/src/lib/createDeterministicHash.ts"],"names":[],"mappings":";;AAaA,0DAaC;AA1BD,6CAAyC;AAEzC;;;;;;;;;;GAUG;AACH,SAAgB,uBAAuB,CAAC,MAGvC;IACC,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,EAAE,EAAE,GAAG,MAAM,CAAC;IAE1C,MAAM,IAAI,GAAG,IAAA,wBAAU,EAAC,QAAQ,CAAC;QAC/B,qEAAqE;SACpE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;SAC/F,MAAM,CAAC,KAAK,CAAC,CAAC;IAEjB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9D,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|