@clipboard-health/notifications 0.3.1 → 0.3.2

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 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.3.1",
4
+ "version": "0.3.2",
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
@@ -1,5 +1,5 @@
1
1
  export * from "./lib/chunkRecipients";
2
- export * from "./lib/createDeterministicHash";
2
+ export * from "./lib/createIdempotencyKey";
3
3
  export * from "./lib/errorsInResult";
4
4
  export * from "./lib/notificationClient";
5
5
  export * from "./lib/types";
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/createDeterministicHash"), exports);
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,wEAA8C;AAC9C,+DAAqC;AACrC,mEAAyC;AACzC,sDAA4B"}
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"}
@@ -125,7 +125,12 @@ export interface TriggerRequest {
125
125
  body: TriggerBody;
126
126
  /**
127
127
  * Key to prevent duplicate requests if provider supports it. It's important it is deterministic
128
- * and remains the same across any retry logic.
128
+ * ({@link createIdempotencyKey}) and remains the same across any retry logic.
129
+ *
130
+ * Ensure your idempotency key doesn't prevent recipients from receiving notifications. For
131
+ * example, if you use the workflow key and the recipient's ID as the idempotency key, but it's
132
+ * possible the recipient could receive the notification multiple times within the idempotency
133
+ * key's validity window, the recipient will only receive the first notification.
129
134
  */
130
135
  idempotencyKey: string;
131
136
  /** 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"}