@clipboard-health/notifications 2.4.15 → 2.4.19

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/README.md CHANGED
@@ -86,9 +86,12 @@ Send notifications through third-party providers.
86
86
  * service instead of this manual calculation.
87
87
  */
88
88
  expiresAt: new Date(Date.now() + 60 * 60_000).toISOString(),
89
- // Set idempotencyKey at enqueue-time so it remains stable across job retries.
90
- idempotencyKey: {
91
- resourceId: "event-123",
89
+ // Set idempotencyKeyParts at enqueue-time so it remains stable across job retries.
90
+ idempotencyKeyParts: {
91
+ resource: {
92
+ type: "account",
93
+ id: "4e3ffeec-1426-4e54-ad28-83246f8f4e7c",
94
+ },
92
95
  },
93
96
  // Set recipients at enqueue-time so they respect our notification provider's limits.
94
97
  recipients: ["userId-1"],
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@clipboard-health/notifications",
3
3
  "description": "Send notifications through third-party providers.",
4
- "version": "2.4.15",
4
+ "version": "2.4.19",
5
5
  "bugs": "https://github.com/ClipboardHealth/core-utils/issues",
6
6
  "dependencies": {
7
- "@clipboard-health/background-jobs-adapter": "1.4.15",
8
- "@clipboard-health/phone-number": "1.4.15",
9
- "@clipboard-health/util-ts": "4.4.15",
7
+ "@clipboard-health/background-jobs-adapter": "1.4.19",
8
+ "@clipboard-health/phone-number": "1.4.19",
9
+ "@clipboard-health/util-ts": "4.4.19",
10
10
  "@knocklabs/node": "1.24.0",
11
11
  "tslib": "2.8.1"
12
12
  },
13
13
  "devDependencies": {
14
- "@clipboard-health/testing-core": "1.4.15",
14
+ "@clipboard-health/testing-core": "1.4.19",
15
15
  "type-fest": "5.2.0"
16
16
  },
17
17
  "keywords": [],
@@ -1,6 +1,6 @@
1
1
  import { type TriggerIdempotencyKeyParams } from "../triggerIdempotencyKey";
2
- interface HashParams extends TriggerIdempotencyKeyParams {
2
+ type HashParams = TriggerIdempotencyKeyParams & {
3
3
  workplaceId?: string | undefined;
4
- }
4
+ };
5
5
  export declare function triggerIdempotencyKeyParamsToHash(params: HashParams): string;
6
6
  export {};
@@ -10,7 +10,11 @@ function toSorted(params) {
10
10
  chunk: params.chunk,
11
11
  eventOccurredAt: params.eventOccurredAt,
12
12
  recipients: [...params.recipients].sort(),
13
- resourceId: params.resourceId,
13
+ resourceId: "resourceId" in params
14
+ ? params.resourceId
15
+ : "resource" in params && params.resource && "id" in params.resource
16
+ ? params.resource.id
17
+ : undefined,
14
18
  workflowKey: params.workflowKey,
15
19
  workplaceId: params.workplaceId,
16
20
  };
@@ -1 +1 @@
1
- {"version":3,"file":"triggerIdempotencyKeyParamsToHash.js","sourceRoot":"","sources":["../../../../../../packages/notifications/src/lib/internal/triggerIdempotencyKeyParamsToHash.ts"],"names":[],"mappings":";;AAOA,8EAEC;AARD,uEAAoE;AAMpE,SAAgB,iCAAiC,CAAC,MAAkB;IAClE,OAAO,IAAA,iDAAuB,EAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,QAAQ,CAAC,MAAkB;IAClC,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,UAAU,EAAE,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE;QACzC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"triggerIdempotencyKeyParamsToHash.js","sourceRoot":"","sources":["../../../../../../packages/notifications/src/lib/internal/triggerIdempotencyKeyParamsToHash.ts"],"names":[],"mappings":";;AAOA,8EAEC;AARD,uEAAoE;AAMpE,SAAgB,iCAAiC,CAAC,MAAkB;IAClE,OAAO,IAAA,iDAAuB,EAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,QAAQ,CAAC,MAAkB;IAClC,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,UAAU,EAAE,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE;QACzC,UAAU,EACR,YAAY,IAAI,MAAM;YACpB,CAAC,CAAC,MAAM,CAAC,UAAU;YACnB,CAAC,CAAC,UAAU,IAAI,MAAM,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ;gBAClE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE;gBACpB,CAAC,CAAC,SAAS;QACjB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC;AACJ,CAAC"}
@@ -1,7 +1,14 @@
1
1
  import { type BackgroundJobsAdapter, type EnqueueOptions, type MongoEnqueueOptions, type PostgresEnqueueOptions } from "@clipboard-health/background-jobs-adapter";
2
2
  import { type TriggerIdempotencyKey } from "./triggerIdempotencyKey";
3
3
  type EnqueueParameters = Parameters<BackgroundJobsAdapter["enqueue"]>;
4
+ /**
5
+ * @deprecated Use `IdempotencyKeyParts` instead.
6
+ */
4
7
  export interface IdempotencyKey {
8
+ eventOccurredAt?: string | undefined;
9
+ resourceId?: string | undefined;
10
+ }
11
+ export type IdempotencyKeyParts = {
5
12
  /**
6
13
  * Prefer `resourceId` over `eventOccurredAt`; it's harder to misuse.
7
14
  *
@@ -10,39 +17,49 @@ export interface IdempotencyKey {
10
17
  *
11
18
  * Use `.toISOString()`.
12
19
  */
13
- eventOccurredAt?: string | undefined;
20
+ eventOccurredAt: string;
21
+ resource?: undefined;
22
+ } | {
23
+ eventOccurredAt?: undefined;
14
24
  /**
15
- * If a resource triggered your workflow, include its unique ID.
25
+ * Do not include `workflowKey`, `recipients`, or `workplaceId`; they are included
26
+ * automatically.
16
27
  *
17
- * Note: `workflowKey`, `recipients`, and `workplaceId` (if it exists in the trigger body) are
18
- * included in the idempotency key automatically.
28
+ * If a resource triggered your workflow, include its unique ID.
19
29
  *
20
30
  * @example
21
31
  * 1. For a "meeting starts in one hour" notification, set resourceId to the meeting ID.
22
32
  * 2. For a payout notification, set resourceId to the payment ID.
23
33
  */
24
- resourceId?: string | undefined;
25
- }
34
+ resource: {
35
+ type: string;
36
+ id: string;
37
+ };
38
+ };
26
39
  export interface NotificationEnqueueData {
27
40
  /**
41
+ * @deprecated Use `idempotencyKeyParts` instead.
42
+ */
43
+ idempotencyKey?: IdempotencyKey;
44
+ /**
45
+ * Do not include `workflowKey`, `recipients`, or `workplaceId`; they are included
46
+ * automatically.
47
+ *
28
48
  * Idempotency keys prevent duplicate notifications. They should be deterministic and remain the
29
49
  * same across retry logic.
30
50
  *
31
- * If you retry a request with the same idempotency key within 24 hours, the client returns the same
32
- * response as the original request.
33
- *
34
- * Note: `workflowKey`, `recipients`, and `workplaceId` (if it exists in the trigger body) are
35
- * included in the idempotency key automatically.
51
+ * If you retry a request with the same idempotency key within 24 hours, the client returns the
52
+ * same response as the original request.
36
53
  *
37
54
  * We provide this class because idempotency keys can be difficult to use correctly. If the key
38
- * changes on each retry (e.g., Date.now() or uuid.v4()), it won't prevent duplicate notifications.
39
- * Conversely, if you don't provide enough information, you prevent recipients from receiving
40
- * notifications they otherwise should have. For example, if you use the trigger key and the
41
- * recipient's ID as the idempotency key, but it's possible the recipient could receive the same
42
- * notification multiple times within the idempotency key's validity window, the recipient will only
43
- * receive the first notification.
55
+ * changes on each retry (e.g., Date.now() or uuid.v4()), it won't prevent duplicate
56
+ * notifications. Conversely, if you don't provide enough information, you prevent recipients from
57
+ * receiving notifications they otherwise should have. For example, if you use the trigger key and
58
+ * the recipient's ID as the idempotency key, but it's possible the recipient could receive the
59
+ * same notification multiple times within the idempotency key's validity window, the recipient
60
+ * will only receive the first notification.
44
61
  */
45
- idempotencyKey: IdempotencyKey;
62
+ idempotencyKeyParts?: IdempotencyKeyParts;
46
63
  /** @see {@link TriggerRequest.expiresAt} */
47
64
  expiresAt: string;
48
65
  /** @see {@link TriggerBody.recipients} */
@@ -141,9 +158,12 @@ export declare class NotificationJobEnqueuer {
141
158
  * * service instead of this manual calculation.
142
159
  * *\/
143
160
  * expiresAt: new Date(Date.now() + 60 * 60_000).toISOString(),
144
- * // Set idempotencyKey at enqueue-time so it remains stable across job retries.
145
- * idempotencyKey: {
146
- * resourceId: "event-123",
161
+ * // Set idempotencyKeyParts at enqueue-time so it remains stable across job retries.
162
+ * idempotencyKeyParts: {
163
+ * resource: {
164
+ * type: "account",
165
+ * id: "4e3ffeec-1426-4e54-ad28-83246f8f4e7c",
166
+ * },
147
167
  * },
148
168
  * // Set recipients at enqueue-time so they respect our notification provider's limits.
149
169
  * recipients: ["userId-1"],
@@ -59,9 +59,12 @@ class NotificationJobEnqueuer {
59
59
  * * service instead of this manual calculation.
60
60
  * *\/
61
61
  * expiresAt: new Date(Date.now() + 60 * 60_000).toISOString(),
62
- * // Set idempotencyKey at enqueue-time so it remains stable across job retries.
63
- * idempotencyKey: {
64
- * resourceId: "event-123",
62
+ * // Set idempotencyKeyParts at enqueue-time so it remains stable across job retries.
63
+ * idempotencyKeyParts: {
64
+ * resource: {
65
+ * type: "account",
66
+ * id: "4e3ffeec-1426-4e54-ad28-83246f8f4e7c",
67
+ * },
65
68
  * },
66
69
  * // Set recipients at enqueue-time so they respect our notification provider's limits.
67
70
  * recipients: ["userId-1"],
@@ -84,6 +87,7 @@ class NotificationJobEnqueuer {
84
87
  await Promise.all((0, chunkRecipients_1.chunkRecipients)({ recipients: data.recipients }).map(async ({ number, recipients }) => {
85
88
  const idempotencyKeyParams = {
86
89
  ...data.idempotencyKey,
90
+ ...data.idempotencyKeyParts,
87
91
  chunk: number,
88
92
  recipients,
89
93
  workflowKey: data.workflowKey,
@@ -1 +1 @@
1
- {"version":3,"file":"notificationJobEnqueuer.js","sourceRoot":"","sources":["../../../../../packages/notifications/src/lib/notificationJobEnqueuer.ts"],"names":[],"mappings":";;;AAAA,uFAMmD;AAEnD,gEAA6D;AAC7D,oGAAiG;AACjG,mEAIiC;AAiHjC,MAAa,uBAAuB;IACjB,OAAO,CAA2C;IAEnE,YAAY,MAAqC;QAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAE3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoEG;IACH,KAAK,CAAC,gBAAgB,CACpB,sBAA4C,EAC5C,IAAkB,EAClB,OAAiC;QAEjC,MAAM,OAAO,CAAC,GAAG,CACf,IAAA,iCAAe,EAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE;YACpF,MAAM,oBAAoB,GAAgC;gBACxD,GAAG,IAAI,CAAC,cAAc;gBACtB,KAAK,EAAE,MAAM;gBACb,UAAU;gBACV,WAAW,EAAE,IAAI,CAAC,WAAW;aAC9B,CAAC;YAEF,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CACxB,sBAAsB,EACtB;gBACE,GAAG,IAAI;gBACP,UAAU;gBACV,cAAc,EAAE,IAAA,yDAAiC,EAAC,oBAAoB,CAAC;aACxE,EACD;gBACE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClC,CAAC,6CAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,cAAc,CAAC,EAC/D,IAAA,qEAAiC,EAAC,oBAAoB,CAAC;aAC1D,CACF,CAAC;QACJ,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;CACF;AA5GD,0DA4GC"}
1
+ {"version":3,"file":"notificationJobEnqueuer.js","sourceRoot":"","sources":["../../../../../packages/notifications/src/lib/notificationJobEnqueuer.ts"],"names":[],"mappings":";;;AAAA,uFAMmD;AAEnD,gEAA6D;AAC7D,oGAAiG;AACjG,mEAIiC;AAoIjC,MAAa,uBAAuB;IACjB,OAAO,CAA2C;IAEnE,YAAY,MAAqC;QAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAE3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuEG;IACH,KAAK,CAAC,gBAAgB,CACpB,sBAA4C,EAC5C,IAAkB,EAClB,OAAiC;QAEjC,MAAM,OAAO,CAAC,GAAG,CACf,IAAA,iCAAe,EAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE;YACpF,MAAM,oBAAoB,GAAgC;gBACxD,GAAG,IAAI,CAAC,cAAc;gBACtB,GAAG,IAAI,CAAC,mBAAmB;gBAC3B,KAAK,EAAE,MAAM;gBACb,UAAU;gBACV,WAAW,EAAE,IAAI,CAAC,WAAW;aAC9B,CAAC;YAEF,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CACxB,sBAAsB,EACtB;gBACE,GAAG,IAAI;gBACP,UAAU;gBACV,cAAc,EAAE,IAAA,yDAAiC,EAAC,oBAAoB,CAAC;aACxE,EACD;gBACE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClC,CAAC,6CAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,cAAc,CAAC,EAC/D,IAAA,qEAAiC,EAAC,oBAAoB,CAAC;aAC1D,CACF,CAAC;QACJ,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;CACF;AAhHD,0DAgHC"}
@@ -1,5 +1,5 @@
1
1
  import { type Tagged } from "type-fest";
2
- import { type IdempotencyKey } from "./notificationJobEnqueuer";
2
+ import { type IdempotencyKey, type IdempotencyKeyParts } from "./notificationJobEnqueuer";
3
3
  /**
4
4
  * Idempotency keys prevent duplicate notifications. `NotificationClient.trigger` should be called
5
5
  * after properly enqueuing a job using `NotificationJobEnqueuer.enqueueOneOrMore` to help ensure
@@ -10,7 +10,7 @@ import { type IdempotencyKey } from "./notificationJobEnqueuer";
10
10
  * unnecessary.
11
11
  */
12
12
  export type TriggerIdempotencyKey = Tagged<string, "TriggerIdempotencyKey">;
13
- export interface TriggerIdempotencyKeyParams extends IdempotencyKey {
13
+ export type TriggerIdempotencyKeyParams = (IdempotencyKey | IdempotencyKeyParts) & {
14
14
  /**
15
15
  * The recipient chunk number.
16
16
  */
@@ -23,7 +23,7 @@ export interface TriggerIdempotencyKeyParams extends IdempotencyKey {
23
23
  * The workflow key.
24
24
  */
25
25
  workflowKey: string;
26
- }
26
+ };
27
27
  /**
28
28
  * Type guard to check if a value is a valid TriggerIdempotencyKeyParams object.
29
29
  */
@@ -1 +1 @@
1
- {"version":3,"file":"triggerIdempotencyKey.js","sourceRoot":"","sources":["../../../../../packages/notifications/src/lib/triggerIdempotencyKey.ts"],"names":[],"mappings":";;AAwCA,sEAeC;AAMD,8EAKC;AAlED,uDAAkD;AAqClD;;GAEG;AACH,SAAgB,6BAA6B,CAC3C,KAAc;IAEd,IAAI,IAAA,eAAK,EAAC,KAAK,CAAC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,MAAM,GAAG,KAAoC,CAAC;IACpD,OAAO,CACL,OAAO,IAAI,MAAM;QACjB,aAAa,IAAI,MAAM;QACvB,YAAY,IAAI,MAAM;QACtB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;QAChC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,SAAS,KAAK,QAAQ,CAAC,CACtE,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,iCAAiC,CAC/C,MAAmC;IAEnC,oEAAoE;IACpE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAA0B,CAAC;AACzD,CAAC"}
1
+ {"version":3,"file":"triggerIdempotencyKey.js","sourceRoot":"","sources":["../../../../../packages/notifications/src/lib/triggerIdempotencyKey.ts"],"names":[],"mappings":";;AAyCA,sEAeC;AAMD,8EAKC;AAnED,uDAAkD;AAsClD;;GAEG;AACH,SAAgB,6BAA6B,CAC3C,KAAc;IAEd,IAAI,IAAA,eAAK,EAAC,KAAK,CAAC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,MAAM,GAAG,KAAoC,CAAC;IACpD,OAAO,CACL,OAAO,IAAI,MAAM;QACjB,aAAa,IAAI,MAAM;QACvB,YAAY,IAAI,MAAM;QACtB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;QAChC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,SAAS,KAAK,QAAQ,CAAC,CACtE,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,iCAAiC,CAC/C,MAAmC;IAEnC,oEAAoE;IACpE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAA0B,CAAC;AACzD,CAAC"}