@slates-integrations/tableau 0.2.0-rc.8
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 +85 -0
- package/docs/SPEC.md +61 -0
- package/logo.png +0 -0
- package/package.json +19 -0
- package/slate.json +18 -0
- package/src/auth.ts +237 -0
- package/src/config.ts +17 -0
- package/src/index.ts +55 -0
- package/src/lib/client.ts +959 -0
- package/src/lib/errors.ts +94 -0
- package/src/lib/helpers.ts +15 -0
- package/src/lib/normalizers.ts +9 -0
- package/src/spec.ts +12 -0
- package/src/tools/export-view.ts +112 -0
- package/src/tools/get-site-info.ts +47 -0
- package/src/tools/get-view-data.ts +31 -0
- package/src/tools/index.ts +18 -0
- package/src/tools/list-datasources.ts +78 -0
- package/src/tools/list-views.ts +70 -0
- package/src/tools/list-workbooks.ts +88 -0
- package/src/tools/manage-alerts.ts +139 -0
- package/src/tools/manage-collections.ts +254 -0
- package/src/tools/manage-custom-views.ts +159 -0
- package/src/tools/manage-datasource.ts +129 -0
- package/src/tools/manage-favorites.ts +80 -0
- package/src/tools/manage-flows.ts +170 -0
- package/src/tools/manage-groups.ts +178 -0
- package/src/tools/manage-jobs.ts +120 -0
- package/src/tools/manage-permissions.ts +118 -0
- package/src/tools/manage-projects.ts +162 -0
- package/src/tools/manage-users.ts +184 -0
- package/src/tools/manage-workbook.ts +160 -0
- package/src/triggers/datasource-events.ts +119 -0
- package/src/triggers/index.ts +6 -0
- package/src/triggers/label-events.ts +98 -0
- package/src/triggers/site-events.ts +97 -0
- package/src/triggers/user-events.ts +98 -0
- package/src/triggers/view-events.ts +83 -0
- package/src/triggers/workbook-events.ts +108 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { SlateTrigger } from 'slates';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { spec } from '../spec';
|
|
4
|
+
import { createClient } from '../lib/helpers';
|
|
5
|
+
|
|
6
|
+
let eventNameMap: Record<string, string> = {
|
|
7
|
+
LabelCreated: 'label.created',
|
|
8
|
+
LabelUpdated: 'label.updated',
|
|
9
|
+
LabelDeleted: 'label.deleted'
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
let webhookEventNames = ['LabelCreated', 'LabelUpdated', 'LabelDeleted'];
|
|
13
|
+
|
|
14
|
+
export let labelEvents = SlateTrigger.create(spec, {
|
|
15
|
+
name: 'Label Events',
|
|
16
|
+
key: 'label_events',
|
|
17
|
+
description:
|
|
18
|
+
'Triggers when data quality labels or certifications are created, updated, or deleted. Tableau Cloud only.'
|
|
19
|
+
})
|
|
20
|
+
.input(
|
|
21
|
+
z.object({
|
|
22
|
+
eventType: z.string().describe('Tableau webhook event type'),
|
|
23
|
+
resourceId: z.string().describe('LUID of the affected label'),
|
|
24
|
+
resourceName: z.string().describe('Name of the affected label'),
|
|
25
|
+
siteId: z.string().describe('LUID of the site'),
|
|
26
|
+
timestamp: z.string().describe('Event timestamp')
|
|
27
|
+
})
|
|
28
|
+
)
|
|
29
|
+
.output(
|
|
30
|
+
z.object({
|
|
31
|
+
labelId: z.string().describe('LUID of the affected label'),
|
|
32
|
+
labelName: z.string().describe('Name of the label'),
|
|
33
|
+
siteId: z.string().describe('LUID of the site'),
|
|
34
|
+
timestamp: z.string().describe('When the event occurred')
|
|
35
|
+
})
|
|
36
|
+
)
|
|
37
|
+
.webhook({
|
|
38
|
+
autoRegisterWebhook: async ctx => {
|
|
39
|
+
let client = createClient(ctx.config, ctx.auth);
|
|
40
|
+
let webhookIds: Record<string, string> = {};
|
|
41
|
+
|
|
42
|
+
for (let eventName of webhookEventNames) {
|
|
43
|
+
let webhook = await client.createWebhook(
|
|
44
|
+
`slates-label-${eventName}`,
|
|
45
|
+
eventName,
|
|
46
|
+
ctx.input.webhookBaseUrl
|
|
47
|
+
);
|
|
48
|
+
webhookIds[eventName] = webhook.id;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { registrationDetails: { webhookIds } };
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
autoUnregisterWebhook: async ctx => {
|
|
55
|
+
let client = createClient(ctx.config, ctx.auth);
|
|
56
|
+
let webhookIds = ctx.input.registrationDetails?.webhookIds || {};
|
|
57
|
+
|
|
58
|
+
for (let webhookId of Object.values(webhookIds) as string[]) {
|
|
59
|
+
try {
|
|
60
|
+
await client.deleteWebhook(webhookId);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
// Webhook may already be deleted
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
handleRequest: async ctx => {
|
|
68
|
+
let body = (await ctx.request.json()) as any;
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
inputs: [
|
|
72
|
+
{
|
|
73
|
+
eventType: body.eventType || body['webhook-source-event-name'] || 'unknown',
|
|
74
|
+
resourceId: body.resource_luid || body.resourceId || '',
|
|
75
|
+
resourceName: body.resource_name || body.resourceName || '',
|
|
76
|
+
siteId: body.site_luid || body.siteId || '',
|
|
77
|
+
timestamp: body.created_at || body.timestamp || new Date().toISOString()
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
handleEvent: async ctx => {
|
|
84
|
+
let mappedType = eventNameMap[ctx.input.eventType] || `label.${ctx.input.eventType}`;
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
type: mappedType,
|
|
88
|
+
id: `${ctx.input.resourceId}-${ctx.input.timestamp}`,
|
|
89
|
+
output: {
|
|
90
|
+
labelId: ctx.input.resourceId,
|
|
91
|
+
labelName: ctx.input.resourceName,
|
|
92
|
+
siteId: ctx.input.siteId,
|
|
93
|
+
timestamp: ctx.input.timestamp
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
.build();
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { SlateTrigger } from 'slates';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { spec } from '../spec';
|
|
4
|
+
import { createClient } from '../lib/helpers';
|
|
5
|
+
|
|
6
|
+
let eventNameMap: Record<string, string> = {
|
|
7
|
+
SiteCreated: 'site.created',
|
|
8
|
+
SiteUpdated: 'site.updated',
|
|
9
|
+
SiteDeleted: 'site.deleted'
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
let webhookEventNames = ['SiteCreated', 'SiteUpdated', 'SiteDeleted'];
|
|
13
|
+
|
|
14
|
+
export let siteEvents = SlateTrigger.create(spec, {
|
|
15
|
+
name: 'Site Events',
|
|
16
|
+
key: 'site_events',
|
|
17
|
+
description: 'Triggers when a site is created, updated, or deleted.'
|
|
18
|
+
})
|
|
19
|
+
.input(
|
|
20
|
+
z.object({
|
|
21
|
+
eventType: z.string().describe('Tableau webhook event type'),
|
|
22
|
+
resourceId: z.string().describe('LUID of the affected site'),
|
|
23
|
+
resourceName: z.string().describe('Name of the affected site'),
|
|
24
|
+
siteId: z.string().describe('LUID of the site'),
|
|
25
|
+
timestamp: z.string().describe('Event timestamp')
|
|
26
|
+
})
|
|
27
|
+
)
|
|
28
|
+
.output(
|
|
29
|
+
z.object({
|
|
30
|
+
affectedSiteId: z.string().describe('LUID of the affected site'),
|
|
31
|
+
siteName: z.string().describe('Name of the site'),
|
|
32
|
+
siteId: z.string().describe('LUID of the site context'),
|
|
33
|
+
timestamp: z.string().describe('When the event occurred')
|
|
34
|
+
})
|
|
35
|
+
)
|
|
36
|
+
.webhook({
|
|
37
|
+
autoRegisterWebhook: async ctx => {
|
|
38
|
+
let client = createClient(ctx.config, ctx.auth);
|
|
39
|
+
let webhookIds: Record<string, string> = {};
|
|
40
|
+
|
|
41
|
+
for (let eventName of webhookEventNames) {
|
|
42
|
+
let webhook = await client.createWebhook(
|
|
43
|
+
`slates-site-${eventName}`,
|
|
44
|
+
eventName,
|
|
45
|
+
ctx.input.webhookBaseUrl
|
|
46
|
+
);
|
|
47
|
+
webhookIds[eventName] = webhook.id;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return { registrationDetails: { webhookIds } };
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
autoUnregisterWebhook: async ctx => {
|
|
54
|
+
let client = createClient(ctx.config, ctx.auth);
|
|
55
|
+
let webhookIds = ctx.input.registrationDetails?.webhookIds || {};
|
|
56
|
+
|
|
57
|
+
for (let webhookId of Object.values(webhookIds) as string[]) {
|
|
58
|
+
try {
|
|
59
|
+
await client.deleteWebhook(webhookId);
|
|
60
|
+
} catch (e) {
|
|
61
|
+
// Webhook may already be deleted
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
handleRequest: async ctx => {
|
|
67
|
+
let body = (await ctx.request.json()) as any;
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
inputs: [
|
|
71
|
+
{
|
|
72
|
+
eventType: body.eventType || body['webhook-source-event-name'] || 'unknown',
|
|
73
|
+
resourceId: body.resource_luid || body.resourceId || '',
|
|
74
|
+
resourceName: body.resource_name || body.resourceName || '',
|
|
75
|
+
siteId: body.site_luid || body.siteId || '',
|
|
76
|
+
timestamp: body.created_at || body.timestamp || new Date().toISOString()
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
handleEvent: async ctx => {
|
|
83
|
+
let mappedType = eventNameMap[ctx.input.eventType] || `site.${ctx.input.eventType}`;
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
type: mappedType,
|
|
87
|
+
id: `${ctx.input.resourceId}-${ctx.input.timestamp}`,
|
|
88
|
+
output: {
|
|
89
|
+
affectedSiteId: ctx.input.resourceId,
|
|
90
|
+
siteName: ctx.input.resourceName,
|
|
91
|
+
siteId: ctx.input.siteId,
|
|
92
|
+
timestamp: ctx.input.timestamp
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
.build();
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { SlateTrigger } from 'slates';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { spec } from '../spec';
|
|
4
|
+
import { createClient } from '../lib/helpers';
|
|
5
|
+
|
|
6
|
+
let eventNameMap: Record<string, string> = {
|
|
7
|
+
AdminPromoted: 'user.admin_promoted',
|
|
8
|
+
AdminDemoted: 'user.admin_demoted',
|
|
9
|
+
UserDeleted: 'user.deleted'
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
let webhookEventNames = ['AdminPromoted', 'AdminDemoted', 'UserDeleted'];
|
|
13
|
+
|
|
14
|
+
export let userEvents = SlateTrigger.create(spec, {
|
|
15
|
+
name: 'User Events',
|
|
16
|
+
key: 'user_events',
|
|
17
|
+
description:
|
|
18
|
+
'Triggers when a user is promoted to or demoted from Site Administrator, or when a user is deleted.'
|
|
19
|
+
})
|
|
20
|
+
.input(
|
|
21
|
+
z.object({
|
|
22
|
+
eventType: z.string().describe('Tableau webhook event type'),
|
|
23
|
+
resourceId: z.string().describe('LUID of the affected user'),
|
|
24
|
+
resourceName: z.string().describe('Name of the affected user'),
|
|
25
|
+
siteId: z.string().describe('LUID of the site'),
|
|
26
|
+
timestamp: z.string().describe('Event timestamp')
|
|
27
|
+
})
|
|
28
|
+
)
|
|
29
|
+
.output(
|
|
30
|
+
z.object({
|
|
31
|
+
userId: z.string().describe('LUID of the affected user'),
|
|
32
|
+
userName: z.string().describe('Name of the user'),
|
|
33
|
+
siteId: z.string().describe('LUID of the site'),
|
|
34
|
+
timestamp: z.string().describe('When the event occurred')
|
|
35
|
+
})
|
|
36
|
+
)
|
|
37
|
+
.webhook({
|
|
38
|
+
autoRegisterWebhook: async ctx => {
|
|
39
|
+
let client = createClient(ctx.config, ctx.auth);
|
|
40
|
+
let webhookIds: Record<string, string> = {};
|
|
41
|
+
|
|
42
|
+
for (let eventName of webhookEventNames) {
|
|
43
|
+
let webhook = await client.createWebhook(
|
|
44
|
+
`slates-user-${eventName}`,
|
|
45
|
+
eventName,
|
|
46
|
+
ctx.input.webhookBaseUrl
|
|
47
|
+
);
|
|
48
|
+
webhookIds[eventName] = webhook.id;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { registrationDetails: { webhookIds } };
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
autoUnregisterWebhook: async ctx => {
|
|
55
|
+
let client = createClient(ctx.config, ctx.auth);
|
|
56
|
+
let webhookIds = ctx.input.registrationDetails?.webhookIds || {};
|
|
57
|
+
|
|
58
|
+
for (let webhookId of Object.values(webhookIds) as string[]) {
|
|
59
|
+
try {
|
|
60
|
+
await client.deleteWebhook(webhookId);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
// Webhook may already be deleted
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
handleRequest: async ctx => {
|
|
68
|
+
let body = (await ctx.request.json()) as any;
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
inputs: [
|
|
72
|
+
{
|
|
73
|
+
eventType: body.eventType || body['webhook-source-event-name'] || 'unknown',
|
|
74
|
+
resourceId: body.resource_luid || body.resourceId || '',
|
|
75
|
+
resourceName: body.resource_name || body.resourceName || '',
|
|
76
|
+
siteId: body.site_luid || body.siteId || '',
|
|
77
|
+
timestamp: body.created_at || body.timestamp || new Date().toISOString()
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
handleEvent: async ctx => {
|
|
84
|
+
let mappedType = eventNameMap[ctx.input.eventType] || `user.${ctx.input.eventType}`;
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
type: mappedType,
|
|
88
|
+
id: `${ctx.input.resourceId}-${ctx.input.timestamp}`,
|
|
89
|
+
output: {
|
|
90
|
+
userId: ctx.input.resourceId,
|
|
91
|
+
userName: ctx.input.resourceName,
|
|
92
|
+
siteId: ctx.input.siteId,
|
|
93
|
+
timestamp: ctx.input.timestamp
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
.build();
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { SlateTrigger } from 'slates';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { spec } from '../spec';
|
|
4
|
+
import { createClient } from '../lib/helpers';
|
|
5
|
+
|
|
6
|
+
export let viewEvents = SlateTrigger.create(spec, {
|
|
7
|
+
name: 'View Events',
|
|
8
|
+
key: 'view_events',
|
|
9
|
+
description: 'Triggers when a view is deleted.'
|
|
10
|
+
})
|
|
11
|
+
.input(
|
|
12
|
+
z.object({
|
|
13
|
+
eventType: z.string().describe('Tableau webhook event type'),
|
|
14
|
+
resourceId: z.string().describe('LUID of the affected view'),
|
|
15
|
+
resourceName: z.string().describe('Name of the affected view'),
|
|
16
|
+
siteId: z.string().describe('LUID of the site'),
|
|
17
|
+
timestamp: z.string().describe('Event timestamp')
|
|
18
|
+
})
|
|
19
|
+
)
|
|
20
|
+
.output(
|
|
21
|
+
z.object({
|
|
22
|
+
viewId: z.string().describe('LUID of the affected view'),
|
|
23
|
+
viewName: z.string().describe('Name of the view'),
|
|
24
|
+
siteId: z.string().describe('LUID of the site'),
|
|
25
|
+
timestamp: z.string().describe('When the event occurred')
|
|
26
|
+
})
|
|
27
|
+
)
|
|
28
|
+
.webhook({
|
|
29
|
+
autoRegisterWebhook: async ctx => {
|
|
30
|
+
let client = createClient(ctx.config, ctx.auth);
|
|
31
|
+
|
|
32
|
+
let webhook = await client.createWebhook(
|
|
33
|
+
'slates-view-ViewDeleted',
|
|
34
|
+
'ViewDeleted',
|
|
35
|
+
ctx.input.webhookBaseUrl
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return { registrationDetails: { webhookId: webhook.id } };
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
autoUnregisterWebhook: async ctx => {
|
|
42
|
+
let client = createClient(ctx.config, ctx.auth);
|
|
43
|
+
let webhookId = ctx.input.registrationDetails?.webhookId;
|
|
44
|
+
|
|
45
|
+
if (webhookId) {
|
|
46
|
+
try {
|
|
47
|
+
await client.deleteWebhook(webhookId);
|
|
48
|
+
} catch (e) {
|
|
49
|
+
// Webhook may already be deleted
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
handleRequest: async ctx => {
|
|
55
|
+
let body = (await ctx.request.json()) as any;
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
inputs: [
|
|
59
|
+
{
|
|
60
|
+
eventType: body.eventType || body['webhook-source-event-name'] || 'ViewDeleted',
|
|
61
|
+
resourceId: body.resource_luid || body.resourceId || '',
|
|
62
|
+
resourceName: body.resource_name || body.resourceName || '',
|
|
63
|
+
siteId: body.site_luid || body.siteId || '',
|
|
64
|
+
timestamp: body.created_at || body.timestamp || new Date().toISOString()
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
handleEvent: async ctx => {
|
|
71
|
+
return {
|
|
72
|
+
type: 'view.deleted',
|
|
73
|
+
id: `${ctx.input.resourceId}-${ctx.input.timestamp}`,
|
|
74
|
+
output: {
|
|
75
|
+
viewId: ctx.input.resourceId,
|
|
76
|
+
viewName: ctx.input.resourceName,
|
|
77
|
+
siteId: ctx.input.siteId,
|
|
78
|
+
timestamp: ctx.input.timestamp
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
.build();
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { SlateTrigger } from 'slates';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { spec } from '../spec';
|
|
4
|
+
import { createClient } from '../lib/helpers';
|
|
5
|
+
|
|
6
|
+
let eventNameMap: Record<string, string> = {
|
|
7
|
+
WorkbookCreated: 'workbook.created',
|
|
8
|
+
WorkbookUpdated: 'workbook.updated',
|
|
9
|
+
WorkbookDeleted: 'workbook.deleted',
|
|
10
|
+
WorkbookRefreshStarted: 'workbook.refresh_started',
|
|
11
|
+
WorkbookRefreshSucceeded: 'workbook.refresh_succeeded',
|
|
12
|
+
WorkbookRefreshFailed: 'workbook.refresh_failed'
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
let webhookEventNames = [
|
|
16
|
+
'WorkbookCreated',
|
|
17
|
+
'WorkbookUpdated',
|
|
18
|
+
'WorkbookDeleted',
|
|
19
|
+
'WorkbookRefreshStarted',
|
|
20
|
+
'WorkbookRefreshSucceeded',
|
|
21
|
+
'WorkbookRefreshFailed'
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export let workbookEvents = SlateTrigger.create(spec, {
|
|
25
|
+
name: 'Workbook Events',
|
|
26
|
+
key: 'workbook_events',
|
|
27
|
+
description:
|
|
28
|
+
'Triggers when a workbook is created, updated, deleted, or when an extract refresh starts, succeeds, or fails.'
|
|
29
|
+
})
|
|
30
|
+
.input(
|
|
31
|
+
z.object({
|
|
32
|
+
eventType: z.string().describe('Tableau webhook event type'),
|
|
33
|
+
resourceId: z.string().describe('LUID of the affected workbook'),
|
|
34
|
+
resourceName: z.string().describe('Name of the affected workbook'),
|
|
35
|
+
siteId: z.string().describe('LUID of the site'),
|
|
36
|
+
timestamp: z.string().describe('Event timestamp')
|
|
37
|
+
})
|
|
38
|
+
)
|
|
39
|
+
.output(
|
|
40
|
+
z.object({
|
|
41
|
+
workbookId: z.string().describe('LUID of the affected workbook'),
|
|
42
|
+
workbookName: z.string().describe('Name of the workbook'),
|
|
43
|
+
siteId: z.string().describe('LUID of the site'),
|
|
44
|
+
timestamp: z.string().describe('When the event occurred')
|
|
45
|
+
})
|
|
46
|
+
)
|
|
47
|
+
.webhook({
|
|
48
|
+
autoRegisterWebhook: async ctx => {
|
|
49
|
+
let client = createClient(ctx.config, ctx.auth);
|
|
50
|
+
let webhookIds: Record<string, string> = {};
|
|
51
|
+
|
|
52
|
+
for (let eventName of webhookEventNames) {
|
|
53
|
+
let webhook = await client.createWebhook(
|
|
54
|
+
`slates-workbook-${eventName}`,
|
|
55
|
+
eventName,
|
|
56
|
+
ctx.input.webhookBaseUrl
|
|
57
|
+
);
|
|
58
|
+
webhookIds[eventName] = webhook.id;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return { registrationDetails: { webhookIds } };
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
autoUnregisterWebhook: async ctx => {
|
|
65
|
+
let client = createClient(ctx.config, ctx.auth);
|
|
66
|
+
let webhookIds = ctx.input.registrationDetails?.webhookIds || {};
|
|
67
|
+
|
|
68
|
+
for (let webhookId of Object.values(webhookIds) as string[]) {
|
|
69
|
+
try {
|
|
70
|
+
await client.deleteWebhook(webhookId);
|
|
71
|
+
} catch (e) {
|
|
72
|
+
// Webhook may already be deleted
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
handleRequest: async ctx => {
|
|
78
|
+
let body = (await ctx.request.json()) as any;
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
inputs: [
|
|
82
|
+
{
|
|
83
|
+
eventType: body.eventType || body['webhook-source-event-name'] || 'unknown',
|
|
84
|
+
resourceId: body.resource_luid || body.resourceId || '',
|
|
85
|
+
resourceName: body.resource_name || body.resourceName || '',
|
|
86
|
+
siteId: body.site_luid || body.siteId || '',
|
|
87
|
+
timestamp: body.created_at || body.timestamp || new Date().toISOString()
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
};
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
handleEvent: async ctx => {
|
|
94
|
+
let mappedType = eventNameMap[ctx.input.eventType] || `workbook.${ctx.input.eventType}`;
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
type: mappedType,
|
|
98
|
+
id: `${ctx.input.resourceId}-${ctx.input.timestamp}`,
|
|
99
|
+
output: {
|
|
100
|
+
workbookId: ctx.input.resourceId,
|
|
101
|
+
workbookName: ctx.input.resourceName,
|
|
102
|
+
siteId: ctx.input.siteId,
|
|
103
|
+
timestamp: ctx.input.timestamp
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
.build();
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"types": ["node"],
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "Preserve",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
|
|
12
|
+
"noEmit": true,
|
|
13
|
+
"strict": true,
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
"noFallthroughCasesInSwitch": true,
|
|
16
|
+
"noUncheckedIndexedAccess": true,
|
|
17
|
+
"noImplicitOverride": true,
|
|
18
|
+
"noUnusedLocals": false,
|
|
19
|
+
"noUnusedParameters": false,
|
|
20
|
+
"noPropertyAccessFromIndexSignature": false
|
|
21
|
+
},
|
|
22
|
+
"include": ["src"]
|
|
23
|
+
}
|