@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.
Files changed (40) hide show
  1. package/README.md +85 -0
  2. package/docs/SPEC.md +61 -0
  3. package/logo.png +0 -0
  4. package/package.json +19 -0
  5. package/slate.json +18 -0
  6. package/src/auth.ts +237 -0
  7. package/src/config.ts +17 -0
  8. package/src/index.ts +55 -0
  9. package/src/lib/client.ts +959 -0
  10. package/src/lib/errors.ts +94 -0
  11. package/src/lib/helpers.ts +15 -0
  12. package/src/lib/normalizers.ts +9 -0
  13. package/src/spec.ts +12 -0
  14. package/src/tools/export-view.ts +112 -0
  15. package/src/tools/get-site-info.ts +47 -0
  16. package/src/tools/get-view-data.ts +31 -0
  17. package/src/tools/index.ts +18 -0
  18. package/src/tools/list-datasources.ts +78 -0
  19. package/src/tools/list-views.ts +70 -0
  20. package/src/tools/list-workbooks.ts +88 -0
  21. package/src/tools/manage-alerts.ts +139 -0
  22. package/src/tools/manage-collections.ts +254 -0
  23. package/src/tools/manage-custom-views.ts +159 -0
  24. package/src/tools/manage-datasource.ts +129 -0
  25. package/src/tools/manage-favorites.ts +80 -0
  26. package/src/tools/manage-flows.ts +170 -0
  27. package/src/tools/manage-groups.ts +178 -0
  28. package/src/tools/manage-jobs.ts +120 -0
  29. package/src/tools/manage-permissions.ts +118 -0
  30. package/src/tools/manage-projects.ts +162 -0
  31. package/src/tools/manage-users.ts +184 -0
  32. package/src/tools/manage-workbook.ts +160 -0
  33. package/src/triggers/datasource-events.ts +119 -0
  34. package/src/triggers/index.ts +6 -0
  35. package/src/triggers/label-events.ts +98 -0
  36. package/src/triggers/site-events.ts +97 -0
  37. package/src/triggers/user-events.ts +98 -0
  38. package/src/triggers/view-events.ts +83 -0
  39. package/src/triggers/workbook-events.ts +108 -0
  40. package/tsconfig.json +23 -0
@@ -0,0 +1,162 @@
1
+ import { SlateTool } from 'slates';
2
+ import { z } from 'zod';
3
+ import { spec } from '../spec';
4
+ import { createClient } from '../lib/helpers';
5
+ import { tableauServiceError } from '../lib/errors';
6
+
7
+ export let manageProjects = SlateTool.create(spec, {
8
+ name: 'Manage Projects',
9
+ key: 'manage_projects',
10
+ description: `List, create, update, or delete projects. Projects organize workbooks, data sources, and other content in Tableau.`,
11
+ tags: { destructive: true }
12
+ })
13
+ .input(
14
+ z.object({
15
+ action: z.enum(['list', 'create', 'update', 'delete']).describe('Operation to perform'),
16
+ projectId: z.string().optional().describe('Project LUID (required for update, delete)'),
17
+ name: z
18
+ .string()
19
+ .optional()
20
+ .describe('Project name (required for create, optional for update)'),
21
+ description: z.string().optional().describe('Project description'),
22
+ parentProjectId: z
23
+ .string()
24
+ .optional()
25
+ .describe('Parent project LUID for nested projects'),
26
+ contentPermissions: z
27
+ .enum(['ManagedByOwner', 'LockedToProject', 'LockedToProjectWithoutNested'])
28
+ .optional()
29
+ .describe('Content permission model'),
30
+ pageSize: z.number().optional().describe('Number of items per page'),
31
+ pageNumber: z.number().optional().describe('Page number (1-based)'),
32
+ filter: z.string().optional().describe('Filter expression for list'),
33
+ sort: z.string().optional().describe('Sort expression for list')
34
+ })
35
+ )
36
+ .output(
37
+ z.object({
38
+ projects: z
39
+ .array(
40
+ z.object({
41
+ projectId: z.string(),
42
+ name: z.string().optional(),
43
+ description: z.string().optional(),
44
+ parentProjectId: z.string().optional(),
45
+ contentPermissions: z.string().optional(),
46
+ createdAt: z.string().optional(),
47
+ updatedAt: z.string().optional()
48
+ })
49
+ )
50
+ .optional(),
51
+ project: z
52
+ .object({
53
+ projectId: z.string(),
54
+ name: z.string().optional(),
55
+ description: z.string().optional(),
56
+ parentProjectId: z.string().optional(),
57
+ contentPermissions: z.string().optional(),
58
+ createdAt: z.string().optional(),
59
+ updatedAt: z.string().optional()
60
+ })
61
+ .optional(),
62
+ totalCount: z.number().optional(),
63
+ deleted: z.boolean().optional()
64
+ })
65
+ )
66
+ .handleInvocation(async ctx => {
67
+ let client = createClient(ctx.config, ctx.auth);
68
+ let { action } = ctx.input;
69
+
70
+ if (action === 'list') {
71
+ let result = await client.queryProjects({
72
+ pageSize: ctx.input.pageSize,
73
+ pageNumber: ctx.input.pageNumber,
74
+ filter: ctx.input.filter,
75
+ sort: ctx.input.sort
76
+ });
77
+ let pagination = result.pagination || {};
78
+ let projects = (result.projects?.project || []).map((p: any) => ({
79
+ projectId: p.id,
80
+ name: p.name,
81
+ description: p.description,
82
+ parentProjectId: p.parentProjectId,
83
+ contentPermissions: p.contentPermissions,
84
+ createdAt: p.createdAt,
85
+ updatedAt: p.updatedAt
86
+ }));
87
+ return {
88
+ output: { projects, totalCount: Number(pagination.totalAvailable || 0) },
89
+ message: `Found **${projects.length}** projects (${pagination.totalAvailable || 0} total).`
90
+ };
91
+ }
92
+
93
+ if (action === 'create') {
94
+ if (!ctx.input.name) throw tableauServiceError('name is required for create action.');
95
+
96
+ let p = await client.createProject(ctx.input.name, {
97
+ description: ctx.input.description,
98
+ parentProjectId: ctx.input.parentProjectId,
99
+ contentPermissions: ctx.input.contentPermissions
100
+ });
101
+ return {
102
+ output: {
103
+ project: {
104
+ projectId: p.id,
105
+ name: p.name,
106
+ description: p.description,
107
+ parentProjectId: p.parentProjectId,
108
+ contentPermissions: p.contentPermissions
109
+ }
110
+ },
111
+ message: `Created project **${p.name}**.`
112
+ };
113
+ }
114
+
115
+ if (action === 'update') {
116
+ if (!ctx.input.projectId) {
117
+ throw tableauServiceError('projectId is required for update action.');
118
+ }
119
+ if (
120
+ ctx.input.name === undefined &&
121
+ ctx.input.description === undefined &&
122
+ ctx.input.parentProjectId === undefined &&
123
+ ctx.input.contentPermissions === undefined
124
+ ) {
125
+ throw tableauServiceError('Provide at least one field to update a project.');
126
+ }
127
+
128
+ let p = await client.updateProject(ctx.input.projectId, {
129
+ name: ctx.input.name,
130
+ description: ctx.input.description,
131
+ parentProjectId: ctx.input.parentProjectId,
132
+ contentPermissions: ctx.input.contentPermissions
133
+ });
134
+ return {
135
+ output: {
136
+ project: {
137
+ projectId: p.id,
138
+ name: p.name,
139
+ description: p.description,
140
+ parentProjectId: p.parentProjectId,
141
+ contentPermissions: p.contentPermissions
142
+ }
143
+ },
144
+ message: `Updated project **${p.name}**.`
145
+ };
146
+ }
147
+
148
+ if (action === 'delete') {
149
+ if (!ctx.input.projectId) {
150
+ throw tableauServiceError('projectId is required for delete action.');
151
+ }
152
+
153
+ await client.deleteProject(ctx.input.projectId);
154
+ return {
155
+ output: { deleted: true },
156
+ message: `Deleted project \`${ctx.input.projectId}\`.`
157
+ };
158
+ }
159
+
160
+ throw tableauServiceError(`Unknown action: ${action}`);
161
+ })
162
+ .build();
@@ -0,0 +1,184 @@
1
+ import { SlateTool } from 'slates';
2
+ import { z } from 'zod';
3
+ import { spec } from '../spec';
4
+ import { createClient } from '../lib/helpers';
5
+ import { tableauServiceError } from '../lib/errors';
6
+
7
+ export let manageUsers = SlateTool.create(spec, {
8
+ name: 'Manage Users',
9
+ key: 'manage_users',
10
+ description: `List, get, add, update, or remove users on the Tableau site. Use the **action** field to select the operation.`,
11
+ tags: { destructive: true }
12
+ })
13
+ .input(
14
+ z.object({
15
+ action: z
16
+ .enum(['list', 'get', 'add', 'update', 'remove'])
17
+ .describe('Operation to perform'),
18
+ userId: z.string().optional().describe('User LUID (required for get, update, remove)'),
19
+ username: z.string().optional().describe('Username (required for add)'),
20
+ siteRole: z
21
+ .string()
22
+ .optional()
23
+ .describe(
24
+ 'Site role, e.g. "Viewer", "Explorer", "Creator", "SiteAdministratorExplorer", "SiteAdministratorCreator" (required for add)'
25
+ ),
26
+ fullName: z.string().optional().describe('Full display name (for update)'),
27
+ email: z.string().optional().describe('Email address (for update)'),
28
+ authSetting: z.string().optional().describe('Auth setting (for add/update)'),
29
+ pageSize: z.number().optional().describe('Number of items per page'),
30
+ pageNumber: z.number().optional().describe('Page number (1-based)'),
31
+ filter: z.string().optional().describe('Filter expression for list'),
32
+ sort: z.string().optional().describe('Sort expression for list')
33
+ })
34
+ )
35
+ .output(
36
+ z.object({
37
+ users: z
38
+ .array(
39
+ z.object({
40
+ userId: z.string(),
41
+ name: z.string().optional(),
42
+ fullName: z.string().optional(),
43
+ email: z.string().optional(),
44
+ siteRole: z.string().optional(),
45
+ authSetting: z.string().optional(),
46
+ lastLogin: z.string().optional()
47
+ })
48
+ )
49
+ .optional(),
50
+ user: z
51
+ .object({
52
+ userId: z.string(),
53
+ name: z.string().optional(),
54
+ fullName: z.string().optional(),
55
+ email: z.string().optional(),
56
+ siteRole: z.string().optional(),
57
+ authSetting: z.string().optional(),
58
+ lastLogin: z.string().optional()
59
+ })
60
+ .optional(),
61
+ totalCount: z.number().optional(),
62
+ removed: z.boolean().optional()
63
+ })
64
+ )
65
+ .handleInvocation(async ctx => {
66
+ let client = createClient(ctx.config, ctx.auth);
67
+ let { action } = ctx.input;
68
+
69
+ if (action === 'list') {
70
+ let result = await client.queryUsers({
71
+ pageSize: ctx.input.pageSize,
72
+ pageNumber: ctx.input.pageNumber,
73
+ filter: ctx.input.filter,
74
+ sort: ctx.input.sort
75
+ });
76
+
77
+ let pagination = result.pagination || {};
78
+ let users = (result.users?.user || []).map((u: any) => ({
79
+ userId: u.id,
80
+ name: u.name,
81
+ fullName: u.fullName,
82
+ email: u.email,
83
+ siteRole: u.siteRole,
84
+ authSetting: u.authSetting,
85
+ lastLogin: u.lastLogin
86
+ }));
87
+
88
+ return {
89
+ output: { users, totalCount: Number(pagination.totalAvailable || 0) },
90
+ message: `Found **${users.length}** users (${pagination.totalAvailable || 0} total).`
91
+ };
92
+ }
93
+
94
+ if (action === 'get') {
95
+ if (!ctx.input.userId) throw tableauServiceError('userId is required for get action.');
96
+
97
+ let u = await client.getUser(ctx.input.userId);
98
+ return {
99
+ output: {
100
+ user: {
101
+ userId: u.id,
102
+ name: u.name,
103
+ fullName: u.fullName,
104
+ email: u.email,
105
+ siteRole: u.siteRole,
106
+ authSetting: u.authSetting,
107
+ lastLogin: u.lastLogin
108
+ }
109
+ },
110
+ message: `Retrieved user **${u.name}** (${u.siteRole}).`
111
+ };
112
+ }
113
+
114
+ if (action === 'add') {
115
+ if (!ctx.input.username)
116
+ throw tableauServiceError('username is required for add action.');
117
+ if (!ctx.input.siteRole)
118
+ throw tableauServiceError('siteRole is required for add action.');
119
+
120
+ let u = await client.addUser(
121
+ ctx.input.username,
122
+ ctx.input.siteRole,
123
+ ctx.input.authSetting
124
+ );
125
+ return {
126
+ output: {
127
+ user: {
128
+ userId: u.id,
129
+ name: u.name,
130
+ siteRole: u.siteRole,
131
+ authSetting: u.authSetting
132
+ }
133
+ },
134
+ message: `Added user **${u.name}** as ${u.siteRole}.`
135
+ };
136
+ }
137
+
138
+ if (action === 'update') {
139
+ if (!ctx.input.userId)
140
+ throw tableauServiceError('userId is required for update action.');
141
+ if (
142
+ ctx.input.fullName === undefined &&
143
+ ctx.input.email === undefined &&
144
+ ctx.input.siteRole === undefined &&
145
+ ctx.input.authSetting === undefined
146
+ ) {
147
+ throw tableauServiceError('Provide at least one field to update a user.');
148
+ }
149
+
150
+ let u = await client.updateUser(ctx.input.userId, {
151
+ fullName: ctx.input.fullName,
152
+ email: ctx.input.email,
153
+ siteRole: ctx.input.siteRole,
154
+ authSetting: ctx.input.authSetting
155
+ });
156
+ return {
157
+ output: {
158
+ user: {
159
+ userId: u.id,
160
+ name: u.name,
161
+ fullName: u.fullName,
162
+ email: u.email,
163
+ siteRole: u.siteRole,
164
+ authSetting: u.authSetting
165
+ }
166
+ },
167
+ message: `Updated user **${u.name}**.`
168
+ };
169
+ }
170
+
171
+ if (action === 'remove') {
172
+ if (!ctx.input.userId)
173
+ throw tableauServiceError('userId is required for remove action.');
174
+
175
+ await client.removeUser(ctx.input.userId);
176
+ return {
177
+ output: { removed: true },
178
+ message: `Removed user \`${ctx.input.userId}\` from the site.`
179
+ };
180
+ }
181
+
182
+ throw tableauServiceError(`Unknown action: ${action}`);
183
+ })
184
+ .build();
@@ -0,0 +1,160 @@
1
+ import { SlateTool } from 'slates';
2
+ import { z } from 'zod';
3
+ import { spec } from '../spec';
4
+ import { createClient } from '../lib/helpers';
5
+ import { tableauServiceError } from '../lib/errors';
6
+ import { normalizeBoolean } from '../lib/normalizers';
7
+
8
+ export let manageWorkbook = SlateTool.create(spec, {
9
+ name: 'Manage Workbook',
10
+ key: 'manage_workbook',
11
+ description: `Get details, update properties, delete, refresh extracts, or manage tags for a workbook. Use the **action** field to select the operation.`,
12
+ tags: { destructive: true }
13
+ })
14
+ .input(
15
+ z.object({
16
+ action: z
17
+ .enum(['get', 'update', 'delete', 'refresh', 'addTags', 'removeTags'])
18
+ .describe('Operation to perform'),
19
+ workbookId: z.string().describe('LUID of the workbook'),
20
+ name: z.string().optional().describe('New name (for update)'),
21
+ description: z.string().optional().describe('New description (for update)'),
22
+ projectId: z
23
+ .string()
24
+ .optional()
25
+ .describe('New project LUID to move workbook to (for update)'),
26
+ ownerUserId: z.string().optional().describe('New owner user LUID (for update)'),
27
+ showTabs: z.boolean().optional().describe('Whether to show tabs (for update)'),
28
+ tags: z.array(z.string()).optional().describe('Tags to add or remove')
29
+ })
30
+ )
31
+ .output(
32
+ z.object({
33
+ workbookId: z.string().optional(),
34
+ name: z.string().optional(),
35
+ description: z.string().optional(),
36
+ contentUrl: z.string().optional(),
37
+ showTabs: z.boolean().optional(),
38
+ projectId: z.string().optional(),
39
+ projectName: z.string().optional(),
40
+ ownerId: z.string().optional(),
41
+ createdAt: z.string().optional(),
42
+ updatedAt: z.string().optional(),
43
+ jobId: z.string().optional(),
44
+ deleted: z.boolean().optional(),
45
+ connections: z.array(z.any()).optional(),
46
+ views: z.array(z.any()).optional()
47
+ })
48
+ )
49
+ .handleInvocation(async ctx => {
50
+ let client = createClient(ctx.config, ctx.auth);
51
+ let { action, workbookId } = ctx.input;
52
+
53
+ if (action === 'get') {
54
+ let wb = await client.getWorkbook(workbookId);
55
+ let conns = await client.getWorkbookConnections(workbookId);
56
+ let views = await client.queryViewsForWorkbook(workbookId);
57
+
58
+ return {
59
+ output: {
60
+ workbookId: wb.id,
61
+ name: wb.name,
62
+ description: wb.description,
63
+ contentUrl: wb.contentUrl,
64
+ showTabs: normalizeBoolean(wb.showTabs),
65
+ projectId: wb.project?.id,
66
+ projectName: wb.project?.name,
67
+ ownerId: wb.owner?.id,
68
+ createdAt: wb.createdAt,
69
+ updatedAt: wb.updatedAt,
70
+ connections: conns.connections?.connection || [],
71
+ views: (views.views?.view || []).map((v: any) => ({
72
+ viewId: v.id,
73
+ name: v.name,
74
+ contentUrl: v.contentUrl
75
+ }))
76
+ },
77
+ message: `Retrieved workbook **${wb.name}** with ${(conns.connections?.connection || []).length} connections and ${(views.views?.view || []).length} views.`
78
+ };
79
+ }
80
+
81
+ if (action === 'update') {
82
+ if (
83
+ ctx.input.name === undefined &&
84
+ ctx.input.description === undefined &&
85
+ ctx.input.projectId === undefined &&
86
+ ctx.input.ownerUserId === undefined &&
87
+ ctx.input.showTabs === undefined
88
+ ) {
89
+ throw tableauServiceError('Provide at least one field to update a workbook.');
90
+ }
91
+
92
+ let wb = await client.updateWorkbook(workbookId, {
93
+ name: ctx.input.name,
94
+ description: ctx.input.description,
95
+ projectId: ctx.input.projectId,
96
+ ownerUserId: ctx.input.ownerUserId,
97
+ showTabs: ctx.input.showTabs
98
+ });
99
+
100
+ return {
101
+ output: {
102
+ workbookId: wb.id,
103
+ name: wb.name,
104
+ description: wb.description,
105
+ contentUrl: wb.contentUrl,
106
+ showTabs: normalizeBoolean(wb.showTabs),
107
+ projectId: wb.project?.id,
108
+ projectName: wb.project?.name,
109
+ ownerId: wb.owner?.id,
110
+ updatedAt: wb.updatedAt
111
+ },
112
+ message: `Updated workbook **${wb.name}**.`
113
+ };
114
+ }
115
+
116
+ if (action === 'delete') {
117
+ await client.deleteWorkbook(workbookId);
118
+ return {
119
+ output: { workbookId, deleted: true },
120
+ message: `Deleted workbook \`${workbookId}\`.`
121
+ };
122
+ }
123
+
124
+ if (action === 'refresh') {
125
+ let job = await client.refreshWorkbook(workbookId);
126
+ return {
127
+ output: { workbookId, jobId: job?.id },
128
+ message: `Triggered extract refresh for workbook \`${workbookId}\`. Job ID: \`${job?.id}\`.`
129
+ };
130
+ }
131
+
132
+ if (action === 'addTags') {
133
+ if (!ctx.input.tags?.length) {
134
+ throw tableauServiceError('tags is required for addTags action.');
135
+ }
136
+
137
+ await client.addTagsToWorkbook(workbookId, ctx.input.tags);
138
+ return {
139
+ output: { workbookId },
140
+ message: `Added tags [${ctx.input.tags.join(', ')}] to workbook \`${workbookId}\`.`
141
+ };
142
+ }
143
+
144
+ if (action === 'removeTags') {
145
+ if (!ctx.input.tags?.length) {
146
+ throw tableauServiceError('tags is required for removeTags action.');
147
+ }
148
+
149
+ for (let tag of ctx.input.tags) {
150
+ await client.deleteTagFromWorkbook(workbookId, tag);
151
+ }
152
+ return {
153
+ output: { workbookId },
154
+ message: `Removed tags [${ctx.input.tags.join(', ')}] from workbook \`${workbookId}\`.`
155
+ };
156
+ }
157
+
158
+ throw tableauServiceError(`Unknown action: ${action}`);
159
+ })
160
+ .build();
@@ -0,0 +1,119 @@
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
+ 'webhook-source-event-datasourcecreated': 'datasource.created',
8
+ 'webhook-source-event-datasourceupdated': 'datasource.updated',
9
+ 'webhook-source-event-datasourcedeleted': 'datasource.deleted',
10
+ 'webhook-source-event-datasourcerefreshstarted': 'datasource.refresh_started',
11
+ 'webhook-source-event-datasourcerefreshsucceeded': 'datasource.refresh_succeeded',
12
+ 'webhook-source-event-datasourcerefreshfailed': 'datasource.refresh_failed',
13
+ DatasourceCreated: 'datasource.created',
14
+ DatasourceUpdated: 'datasource.updated',
15
+ DatasourceDeleted: 'datasource.deleted',
16
+ DatasourceRefreshStarted: 'datasource.refresh_started',
17
+ DatasourceRefreshSucceeded: 'datasource.refresh_succeeded',
18
+ DatasourceRefreshFailed: 'datasource.refresh_failed'
19
+ };
20
+
21
+ let webhookEventNames = [
22
+ 'DatasourceCreated',
23
+ 'DatasourceUpdated',
24
+ 'DatasourceDeleted',
25
+ 'DatasourceRefreshStarted',
26
+ 'DatasourceRefreshSucceeded',
27
+ 'DatasourceRefreshFailed'
28
+ ];
29
+
30
+ export let datasourceEvents = SlateTrigger.create(spec, {
31
+ name: 'Data Source Events',
32
+ key: 'datasource_events',
33
+ description:
34
+ 'Triggers when a data source is created, updated, deleted, or when an extract refresh starts, succeeds, or fails.'
35
+ })
36
+ .input(
37
+ z.object({
38
+ eventType: z.string().describe('Tableau webhook event type'),
39
+ resourceId: z.string().describe('LUID of the affected data source'),
40
+ resourceName: z.string().describe('Name of the affected data source'),
41
+ siteId: z.string().describe('LUID of the site'),
42
+ timestamp: z.string().describe('Event timestamp')
43
+ })
44
+ )
45
+ .output(
46
+ z.object({
47
+ datasourceId: z.string().describe('LUID of the affected data source'),
48
+ datasourceName: z.string().describe('Name of the data source'),
49
+ siteId: z.string().describe('LUID of the site'),
50
+ timestamp: z.string().describe('When the event occurred')
51
+ })
52
+ )
53
+ .webhook({
54
+ autoRegisterWebhook: async ctx => {
55
+ let client = createClient(ctx.config, ctx.auth);
56
+ let webhookIds: Record<string, string> = {};
57
+
58
+ for (let eventName of webhookEventNames) {
59
+ let webhook = await client.createWebhook(
60
+ `slates-datasource-${eventName}`,
61
+ eventName,
62
+ ctx.input.webhookBaseUrl
63
+ );
64
+ webhookIds[eventName] = webhook.id;
65
+ }
66
+
67
+ return { registrationDetails: { webhookIds } };
68
+ },
69
+
70
+ autoUnregisterWebhook: async ctx => {
71
+ let client = createClient(ctx.config, ctx.auth);
72
+ let webhookIds = ctx.input.registrationDetails?.webhookIds || {};
73
+
74
+ for (let webhookId of Object.values(webhookIds) as string[]) {
75
+ try {
76
+ await client.deleteWebhook(webhookId);
77
+ } catch (e) {
78
+ // Webhook may already be deleted
79
+ }
80
+ }
81
+ },
82
+
83
+ handleRequest: async ctx => {
84
+ let body = (await ctx.request.json()) as any;
85
+
86
+ let eventType = body.resource_type
87
+ ? `${body.resource_type}${body.event_type ? '_' + body.event_type : ''}`
88
+ : body.eventType || body['webhook-source-event-name'] || 'unknown';
89
+
90
+ return {
91
+ inputs: [
92
+ {
93
+ eventType: eventType,
94
+ resourceId: body.resource_luid || body.resourceId || '',
95
+ resourceName: body.resource_name || body.resourceName || '',
96
+ siteId: body.site_luid || body.siteId || '',
97
+ timestamp: body.created_at || body.timestamp || new Date().toISOString()
98
+ }
99
+ ]
100
+ };
101
+ },
102
+
103
+ handleEvent: async ctx => {
104
+ let mappedType =
105
+ eventNameMap[ctx.input.eventType] || `datasource.${ctx.input.eventType}`;
106
+
107
+ return {
108
+ type: mappedType,
109
+ id: `${ctx.input.resourceId}-${ctx.input.timestamp}`,
110
+ output: {
111
+ datasourceId: ctx.input.resourceId,
112
+ datasourceName: ctx.input.resourceName,
113
+ siteId: ctx.input.siteId,
114
+ timestamp: ctx.input.timestamp
115
+ }
116
+ };
117
+ }
118
+ })
119
+ .build();
@@ -0,0 +1,6 @@
1
+ export * from './datasource-events';
2
+ export * from './workbook-events';
3
+ export * from './user-events';
4
+ export * from './label-events';
5
+ export * from './site-events';
6
+ export * from './view-events';