@slates/provider-handler 1.0.0-rc.6 → 1.0.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/dist/index.cjs +1000 -2
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.module.js +972 -2
- package/package.json +10 -9
- package/src/index.ts +550 -84
- package/src/spec.ts +9 -8
- package/src/validation.ts +1 -1
- package/dist/action/action.d.ts +0 -90
- package/dist/action/action.d.ts.map +0 -1
- package/dist/action/builder.d.ts +0 -27
- package/dist/action/builder.d.ts.map +0 -1
- package/dist/action/index.d.ts +0 -5
- package/dist/action/index.d.ts.map +0 -1
- package/dist/action/tool.d.ts +0 -11
- package/dist/action/tool.d.ts.map +0 -1
- package/dist/action/trigger.d.ts +0 -14
- package/dist/action/trigger.d.ts.map +0 -1
- package/dist/auth/auth.d.ts +0 -26
- package/dist/auth/auth.d.ts.map +0 -1
- package/dist/auth/index.d.ts +0 -3
- package/dist/auth/index.d.ts.map +0 -1
- package/dist/auth/types.d.ts +0 -148
- package/dist/auth/types.d.ts.map +0 -1
- package/dist/axios/index.d.ts +0 -4
- package/dist/axios/index.d.ts.map +0 -1
- package/dist/config/config.d.ts +0 -22
- package/dist/config/config.d.ts.map +0 -1
- package/dist/config/index.d.ts +0 -2
- package/dist/config/index.d.ts.map +0 -1
- package/dist/context/context.d.ts +0 -20
- package/dist/context/context.d.ts.map +0 -1
- package/dist/context/hook.d.ts +0 -4
- package/dist/context/hook.d.ts.map +0 -1
- package/dist/context/index.d.ts +0 -2
- package/dist/context/index.d.ts.map +0 -1
- package/dist/error/base.d.ts +0 -5
- package/dist/error/base.d.ts.map +0 -1
- package/dist/error/declaration.d.ts +0 -6
- package/dist/error/declaration.d.ts.map +0 -1
- package/dist/error/index.d.ts +0 -3
- package/dist/error/index.d.ts.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.modern.js +0 -2
- package/dist/index.modern.js.map +0 -1
- package/dist/index.module.js.map +0 -1
- package/dist/index.umd.js +0 -2
- package/dist/index.umd.js.map +0 -1
- package/dist/spec.d.ts +0 -14
- package/dist/spec.d.ts.map +0 -1
- package/dist/specification/index.d.ts +0 -3
- package/dist/specification/index.d.ts.map +0 -1
- package/dist/specification/slate.d.ts +0 -15
- package/dist/specification/slate.d.ts.map +0 -1
- package/dist/specification/specification.d.ts +0 -30
- package/dist/specification/specification.d.ts.map +0 -1
- package/dist/specification/zero.d.ts +0 -13
- package/dist/specification/zero.d.ts.map +0 -1
- package/dist/state.d.ts +0 -8
- package/dist/state.d.ts.map +0 -1
- package/dist/tokens.d.ts +0 -34
- package/dist/tokens.d.ts.map +0 -1
- package/dist/validation.d.ts +0 -5
- package/dist/validation.d.ts.map +0 -1
package/src/index.ts
CHANGED
|
@@ -1,16 +1,111 @@
|
|
|
1
1
|
import { badRequestError, preconditionFailedError, ServiceError } from '@lowerdeck/error';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
createSlatesProviderProtoHandler,
|
|
4
|
+
SLATES_PROTOCOL_VERSION,
|
|
5
|
+
type SlatesParticipant
|
|
6
|
+
} from '@slates/proto';
|
|
3
7
|
import {
|
|
4
8
|
runWithContext,
|
|
5
|
-
Slate,
|
|
9
|
+
type Slate,
|
|
10
|
+
type SlateAttachment,
|
|
6
11
|
SlateContext,
|
|
7
12
|
SlateLogger,
|
|
8
|
-
SlateLogListener
|
|
13
|
+
type SlateLogListener
|
|
9
14
|
} from '@slates/provider';
|
|
10
15
|
import { getAction, getActionWithType, getAuthMethod, mapAction, mapAuthMethod } from './spec';
|
|
11
16
|
import { State } from './state';
|
|
12
17
|
import { toJsonSchema, validate } from './validation';
|
|
13
18
|
|
|
19
|
+
let isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
20
|
+
typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
21
|
+
|
|
22
|
+
let getObjectKeyCount = (value: unknown) =>
|
|
23
|
+
isRecord(value) ? Object.keys(value).length : undefined;
|
|
24
|
+
|
|
25
|
+
let DOWNLOAD_ATTACHMENT_URL_KEYS = new Set([
|
|
26
|
+
'downloadUrl',
|
|
27
|
+
'fileUrl',
|
|
28
|
+
'temporaryDownloadUrl',
|
|
29
|
+
'webContentLink'
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
let isAttachmentUrl = (value: string) => /^[a-z][a-z0-9+.-]*:\/\//i.test(value);
|
|
33
|
+
|
|
34
|
+
let collectOutputUrlAttachments = (
|
|
35
|
+
value: unknown,
|
|
36
|
+
seen = new Set<string>()
|
|
37
|
+
): SlateAttachment[] => {
|
|
38
|
+
if (Array.isArray(value)) {
|
|
39
|
+
return value.flatMap(item => collectOutputUrlAttachments(item, seen));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!isRecord(value)) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let attachments: SlateAttachment[] = [];
|
|
47
|
+
|
|
48
|
+
for (let [key, nestedValue] of Object.entries(value)) {
|
|
49
|
+
if (
|
|
50
|
+
DOWNLOAD_ATTACHMENT_URL_KEYS.has(key) &&
|
|
51
|
+
typeof nestedValue === 'string' &&
|
|
52
|
+
nestedValue.length > 0 &&
|
|
53
|
+
isAttachmentUrl(nestedValue) &&
|
|
54
|
+
!seen.has(nestedValue)
|
|
55
|
+
) {
|
|
56
|
+
seen.add(nestedValue);
|
|
57
|
+
attachments.push({
|
|
58
|
+
content: {
|
|
59
|
+
type: 'url',
|
|
60
|
+
url: nestedValue
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
attachments.push(...collectOutputUrlAttachments(nestedValue, seen));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return attachments;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
let mergeAttachments = (
|
|
73
|
+
explicitAttachments: SlateAttachment[] | undefined,
|
|
74
|
+
output: unknown
|
|
75
|
+
): SlateAttachment[] | undefined => {
|
|
76
|
+
let attachments = [...(explicitAttachments ?? [])];
|
|
77
|
+
let seen = new Set(attachments.map(attachment => JSON.stringify(attachment)));
|
|
78
|
+
|
|
79
|
+
for (let attachment of collectOutputUrlAttachments(output)) {
|
|
80
|
+
let key = JSON.stringify(attachment);
|
|
81
|
+
if (seen.has(key)) continue;
|
|
82
|
+
seen.add(key);
|
|
83
|
+
attachments.push(attachment);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return attachments.length > 0 ? attachments : undefined;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
let toErrorMetadata = (error: unknown) => {
|
|
90
|
+
if (error instanceof Error) {
|
|
91
|
+
return {
|
|
92
|
+
errorName: error.name,
|
|
93
|
+
errorMessage: error.message,
|
|
94
|
+
errorStack: error.stack
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
errorValue: String(error)
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
let formatEntityLabel = (name: string, key: string) => `"${name}" (${key})`;
|
|
104
|
+
let resolveTraceMessage = <ResultType>(
|
|
105
|
+
message: string | ((result: ResultType) => string),
|
|
106
|
+
result: ResultType
|
|
107
|
+
) => (typeof message === 'function' ? message(result) : message);
|
|
108
|
+
|
|
14
109
|
export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
15
110
|
slate: Slate<ConfigType, AuthType>,
|
|
16
111
|
listeners: SlateLogListener[]
|
|
@@ -21,10 +116,69 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
21
116
|
|
|
22
117
|
let auth = new State<{ authenticationMethodId: string; output: AuthType } | null>(null);
|
|
23
118
|
let config = new State<{ value: ConfigType } | null>(null);
|
|
24
|
-
|
|
25
119
|
let session = new State<{ id: string; state: any } | null>(null);
|
|
26
120
|
|
|
27
121
|
let logger = new SlateLogger(listeners);
|
|
122
|
+
let providerTrace = {
|
|
123
|
+
providerId: slate.spec.key,
|
|
124
|
+
providerName: slate.spec.name
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
let traceProviderCall = async <ResultType>(
|
|
128
|
+
trace: {
|
|
129
|
+
component: 'config' | 'auth' | 'action';
|
|
130
|
+
functionName: string;
|
|
131
|
+
message: string;
|
|
132
|
+
successMessage: string | ((result: ResultType) => string);
|
|
133
|
+
errorMessage?: string;
|
|
134
|
+
metadata?: Record<string, unknown>;
|
|
135
|
+
onSuccess?: (result: ResultType) => Record<string, unknown> | undefined;
|
|
136
|
+
},
|
|
137
|
+
handler: () => Promise<ResultType>
|
|
138
|
+
): Promise<ResultType> => {
|
|
139
|
+
let startedAt = Date.now();
|
|
140
|
+
|
|
141
|
+
logger.info({
|
|
142
|
+
...providerTrace,
|
|
143
|
+
...trace.metadata,
|
|
144
|
+
component: trace.component,
|
|
145
|
+
functionName: trace.functionName,
|
|
146
|
+
phase: 'start',
|
|
147
|
+
message: trace.message
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
let result = await handler();
|
|
152
|
+
let successMessage = resolveTraceMessage(trace.successMessage, result);
|
|
153
|
+
|
|
154
|
+
logger.info({
|
|
155
|
+
...providerTrace,
|
|
156
|
+
...trace.metadata,
|
|
157
|
+
...(trace.onSuccess?.(result) ?? {}),
|
|
158
|
+
component: trace.component,
|
|
159
|
+
functionName: trace.functionName,
|
|
160
|
+
phase: 'success',
|
|
161
|
+
durationMs: Date.now() - startedAt,
|
|
162
|
+
message: successMessage
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
return result;
|
|
166
|
+
} catch (error) {
|
|
167
|
+
logger.error({
|
|
168
|
+
...providerTrace,
|
|
169
|
+
...trace.metadata,
|
|
170
|
+
...toErrorMetadata(error),
|
|
171
|
+
component: trace.component,
|
|
172
|
+
functionName: trace.functionName,
|
|
173
|
+
phase: 'error',
|
|
174
|
+
durationMs: Date.now() - startedAt,
|
|
175
|
+
message:
|
|
176
|
+
trace.errorMessage ??
|
|
177
|
+
`${typeof trace.successMessage === 'string' ? trace.successMessage : trace.message} failed`
|
|
178
|
+
});
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
28
182
|
|
|
29
183
|
let getContextBasic = () => {
|
|
30
184
|
let currentProtocol = protocol.get();
|
|
@@ -72,6 +226,13 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
72
226
|
};
|
|
73
227
|
|
|
74
228
|
let getEmptyContext = () => new SlateContext({}, {}, {}, slate.spec as any, logger);
|
|
229
|
+
let withRequestTraces = <Result extends Record<string, any>>(
|
|
230
|
+
context: SlateContext<any, any, any>,
|
|
231
|
+
result: Result
|
|
232
|
+
) => {
|
|
233
|
+
let requestTraces = context.getHttpTraces();
|
|
234
|
+
return requestTraces.length > 0 ? { ...result, requestTraces } : result;
|
|
235
|
+
};
|
|
75
236
|
|
|
76
237
|
manager.onNotification('slates/hello', async ({ params }) => {
|
|
77
238
|
protocol.set(params.protocol);
|
|
@@ -141,15 +302,37 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
141
302
|
return { success: true, config: newConfig };
|
|
142
303
|
}
|
|
143
304
|
|
|
144
|
-
let
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
305
|
+
let context = getEmptyContext();
|
|
306
|
+
let updatedConfig = await traceProviderCall<{ config?: ConfigType } | undefined>(
|
|
307
|
+
{
|
|
308
|
+
component: 'config',
|
|
309
|
+
functionName: 'configChanged',
|
|
310
|
+
message: 'Running config change handler',
|
|
311
|
+
successMessage: 'Config change handler completed',
|
|
312
|
+
metadata: {
|
|
313
|
+
hasPreviousConfig: params.previousConfig !== null,
|
|
314
|
+
newConfigKeyCount: getObjectKeyCount(newConfig)
|
|
315
|
+
},
|
|
316
|
+
onSuccess: result => ({
|
|
317
|
+
returnedConfig: !!result?.config
|
|
318
|
+
})
|
|
319
|
+
},
|
|
320
|
+
() =>
|
|
321
|
+
runWithContext(context, async () =>
|
|
322
|
+
configChanged({
|
|
323
|
+
previousConfig: params.previousConfig as ConfigType | null,
|
|
324
|
+
newConfig
|
|
325
|
+
})
|
|
326
|
+
)
|
|
327
|
+
);
|
|
148
328
|
|
|
149
|
-
return
|
|
329
|
+
return withRequestTraces(context, {
|
|
330
|
+
success: true,
|
|
331
|
+
config: (updatedConfig?.config ?? newConfig) as Record<string, any>
|
|
332
|
+
});
|
|
150
333
|
});
|
|
151
334
|
|
|
152
|
-
manager.onRequest('slates/config.get_default', async (
|
|
335
|
+
manager.onRequest('slates/config.get_default', async () => {
|
|
153
336
|
getContextBasic();
|
|
154
337
|
|
|
155
338
|
let getDefaultConfig = slate.spec.config.handlers.getDefaultConfig;
|
|
@@ -157,21 +340,35 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
157
340
|
return { config: null };
|
|
158
341
|
}
|
|
159
342
|
|
|
160
|
-
let
|
|
161
|
-
|
|
343
|
+
let context = getEmptyContext();
|
|
344
|
+
let defaultConfig = await traceProviderCall<ConfigType>(
|
|
345
|
+
{
|
|
346
|
+
component: 'config',
|
|
347
|
+
functionName: 'getDefaultConfig',
|
|
348
|
+
message: 'Getting default config',
|
|
349
|
+
successMessage: 'Default config retrieved',
|
|
350
|
+
onSuccess: result => ({
|
|
351
|
+
configKeyCount: getObjectKeyCount(result)
|
|
352
|
+
})
|
|
353
|
+
},
|
|
354
|
+
() => runWithContext(context, async () => getDefaultConfig())
|
|
355
|
+
);
|
|
356
|
+
return withRequestTraces(context, {
|
|
357
|
+
config: (defaultConfig ?? null) as Record<string, any> | null
|
|
358
|
+
});
|
|
162
359
|
});
|
|
163
360
|
|
|
164
|
-
manager.onRequest('slates/config.schema.get', async (
|
|
361
|
+
manager.onRequest('slates/config.schema.get', async () => {
|
|
165
362
|
getContextBasic();
|
|
166
363
|
|
|
167
364
|
return { schema: toJsonSchema(slate.spec.configSchema) };
|
|
168
365
|
});
|
|
169
366
|
|
|
170
|
-
manager.onRequest('slates/provider.identify', async (
|
|
367
|
+
manager.onRequest('slates/provider.identify', async () => {
|
|
171
368
|
getContextBasic();
|
|
172
369
|
|
|
173
370
|
return {
|
|
174
|
-
protocol:
|
|
371
|
+
protocol: SLATES_PROTOCOL_VERSION,
|
|
175
372
|
provider: {
|
|
176
373
|
type: 'provider',
|
|
177
374
|
id: slate.spec.key,
|
|
@@ -182,7 +379,7 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
182
379
|
};
|
|
183
380
|
});
|
|
184
381
|
|
|
185
|
-
manager.onRequest('slates/auth.methods.list', async (
|
|
382
|
+
manager.onRequest('slates/auth.methods.list', async () => {
|
|
186
383
|
getContextBasic();
|
|
187
384
|
|
|
188
385
|
return {
|
|
@@ -207,9 +404,25 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
207
404
|
return { input: null };
|
|
208
405
|
}
|
|
209
406
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
407
|
+
let context = getEmptyContext();
|
|
408
|
+
let input = await traceProviderCall(
|
|
409
|
+
{
|
|
410
|
+
component: 'auth',
|
|
411
|
+
functionName: 'getDefaultInput',
|
|
412
|
+
message: 'Getting default authentication input',
|
|
413
|
+
successMessage: 'Default authentication input retrieved',
|
|
414
|
+
metadata: {
|
|
415
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
416
|
+
authenticationMethodName: authMethod.name
|
|
417
|
+
},
|
|
418
|
+
onSuccess: result => ({
|
|
419
|
+
inputKeyCount: getObjectKeyCount(result)
|
|
420
|
+
})
|
|
421
|
+
},
|
|
422
|
+
() => runWithContext(context, () => authMethod.getDefaultInput!())
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
return withRequestTraces(context, { input });
|
|
213
426
|
});
|
|
214
427
|
|
|
215
428
|
manager.onRequest('slates/auth.input.changed', async ({ params }) => {
|
|
@@ -220,14 +433,36 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
220
433
|
return { success: true, input: params.newInput };
|
|
221
434
|
}
|
|
222
435
|
|
|
223
|
-
let
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
436
|
+
let context = getEmptyContext();
|
|
437
|
+
let updatedInput = await traceProviderCall(
|
|
438
|
+
{
|
|
439
|
+
component: 'auth',
|
|
440
|
+
functionName: 'onInputChanged',
|
|
441
|
+
message: 'Running authentication input change handler',
|
|
442
|
+
successMessage: 'Authentication input change handler completed',
|
|
443
|
+
metadata: {
|
|
444
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
445
|
+
authenticationMethodName: authMethod.name,
|
|
446
|
+
hasPreviousInput: params.previousInput !== null,
|
|
447
|
+
newInputKeyCount: getObjectKeyCount(params.newInput)
|
|
448
|
+
},
|
|
449
|
+
onSuccess: result => ({
|
|
450
|
+
returnedInput: !!result?.input
|
|
451
|
+
})
|
|
452
|
+
},
|
|
453
|
+
() =>
|
|
454
|
+
runWithContext(context, () =>
|
|
455
|
+
authMethod.onInputChanged!({
|
|
456
|
+
previousInput: params.previousInput as any | null,
|
|
457
|
+
newInput: params.newInput
|
|
458
|
+
})
|
|
459
|
+
)
|
|
228
460
|
);
|
|
229
461
|
|
|
230
|
-
return
|
|
462
|
+
return withRequestTraces(context, {
|
|
463
|
+
success: true,
|
|
464
|
+
input: updatedInput?.input ?? params.newInput
|
|
465
|
+
});
|
|
231
466
|
});
|
|
232
467
|
|
|
233
468
|
manager.onRequest('slates/auth.output.get', async ({ params }) => {
|
|
@@ -246,10 +481,25 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
246
481
|
}
|
|
247
482
|
|
|
248
483
|
if ('getOutput' in authMethod) {
|
|
249
|
-
let
|
|
250
|
-
|
|
484
|
+
let context = getEmptyContext();
|
|
485
|
+
let outputRes = await traceProviderCall(
|
|
486
|
+
{
|
|
487
|
+
component: 'auth',
|
|
488
|
+
functionName: 'getOutput',
|
|
489
|
+
message: 'Getting authentication output',
|
|
490
|
+
successMessage: 'Authentication output retrieved',
|
|
491
|
+
metadata: {
|
|
492
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
493
|
+
authenticationMethodName: authMethod.name,
|
|
494
|
+
inputKeyCount: getObjectKeyCount(input)
|
|
495
|
+
},
|
|
496
|
+
onSuccess: result => ({
|
|
497
|
+
outputKeyCount: getObjectKeyCount(result.output)
|
|
498
|
+
})
|
|
499
|
+
},
|
|
500
|
+
() => runWithContext(context, () => authMethod.getOutput({ input }))
|
|
251
501
|
);
|
|
252
|
-
return { output: outputRes.output };
|
|
502
|
+
return withRequestTraces(context, { output: outputRes.output });
|
|
253
503
|
}
|
|
254
504
|
|
|
255
505
|
return { output: input as any };
|
|
@@ -260,23 +510,45 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
260
510
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
261
511
|
|
|
262
512
|
if ('handleCallback' in authMethod) {
|
|
263
|
-
let
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
513
|
+
let context = getEmptyContext();
|
|
514
|
+
let callbackRes = await traceProviderCall(
|
|
515
|
+
{
|
|
516
|
+
component: 'auth',
|
|
517
|
+
functionName: 'handleCallback',
|
|
518
|
+
message: 'Handling authentication callback',
|
|
519
|
+
successMessage: 'Authentication callback handled',
|
|
520
|
+
metadata: {
|
|
521
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
522
|
+
authenticationMethodName: authMethod.name,
|
|
523
|
+
scopeCount: params.scopes.length,
|
|
524
|
+
hasCallbackState: !!params.callbackState
|
|
525
|
+
},
|
|
526
|
+
onSuccess: result => ({
|
|
527
|
+
outputKeyCount: getObjectKeyCount(result.output),
|
|
528
|
+
returnedInput: !!result.input,
|
|
529
|
+
returnedScopeCount: result.scopes?.length
|
|
530
|
+
})
|
|
531
|
+
},
|
|
532
|
+
() =>
|
|
533
|
+
runWithContext(context, () =>
|
|
534
|
+
authMethod.handleCallback({
|
|
535
|
+
code: params.code,
|
|
536
|
+
state: params.state,
|
|
537
|
+
redirectUri: params.redirectUri,
|
|
538
|
+
input: params.input,
|
|
539
|
+
clientId: params.clientId,
|
|
540
|
+
clientSecret: params.clientSecret,
|
|
541
|
+
scopes: params.scopes,
|
|
542
|
+
callbackState: params.callbackState || {}
|
|
543
|
+
})
|
|
544
|
+
)
|
|
274
545
|
);
|
|
275
546
|
|
|
276
|
-
return {
|
|
547
|
+
return withRequestTraces(context, {
|
|
277
548
|
output: callbackRes.output,
|
|
278
|
-
input: callbackRes.input
|
|
279
|
-
|
|
549
|
+
input: callbackRes.input,
|
|
550
|
+
scopes: callbackRes.scopes
|
|
551
|
+
});
|
|
280
552
|
}
|
|
281
553
|
|
|
282
554
|
throw new ServiceError(
|
|
@@ -291,22 +563,42 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
291
563
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
292
564
|
|
|
293
565
|
if ('getAuthorizationUrl' in authMethod) {
|
|
294
|
-
let
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
566
|
+
let context = getEmptyContext();
|
|
567
|
+
let urlRes = await traceProviderCall(
|
|
568
|
+
{
|
|
569
|
+
component: 'auth',
|
|
570
|
+
functionName: 'getAuthorizationUrl',
|
|
571
|
+
message: 'Getting authentication authorization URL',
|
|
572
|
+
successMessage: 'Authentication authorization URL retrieved',
|
|
573
|
+
metadata: {
|
|
574
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
575
|
+
authenticationMethodName: authMethod.name,
|
|
576
|
+
scopeCount: params.scopes.length,
|
|
577
|
+
inputKeyCount: getObjectKeyCount(params.input)
|
|
578
|
+
},
|
|
579
|
+
onSuccess: result => ({
|
|
580
|
+
returnedInput: !!result.input,
|
|
581
|
+
hasCallbackState: !!result.callbackState
|
|
582
|
+
})
|
|
583
|
+
},
|
|
584
|
+
() =>
|
|
585
|
+
runWithContext(context, () =>
|
|
586
|
+
authMethod.getAuthorizationUrl({
|
|
587
|
+
redirectUri: params.redirectUri,
|
|
588
|
+
state: params.state,
|
|
589
|
+
input: params.input,
|
|
590
|
+
clientId: params.clientId,
|
|
591
|
+
clientSecret: params.clientSecret,
|
|
592
|
+
scopes: params.scopes
|
|
593
|
+
})
|
|
594
|
+
)
|
|
303
595
|
);
|
|
304
596
|
|
|
305
|
-
return {
|
|
597
|
+
return withRequestTraces(context, {
|
|
306
598
|
authorizationUrl: urlRes.url,
|
|
307
599
|
input: urlRes.input,
|
|
308
600
|
callbackState: urlRes.callbackState
|
|
309
|
-
};
|
|
601
|
+
});
|
|
310
602
|
}
|
|
311
603
|
|
|
312
604
|
throw new ServiceError(
|
|
@@ -321,17 +613,39 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
321
613
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
322
614
|
|
|
323
615
|
if (authMethod.getProfile) {
|
|
324
|
-
let
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
616
|
+
let context = getEmptyContext();
|
|
617
|
+
let profileRes = await traceProviderCall(
|
|
618
|
+
{
|
|
619
|
+
component: 'auth',
|
|
620
|
+
functionName: 'getProfile',
|
|
621
|
+
message: 'Getting authentication profile',
|
|
622
|
+
successMessage: 'Authentication profile retrieved',
|
|
623
|
+
metadata: {
|
|
624
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
625
|
+
authenticationMethodName: authMethod.name,
|
|
626
|
+
scopeCount: params.scopes.length,
|
|
627
|
+
inputKeyCount: getObjectKeyCount(params.input),
|
|
628
|
+
outputKeyCount: getObjectKeyCount(params.output)
|
|
629
|
+
},
|
|
630
|
+
onSuccess: result => ({
|
|
631
|
+
profileKeyCount: getObjectKeyCount(result.profile)
|
|
632
|
+
})
|
|
633
|
+
},
|
|
634
|
+
() =>
|
|
635
|
+
runWithContext(
|
|
636
|
+
context,
|
|
637
|
+
() =>
|
|
638
|
+
authMethod.getProfile!({
|
|
639
|
+
output: params.output as any,
|
|
640
|
+
input: params.input,
|
|
641
|
+
scopes: params.scopes
|
|
642
|
+
})!
|
|
643
|
+
)
|
|
330
644
|
);
|
|
331
645
|
|
|
332
|
-
return {
|
|
646
|
+
return withRequestTraces(context, {
|
|
333
647
|
profile: profileRes.profile
|
|
334
|
-
};
|
|
648
|
+
});
|
|
335
649
|
}
|
|
336
650
|
|
|
337
651
|
throw new ServiceError(
|
|
@@ -346,20 +660,41 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
346
660
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
347
661
|
|
|
348
662
|
if ('handleTokenRefresh' in authMethod && authMethod.handleTokenRefresh) {
|
|
349
|
-
let
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
663
|
+
let context = getEmptyContext();
|
|
664
|
+
let refreshRes = await traceProviderCall(
|
|
665
|
+
{
|
|
666
|
+
component: 'auth',
|
|
667
|
+
functionName: 'handleTokenRefresh',
|
|
668
|
+
message: 'Refreshing authentication token',
|
|
669
|
+
successMessage: 'Authentication token refreshed',
|
|
670
|
+
metadata: {
|
|
671
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
672
|
+
authenticationMethodName: authMethod.name,
|
|
673
|
+
scopeCount: params.scopes.length,
|
|
674
|
+
inputKeyCount: getObjectKeyCount(params.input),
|
|
675
|
+
outputKeyCount: getObjectKeyCount(params.output)
|
|
676
|
+
},
|
|
677
|
+
onSuccess: result => ({
|
|
678
|
+
refreshedOutputKeyCount: getObjectKeyCount(result.output),
|
|
679
|
+
returnedInput: !!result.input
|
|
680
|
+
})
|
|
681
|
+
},
|
|
682
|
+
() =>
|
|
683
|
+
runWithContext(context, () =>
|
|
684
|
+
authMethod.handleTokenRefresh!({
|
|
685
|
+
output: params.output as any,
|
|
686
|
+
input: params.input,
|
|
687
|
+
clientId: params.clientId,
|
|
688
|
+
clientSecret: params.clientSecret,
|
|
689
|
+
scopes: params.scopes
|
|
690
|
+
})
|
|
691
|
+
)
|
|
357
692
|
);
|
|
358
693
|
|
|
359
|
-
return {
|
|
694
|
+
return withRequestTraces(context, {
|
|
360
695
|
output: refreshRes.output,
|
|
361
696
|
input: refreshRes.input
|
|
362
|
-
};
|
|
697
|
+
});
|
|
363
698
|
}
|
|
364
699
|
|
|
365
700
|
throw new ServiceError(
|
|
@@ -369,7 +704,7 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
369
704
|
);
|
|
370
705
|
});
|
|
371
706
|
|
|
372
|
-
manager.onRequest('slates/actions.list', async (
|
|
707
|
+
manager.onRequest('slates/actions.list', async () => {
|
|
373
708
|
getContextBasic();
|
|
374
709
|
|
|
375
710
|
return {
|
|
@@ -398,9 +733,34 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
398
733
|
);
|
|
399
734
|
|
|
400
735
|
let context = new SlateContext(ctx.config, input, ctx.auth?.output!, slate.spec, logger);
|
|
401
|
-
let res = await
|
|
736
|
+
let res = await traceProviderCall(
|
|
737
|
+
{
|
|
738
|
+
component: 'action',
|
|
739
|
+
functionName: 'handleInvocation',
|
|
740
|
+
message: `Starting tool ${formatEntityLabel(action.name, action.key)}`,
|
|
741
|
+
successMessage: `Completed tool ${formatEntityLabel(action.name, action.key)}`,
|
|
742
|
+
errorMessage: `Tool ${formatEntityLabel(action.name, action.key)} failed`,
|
|
743
|
+
metadata: {
|
|
744
|
+
actionId: action.key,
|
|
745
|
+
actionName: action.name,
|
|
746
|
+
actionType: action.type,
|
|
747
|
+
inputKeyCount: getObjectKeyCount(input)
|
|
748
|
+
},
|
|
749
|
+
onSuccess: result => ({
|
|
750
|
+
hasMessage: !!result.message,
|
|
751
|
+
actionResultMessage: result.message,
|
|
752
|
+
outputKeyCount: getObjectKeyCount(result.output),
|
|
753
|
+
attachmentCount: result.attachments?.length
|
|
754
|
+
})
|
|
755
|
+
},
|
|
756
|
+
() => runWithContext(context, () => action.handleInvocation(context))
|
|
757
|
+
);
|
|
402
758
|
|
|
403
|
-
return
|
|
759
|
+
return withRequestTraces(context, {
|
|
760
|
+
output: res.output,
|
|
761
|
+
message: res.message,
|
|
762
|
+
attachments: mergeAttachments(res.attachments, res.output)
|
|
763
|
+
});
|
|
404
764
|
});
|
|
405
765
|
|
|
406
766
|
manager.onRequest('slates/action.trigger.map_event', async ({ params }) => {
|
|
@@ -415,9 +775,30 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
415
775
|
);
|
|
416
776
|
|
|
417
777
|
let context = new SlateContext(ctx.config, input, ctx.auth?.output!, slate.spec, logger);
|
|
418
|
-
let res = await
|
|
778
|
+
let res = await traceProviderCall(
|
|
779
|
+
{
|
|
780
|
+
component: 'action',
|
|
781
|
+
functionName: 'handleEvent',
|
|
782
|
+
message: `Mapping event for trigger ${formatEntityLabel(action.name, action.key)}`,
|
|
783
|
+
successMessage: result =>
|
|
784
|
+
`Mapped trigger event "${result.type}" for ${formatEntityLabel(action.name, action.key)}`,
|
|
785
|
+
errorMessage: `Trigger ${formatEntityLabel(action.name, action.key)} failed while mapping an event`,
|
|
786
|
+
metadata: {
|
|
787
|
+
actionId: action.key,
|
|
788
|
+
actionName: action.name,
|
|
789
|
+
actionType: action.type,
|
|
790
|
+
inputKeyCount: getObjectKeyCount(input)
|
|
791
|
+
},
|
|
792
|
+
onSuccess: result => ({
|
|
793
|
+
eventType: result.type,
|
|
794
|
+
hasEventId: !!result.id,
|
|
795
|
+
outputKeyCount: getObjectKeyCount(result.output)
|
|
796
|
+
})
|
|
797
|
+
},
|
|
798
|
+
() => runWithContext(context, () => action.handleEvent(context))
|
|
799
|
+
);
|
|
419
800
|
|
|
420
|
-
return { id: res.id, type: res.type, output: res.output };
|
|
801
|
+
return withRequestTraces(context, { id: res.id, type: res.type, output: res.output });
|
|
421
802
|
});
|
|
422
803
|
|
|
423
804
|
manager.onRequest('slates/action.trigger.poll_events', async ({ params }) => {
|
|
@@ -439,9 +820,32 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
439
820
|
slate.spec,
|
|
440
821
|
logger
|
|
441
822
|
);
|
|
442
|
-
let res = await
|
|
823
|
+
let res = await traceProviderCall(
|
|
824
|
+
{
|
|
825
|
+
component: 'action',
|
|
826
|
+
functionName: 'pollEvents',
|
|
827
|
+
message: `Polling events for trigger ${formatEntityLabel(action.name, action.key)}`,
|
|
828
|
+
successMessage: result =>
|
|
829
|
+
`Polled ${result.inputs.length} event(s) for trigger ${formatEntityLabel(action.name, action.key)}`,
|
|
830
|
+
errorMessage: `Trigger ${formatEntityLabel(action.name, action.key)} failed while polling events`,
|
|
831
|
+
metadata: {
|
|
832
|
+
actionId: action.key,
|
|
833
|
+
actionName: action.name,
|
|
834
|
+
actionType: action.type,
|
|
835
|
+
hasPreviousState: params.state !== null
|
|
836
|
+
},
|
|
837
|
+
onSuccess: result => ({
|
|
838
|
+
inputCount: result.inputs.length,
|
|
839
|
+
hasUpdatedState: result.updatedState !== undefined
|
|
840
|
+
})
|
|
841
|
+
},
|
|
842
|
+
() => runWithContext(context, () => action.pollEvents!(context))
|
|
843
|
+
);
|
|
443
844
|
|
|
444
|
-
return
|
|
845
|
+
return withRequestTraces(context, {
|
|
846
|
+
inputs: res.inputs,
|
|
847
|
+
updatedState: res.updatedState
|
|
848
|
+
});
|
|
445
849
|
});
|
|
446
850
|
|
|
447
851
|
manager.onRequest('slates/action.trigger.webhook_handle', async ({ params }) => {
|
|
@@ -471,9 +875,34 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
471
875
|
slate.spec,
|
|
472
876
|
logger
|
|
473
877
|
);
|
|
474
|
-
let res = await
|
|
878
|
+
let res = await traceProviderCall(
|
|
879
|
+
{
|
|
880
|
+
component: 'action',
|
|
881
|
+
functionName: 'handleRequest',
|
|
882
|
+
message: `Handling webhook request for trigger ${formatEntityLabel(action.name, action.key)}`,
|
|
883
|
+
successMessage: result =>
|
|
884
|
+
`Received ${result.inputs.length} webhook event(s) for trigger ${formatEntityLabel(action.name, action.key)}`,
|
|
885
|
+
errorMessage: `Trigger ${formatEntityLabel(action.name, action.key)} failed while handling a webhook request`,
|
|
886
|
+
metadata: {
|
|
887
|
+
actionId: action.key,
|
|
888
|
+
actionName: action.name,
|
|
889
|
+
actionType: action.type,
|
|
890
|
+
requestMethod: params.method,
|
|
891
|
+
hasRequestBody: !!params.body,
|
|
892
|
+
hasPreviousState: params.state !== null
|
|
893
|
+
},
|
|
894
|
+
onSuccess: result => ({
|
|
895
|
+
inputCount: result.inputs.length,
|
|
896
|
+
hasUpdatedState: result.updatedState !== undefined
|
|
897
|
+
})
|
|
898
|
+
},
|
|
899
|
+
() => runWithContext(context, () => action.handleRequest!(context))
|
|
900
|
+
);
|
|
475
901
|
|
|
476
|
-
return
|
|
902
|
+
return withRequestTraces(context, {
|
|
903
|
+
inputs: res.inputs,
|
|
904
|
+
updatedState: res.updatedState
|
|
905
|
+
});
|
|
477
906
|
});
|
|
478
907
|
|
|
479
908
|
manager.onRequest('slates/action.trigger.webhook_register', async ({ params }) => {
|
|
@@ -495,9 +924,30 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
495
924
|
slate.spec,
|
|
496
925
|
logger
|
|
497
926
|
);
|
|
498
|
-
let res = await
|
|
927
|
+
let res = await traceProviderCall(
|
|
928
|
+
{
|
|
929
|
+
component: 'action',
|
|
930
|
+
functionName: 'autoRegisterWebhook',
|
|
931
|
+
message: `Registering webhook for trigger ${formatEntityLabel(action.name, action.key)}`,
|
|
932
|
+
successMessage: `Registered webhook for trigger ${formatEntityLabel(action.name, action.key)}`,
|
|
933
|
+
errorMessage: `Trigger ${formatEntityLabel(action.name, action.key)} failed while registering a webhook`,
|
|
934
|
+
metadata: {
|
|
935
|
+
actionId: action.key,
|
|
936
|
+
actionName: action.name,
|
|
937
|
+
actionType: action.type
|
|
938
|
+
},
|
|
939
|
+
onSuccess: result => ({
|
|
940
|
+
hasRegistrationDetails: result.registrationDetails !== undefined,
|
|
941
|
+
hasState: result.state !== undefined
|
|
942
|
+
})
|
|
943
|
+
},
|
|
944
|
+
() => runWithContext(context, () => action.autoRegisterWebhook!(context))
|
|
945
|
+
);
|
|
499
946
|
|
|
500
|
-
return
|
|
947
|
+
return withRequestTraces(context, {
|
|
948
|
+
registrationDetails: res.registrationDetails,
|
|
949
|
+
state: res.state
|
|
950
|
+
});
|
|
501
951
|
});
|
|
502
952
|
|
|
503
953
|
manager.onRequest('slates/action.trigger.webhook_unregister', async ({ params }) => {
|
|
@@ -523,8 +973,24 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
523
973
|
slate.spec,
|
|
524
974
|
logger
|
|
525
975
|
);
|
|
526
|
-
await
|
|
976
|
+
await traceProviderCall(
|
|
977
|
+
{
|
|
978
|
+
component: 'action',
|
|
979
|
+
functionName: 'autoUnregisterWebhook',
|
|
980
|
+
message: `Unregistering webhook for trigger ${formatEntityLabel(action.name, action.key)}`,
|
|
981
|
+
successMessage: `Unregistered webhook for trigger ${formatEntityLabel(action.name, action.key)}`,
|
|
982
|
+
errorMessage: `Trigger ${formatEntityLabel(action.name, action.key)} failed while unregistering a webhook`,
|
|
983
|
+
metadata: {
|
|
984
|
+
actionId: action.key,
|
|
985
|
+
actionName: action.name,
|
|
986
|
+
actionType: action.type,
|
|
987
|
+
hasRegistrationDetails: params.registrationDetails !== null,
|
|
988
|
+
hasPreviousState: params.state !== null
|
|
989
|
+
}
|
|
990
|
+
},
|
|
991
|
+
() => runWithContext(context, () => action.autoUnregisterWebhook!(context))
|
|
992
|
+
);
|
|
527
993
|
|
|
528
|
-
return {};
|
|
994
|
+
return withRequestTraces(context, {});
|
|
529
995
|
});
|
|
530
996
|
});
|