@xube/kit-aws-hooks 0.0.33 → 0.0.34

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.
@@ -1 +1,2 @@
1
1
  export declare const WEBHOOK_TABLE_NAME_ENV_VAR = "WEBHOOK_TABLE_NAME";
2
+ export declare const WEBHOOK_TABLE_INVERTED_INDEX_NAME_ENV_VAR = "WEBHOOK_TABLE_INVERTED_INDEX_NAME";
package/dist/constants.js CHANGED
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WEBHOOK_TABLE_NAME_ENV_VAR = void 0;
3
+ exports.WEBHOOK_TABLE_INVERTED_INDEX_NAME_ENV_VAR = exports.WEBHOOK_TABLE_NAME_ENV_VAR = void 0;
4
4
  exports.WEBHOOK_TABLE_NAME_ENV_VAR = "WEBHOOK_TABLE_NAME";
5
+ exports.WEBHOOK_TABLE_INVERTED_INDEX_NAME_ENV_VAR = "WEBHOOK_TABLE_INVERTED_INDEX_NAME";
package/dist/create.js CHANGED
@@ -15,6 +15,8 @@ const createWebhookForAccount = async (request, tableName, log = kit_log_1.XubeL
15
15
  });
16
16
  }
17
17
  const newWebhooks = (0, generate_1.generateWebhookItems)(request);
18
+ //TODO - These webhooks need to be added to the items if they already exist.
19
+ //For now they will just override any existing webhooks.
18
20
  const putWebhookItems = [];
19
21
  for (const webhook of newWebhooks) {
20
22
  putWebhookItems.push((0, kit_aws_1.putItemInTable)(tableName, webhook));
package/dist/generate.js CHANGED
@@ -3,19 +3,29 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateWebhookItems = void 0;
4
4
  const keys_1 = require("./keys");
5
5
  const types_1 = require("./types");
6
+ const kit_aws_1 = require("@xube/kit-aws");
6
7
  const generateWebhookItems = (request) => {
7
- const webhookItems = [];
8
+ const webhookItems = {};
8
9
  for (const endpoint of request.endpoints) {
9
10
  for (const id of request.ids) {
10
- webhookItems.push({
11
- account: request.account,
12
- ...endpoint,
13
- id,
11
+ const key = {
14
12
  PK: (0, keys_1.getWebhookPartitionKey)(request.account),
15
13
  SK: (0, keys_1.getWebhookSortKey)(id, request.type ?? types_1.WebhookTypes.data),
16
- });
14
+ };
15
+ const aggregateKey = (0, kit_aws_1.getAggregateKeyFromTableKey)(key);
16
+ if (!webhookItems[aggregateKey]) {
17
+ webhookItems[aggregateKey] = {
18
+ account: request.account,
19
+ endpoints: [endpoint],
20
+ id,
21
+ ...key,
22
+ };
23
+ }
24
+ else {
25
+ webhookItems[aggregateKey].endpoints.push(endpoint);
26
+ }
17
27
  }
18
28
  }
19
- return webhookItems;
29
+ return Object.values(webhookItems);
20
30
  };
21
31
  exports.generateWebhookItems = generateWebhookItems;
package/dist/index.d.ts CHANGED
@@ -6,4 +6,5 @@ export * from "./create";
6
6
  export * from "./generate";
7
7
  export * from "./get";
8
8
  export * from "./keys";
9
+ export * from "./send";
9
10
  export * from "./types";
package/dist/index.js CHANGED
@@ -23,4 +23,5 @@ __exportStar(require("./create"), exports);
23
23
  __exportStar(require("./generate"), exports);
24
24
  __exportStar(require("./get"), exports);
25
25
  __exportStar(require("./keys"), exports);
26
+ __exportStar(require("./send"), exports);
26
27
  __exportStar(require("./types"), exports);
@@ -1,55 +1,83 @@
1
1
  import { z } from "zod";
2
2
  export declare const WebhookEndpointSchema: z.ZodObject<{
3
- url: z.ZodString;
4
- headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
3
+ endpoints: z.ZodArray<z.ZodObject<{
4
+ url: z.ZodString;
5
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ url: string;
8
+ headers?: Record<string, string> | undefined;
9
+ }, {
10
+ url: string;
11
+ headers?: Record<string, string> | undefined;
12
+ }>, "many">;
5
13
  id: z.ZodString;
6
14
  account: z.ZodString;
7
15
  }, "strip", z.ZodTypeAny, {
8
- url: string;
9
16
  account: string;
17
+ endpoints: {
18
+ url: string;
19
+ headers?: Record<string, string> | undefined;
20
+ }[];
10
21
  id: string;
11
- headers?: Record<string, string> | undefined;
12
22
  }, {
13
- url: string;
14
23
  account: string;
24
+ endpoints: {
25
+ url: string;
26
+ headers?: Record<string, string> | undefined;
27
+ }[];
15
28
  id: string;
16
- headers?: Record<string, string> | undefined;
17
29
  }>;
18
30
  export type WebhookEndpoint = z.infer<typeof WebhookEndpointSchema>;
19
31
  export declare const isWebhookEndpoint: (obj: unknown) => obj is {
20
- url: string;
21
32
  account: string;
33
+ endpoints: {
34
+ url: string;
35
+ headers?: Record<string, string> | undefined;
36
+ }[];
22
37
  id: string;
23
- headers?: Record<string, string> | undefined;
24
38
  };
25
39
  export declare const WebhookEndpointItemSchema: z.ZodObject<{
26
- url: z.ZodString;
27
- headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
28
40
  account: z.ZodString;
41
+ endpoints: z.ZodArray<z.ZodObject<{
42
+ url: z.ZodString;
43
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
44
+ }, "strip", z.ZodTypeAny, {
45
+ url: string;
46
+ headers?: Record<string, string> | undefined;
47
+ }, {
48
+ url: string;
49
+ headers?: Record<string, string> | undefined;
50
+ }>, "many">;
51
+ id: z.ZodString;
29
52
  PK: z.ZodString;
30
53
  SK: z.ZodString;
31
- id: z.ZodString;
32
54
  }, "strip", z.ZodTypeAny, {
33
- url: string;
34
55
  account: string;
56
+ endpoints: {
57
+ url: string;
58
+ headers?: Record<string, string> | undefined;
59
+ }[];
35
60
  id: string;
36
61
  PK: string;
37
62
  SK: string;
38
- headers?: Record<string, string> | undefined;
39
63
  }, {
40
- url: string;
41
64
  account: string;
65
+ endpoints: {
66
+ url: string;
67
+ headers?: Record<string, string> | undefined;
68
+ }[];
42
69
  id: string;
43
70
  PK: string;
44
71
  SK: string;
45
- headers?: Record<string, string> | undefined;
46
72
  }>;
47
73
  export type WebhookEndpointItem = z.infer<typeof WebhookEndpointItemSchema>;
48
74
  export declare const isWebhookEndpointItem: (obj: unknown) => obj is {
49
- url: string;
50
75
  account: string;
76
+ endpoints: {
77
+ url: string;
78
+ headers?: Record<string, string> | undefined;
79
+ }[];
51
80
  id: string;
52
81
  PK: string;
53
82
  SK: string;
54
- headers?: Record<string, string> | undefined;
55
83
  };
@@ -5,8 +5,7 @@ const kit_aws_1 = require("@xube/kit-aws");
5
5
  const zod_1 = require("zod");
6
6
  const endpoint_1 = require("./endpoint");
7
7
  exports.WebhookEndpointSchema = zod_1.z.object({
8
- url: zod_1.z.string(),
9
- headers: endpoint_1.HookEndpointHeaderSchema.optional(),
8
+ endpoints: zod_1.z.array(endpoint_1.HookEndpointSchema),
10
9
  id: zod_1.z.string(),
11
10
  account: zod_1.z.string(),
12
11
  });
package/dist/send.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { TableItem } from "@xube/kit-aws";
2
+ import { XubeResponse } from "@xube/kit-request";
3
+ export declare const sendDataToEndpoints: (webhookTableName: string, indexName: string, items: TableItem[]) => Promise<XubeResponse<boolean>>;
package/dist/send.js ADDED
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendDataToEndpoints = void 0;
4
+ const kit_aws_1 = require("@xube/kit-aws");
5
+ const keys_1 = require("./keys");
6
+ const types_1 = require("./types");
7
+ const kit_request_1 = require("@xube/kit-request");
8
+ const webhook_1 = require("./schemas/webhook");
9
+ const sendDataToEndpoints = async (webhookTableName, indexName, items) => {
10
+ const endpointSends = [];
11
+ for (const item of items) {
12
+ const invertedWebhookKey = {
13
+ PK: (0, keys_1.getWebhookSortKey)(item.id, types_1.WebhookTypes.data),
14
+ };
15
+ const getWebhookEndpointsResponse = await (0, kit_aws_1.queryItemsFromTable)(webhookTableName, invertedWebhookKey, indexName);
16
+ if (getWebhookEndpointsResponse.hasFailed()) {
17
+ return getWebhookEndpointsResponse.switchXubeResponseType();
18
+ }
19
+ if (!getWebhookEndpointsResponse.data ||
20
+ !getWebhookEndpointsResponse.data.length) {
21
+ console.log(`No webhook endpoints found for webhook endpoint ${item.id} and type ${types_1.WebhookTypes.data}`);
22
+ continue;
23
+ }
24
+ const webhookEndpoints = getWebhookEndpointsResponse.data;
25
+ for (const webhookEndpoint of webhookEndpoints) {
26
+ if (!(0, webhook_1.isWebhookEndpoint)(webhookEndpoint)) {
27
+ console.log(`Webhook endpoint ${webhookEndpoint.id} is not a valid webhook endpoint`);
28
+ continue;
29
+ }
30
+ if (!webhookEndpoint.endpoints || !webhookEndpoint.endpoints.length) {
31
+ console.log(`No endpoints found for webhook endpoint ${webhookEndpoint.id}`);
32
+ continue;
33
+ }
34
+ for (const endpoint of webhookEndpoint.endpoints) {
35
+ endpointSends.push(fetch(endpoint.url, {
36
+ body: JSON.stringify(item),
37
+ headers: endpoint.headers,
38
+ method: "POST",
39
+ }));
40
+ }
41
+ }
42
+ }
43
+ const responses = await Promise.all(endpointSends);
44
+ const failedEndpointSendUrls = [];
45
+ let failedResponseCount = 0;
46
+ for (const response of responses) {
47
+ if (!response.ok) {
48
+ failedEndpointSendUrls.push(response.url);
49
+ failedResponseCount++;
50
+ }
51
+ }
52
+ if (failedResponseCount == endpointSends.length) {
53
+ return new kit_request_1.XubeResponse({
54
+ statusCode: 500,
55
+ error: `Failed to send data to all endpoints: ${JSON.stringify(failedEndpointSendUrls, null, 2)}`,
56
+ });
57
+ }
58
+ if (failedResponseCount) {
59
+ return new kit_request_1.XubeResponse({
60
+ statusCode: 207,
61
+ error: `Failed to send data to ${failedResponseCount} of ${endpointSends.length} endpoints: ${JSON.stringify(failedEndpointSendUrls, null, 2)}`,
62
+ });
63
+ }
64
+ return new kit_request_1.XubeResponse({
65
+ statusCode: 200,
66
+ data: true,
67
+ });
68
+ };
69
+ exports.sendDataToEndpoints = sendDataToEndpoints;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xube/kit-aws-hooks",
3
- "version": "0.0.33",
3
+ "version": "0.0.34",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -17,12 +17,12 @@
17
17
  },
18
18
  "homepage": "https://github.com/XubeLtd/dev-kit#readme",
19
19
  "devDependencies": {
20
- "@xube/kit-build": "^0.0.33"
20
+ "@xube/kit-build": "^0.0.34"
21
21
  },
22
22
  "dependencies": {
23
- "@xube/kit-aws": "^0.0.33",
24
- "@xube/kit-log": "^0.0.33",
25
- "@xube/kit-request": "^0.0.33",
23
+ "@xube/kit-aws": "^0.0.34",
24
+ "@xube/kit-log": "^0.0.34",
25
+ "@xube/kit-request": "^0.0.34",
26
26
  "zod": "^3.22.4"
27
27
  }
28
28
  }
package/src/constants.ts CHANGED
@@ -1 +1,3 @@
1
- export const WEBHOOK_TABLE_NAME_ENV_VAR = "WEBHOOK_TABLE_NAME";
1
+ export const WEBHOOK_TABLE_NAME_ENV_VAR = "WEBHOOK_TABLE_NAME";
2
+ export const WEBHOOK_TABLE_INVERTED_INDEX_NAME_ENV_VAR =
3
+ "WEBHOOK_TABLE_INVERTED_INDEX_NAME";
package/src/create.ts CHANGED
@@ -24,6 +24,9 @@ export const createWebhookForAccount = async (
24
24
 
25
25
  const newWebhooks: WebhookEndpointItem[] = generateWebhookItems(request);
26
26
 
27
+ //TODO - These webhooks need to be added to the items if they already exist.
28
+ //For now they will just override any existing webhooks.
29
+
27
30
  const putWebhookItems: Promise<XubeResponse<boolean>>[] = [];
28
31
  for (const webhook of newWebhooks) {
29
32
  putWebhookItems.push(putItemInTable(tableName, webhook));
package/src/generate.ts CHANGED
@@ -2,23 +2,34 @@ import { getWebhookPartitionKey, getWebhookSortKey } from "./keys";
2
2
  import { CreateWebhookForAccountRequest } from "./schemas/create";
3
3
  import { WebhookEndpoint, WebhookEndpointItem } from "./schemas/webhook";
4
4
  import { WebhookTypes } from "./types";
5
+ import { TableKey, getAggregateKeyFromTableKey } from "@xube/kit-aws";
5
6
 
6
7
  export const generateWebhookItems = (
7
8
  request: CreateWebhookForAccountRequest
8
9
  ): WebhookEndpointItem[] => {
9
- const webhookItems: WebhookEndpointItem[] = [];
10
+ const webhookItems: Record<string, WebhookEndpointItem> = {};
10
11
 
11
12
  for (const endpoint of request.endpoints) {
12
13
  for (const id of request.ids) {
13
- webhookItems.push({
14
- account: request.account,
15
- ...endpoint,
16
- id,
14
+ const key: TableKey = {
17
15
  PK: getWebhookPartitionKey(request.account),
18
16
  SK: getWebhookSortKey(id, request.type ?? WebhookTypes.data),
19
- });
17
+ };
18
+
19
+ const aggregateKey = getAggregateKeyFromTableKey(key);
20
+
21
+ if (!webhookItems[aggregateKey]) {
22
+ webhookItems[aggregateKey] = {
23
+ account: request.account,
24
+ endpoints: [endpoint],
25
+ id,
26
+ ...key,
27
+ };
28
+ } else {
29
+ webhookItems[aggregateKey].endpoints.push(endpoint);
30
+ }
20
31
  }
21
32
  }
22
33
 
23
- return webhookItems;
34
+ return Object.values(webhookItems);
24
35
  };
package/src/index.ts CHANGED
@@ -7,4 +7,5 @@ export * from "./create";
7
7
  export * from "./generate";
8
8
  export * from "./get";
9
9
  export * from "./keys";
10
+ export * from "./send";
10
11
  export * from "./types";
@@ -1,10 +1,9 @@
1
1
  import { TableItemSchema } from "@xube/kit-aws";
2
2
  import { z } from "zod";
3
- import { HookEndpointHeaderSchema } from "./endpoint";
3
+ import { HookEndpointSchema } from "./endpoint";
4
4
 
5
5
  export const WebhookEndpointSchema = z.object({
6
- url: z.string(),
7
- headers: HookEndpointHeaderSchema.optional(),
6
+ endpoints: z.array(HookEndpointSchema),
8
7
  id: z.string(),
9
8
  account: z.string(),
10
9
  });
package/src/send.ts ADDED
@@ -0,0 +1,108 @@
1
+ import {
2
+ PartialTableKey,
3
+ TableItem,
4
+ queryItemsFromTable,
5
+ } from "@xube/kit-aws";
6
+ import { getWebhookSortKey } from "./keys";
7
+ import { WebhookTypes } from "./types";
8
+ import { XubeResponse } from "@xube/kit-request";
9
+ import { isWebhookEndpoint } from "./schemas/webhook";
10
+
11
+ export const sendDataToEndpoints = async (
12
+ webhookTableName: string,
13
+ indexName: string,
14
+ items: TableItem[]
15
+ ): Promise<XubeResponse<boolean>> => {
16
+ const endpointSends: Promise<Response>[] = [];
17
+
18
+ for (const item of items) {
19
+ const invertedWebhookKey: PartialTableKey = {
20
+ PK: getWebhookSortKey(item.id, WebhookTypes.data),
21
+ };
22
+
23
+ const getWebhookEndpointsResponse = await queryItemsFromTable(
24
+ webhookTableName,
25
+ invertedWebhookKey,
26
+ indexName
27
+ );
28
+
29
+ if (getWebhookEndpointsResponse.hasFailed()) {
30
+ return getWebhookEndpointsResponse.switchXubeResponseType();
31
+ }
32
+
33
+ if (
34
+ !getWebhookEndpointsResponse.data ||
35
+ !getWebhookEndpointsResponse.data.length
36
+ ) {
37
+ console.log(
38
+ `No webhook endpoints found for webhook endpoint ${item.id} and type ${WebhookTypes.data}`
39
+ );
40
+ continue;
41
+ }
42
+
43
+ const webhookEndpoints: TableItem[] = getWebhookEndpointsResponse.data;
44
+
45
+ for (const webhookEndpoint of webhookEndpoints) {
46
+ if (!isWebhookEndpoint(webhookEndpoint)) {
47
+ console.log(
48
+ `Webhook endpoint ${webhookEndpoint.id} is not a valid webhook endpoint`
49
+ );
50
+ continue;
51
+ }
52
+
53
+ if (!webhookEndpoint.endpoints || !webhookEndpoint.endpoints.length) {
54
+ console.log(
55
+ `No endpoints found for webhook endpoint ${webhookEndpoint.id}`
56
+ );
57
+ continue;
58
+ }
59
+
60
+ for (const endpoint of webhookEndpoint.endpoints) {
61
+ endpointSends.push(
62
+ fetch(endpoint.url, {
63
+ body: JSON.stringify(item),
64
+ headers: endpoint.headers,
65
+ method: "POST",
66
+ })
67
+ );
68
+ }
69
+ }
70
+ }
71
+
72
+ const responses: Response[] = await Promise.all(endpointSends);
73
+
74
+ const failedEndpointSendUrls: string[] = [];
75
+ let failedResponseCount: number = 0;
76
+
77
+ for (const response of responses) {
78
+ if (!response.ok) {
79
+ failedEndpointSendUrls.push(response.url);
80
+ failedResponseCount++;
81
+ }
82
+ }
83
+
84
+ if (failedResponseCount == endpointSends.length) {
85
+ return new XubeResponse({
86
+ statusCode: 500,
87
+ error: `Failed to send data to all endpoints: ${JSON.stringify(
88
+ failedEndpointSendUrls,
89
+ null,
90
+ 2
91
+ )}`,
92
+ });
93
+ }
94
+
95
+ if (failedResponseCount) {
96
+ return new XubeResponse({
97
+ statusCode: 207,
98
+ error: `Failed to send data to ${failedResponseCount} of ${
99
+ endpointSends.length
100
+ } endpoints: ${JSON.stringify(failedEndpointSendUrls, null, 2)}`,
101
+ });
102
+ }
103
+
104
+ return new XubeResponse({
105
+ statusCode: 200,
106
+ data: true,
107
+ });
108
+ };