@slates/provider-handler 1.0.0-rc.17 → 1.0.0-rc.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +112 -35
- package/dist/index.module.js +105 -28
- package/package.json +3 -3
- package/src/index.ts +38 -11
- package/src/spec.ts +3 -1
- package/src/webhook.test.ts +65 -0
- package/src/webhook.ts +69 -0
package/dist/index.cjs
CHANGED
|
@@ -33,7 +33,7 @@ __export(index_exports, {
|
|
|
33
33
|
createProviderHandler: () => createProviderHandler
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
|
-
var
|
|
36
|
+
var import_error4 = require("@lowerdeck/error");
|
|
37
37
|
var import_proto = require("@slates/proto");
|
|
38
38
|
var import_provider2 = require("@slates/provider");
|
|
39
39
|
|
|
@@ -139,6 +139,7 @@ var mapAction = (_slate, a) => {
|
|
|
139
139
|
tags: a.tags,
|
|
140
140
|
metadata: a.metadata,
|
|
141
141
|
scopes: a.scopes,
|
|
142
|
+
authMethods: a.authMethods,
|
|
142
143
|
docs: a.docs ?? [],
|
|
143
144
|
inputSchema: toJsonSchema(a.inputSchema),
|
|
144
145
|
outputSchema: toJsonSchema(a.outputSchema)
|
|
@@ -160,7 +161,8 @@ var mapAction = (_slate, a) => {
|
|
|
160
161
|
} : {
|
|
161
162
|
type: "webhook",
|
|
162
163
|
autoRegistration: !!a.autoRegisterWebhook,
|
|
163
|
-
autoUnregistration: !!a.autoUnregisterWebhook
|
|
164
|
+
autoUnregistration: !!a.autoUnregisterWebhook,
|
|
165
|
+
http: a.http
|
|
164
166
|
}
|
|
165
167
|
};
|
|
166
168
|
};
|
|
@@ -182,6 +184,60 @@ var State = class {
|
|
|
182
184
|
}
|
|
183
185
|
};
|
|
184
186
|
|
|
187
|
+
// src/webhook.ts
|
|
188
|
+
var import_error3 = require("@lowerdeck/error");
|
|
189
|
+
var SLATE_WEBHOOK_RESPONSE_MAX_BODY_BYTES = 1024 * 1024;
|
|
190
|
+
var serializeBody = (body) => {
|
|
191
|
+
if (body === null) return null;
|
|
192
|
+
if (body.byteLength > SLATE_WEBHOOK_RESPONSE_MAX_BODY_BYTES) {
|
|
193
|
+
throw new import_error3.ServiceError(
|
|
194
|
+
(0, import_error3.badRequestError)({
|
|
195
|
+
message: `Webhook response body exceeds the ${SLATE_WEBHOOK_RESPONSE_MAX_BODY_BYTES}-byte limit`
|
|
196
|
+
})
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
encoding: "base64",
|
|
201
|
+
content: Buffer.from(body).toString("base64")
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
var headersToObject = (headers) => {
|
|
205
|
+
let result = {};
|
|
206
|
+
headers.forEach((value, key) => {
|
|
207
|
+
result[key] = value;
|
|
208
|
+
});
|
|
209
|
+
return result;
|
|
210
|
+
};
|
|
211
|
+
var validateStatus = (status) => {
|
|
212
|
+
if (!Number.isInteger(status) || status < 100 || status > 599) {
|
|
213
|
+
throw new import_error3.ServiceError(
|
|
214
|
+
(0, import_error3.badRequestError)({
|
|
215
|
+
message: "Webhook response status must be an integer between 100 and 599"
|
|
216
|
+
})
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
var serializeWebhookHttpResponse = async (response) => {
|
|
221
|
+
if (response instanceof Response) {
|
|
222
|
+
validateStatus(response.status);
|
|
223
|
+
return {
|
|
224
|
+
status: response.status,
|
|
225
|
+
headers: headersToObject(response.headers),
|
|
226
|
+
body: serializeBody(
|
|
227
|
+
response.body === null ? null : new Uint8Array(await response.arrayBuffer())
|
|
228
|
+
)
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
let status = response.status ?? 200;
|
|
232
|
+
validateStatus(status);
|
|
233
|
+
let body = typeof response.body === "string" ? new TextEncoder().encode(response.body) : response.body ?? null;
|
|
234
|
+
return {
|
|
235
|
+
status,
|
|
236
|
+
headers: response.headers ?? {},
|
|
237
|
+
body: serializeBody(body)
|
|
238
|
+
};
|
|
239
|
+
};
|
|
240
|
+
|
|
185
241
|
// src/index.ts
|
|
186
242
|
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
187
243
|
var getObjectKeyCount = (value) => isRecord(value) ? Object.keys(value).length : void 0;
|
|
@@ -293,8 +349,8 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
293
349
|
let currentProtocol = protocol.get();
|
|
294
350
|
let currentParticipants = participants.get();
|
|
295
351
|
if (!currentProtocol || !currentParticipants) {
|
|
296
|
-
throw new
|
|
297
|
-
(0,
|
|
352
|
+
throw new import_error4.ServiceError(
|
|
353
|
+
(0, import_error4.preconditionFailedError)({
|
|
298
354
|
message: "Connection context has not been initialized"
|
|
299
355
|
})
|
|
300
356
|
);
|
|
@@ -310,8 +366,8 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
310
366
|
let currentSession = session.get();
|
|
311
367
|
let currentAuth = auth.get();
|
|
312
368
|
if (!currentConfig || !currentSession || !currentAuth && slate.spec.auth.authStack.length > 0) {
|
|
313
|
-
throw new
|
|
314
|
-
(0,
|
|
369
|
+
throw new import_error4.ServiceError(
|
|
370
|
+
(0, import_error4.preconditionFailedError)({
|
|
315
371
|
message: "Session context has not been initialized"
|
|
316
372
|
})
|
|
317
373
|
);
|
|
@@ -325,6 +381,7 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
325
381
|
};
|
|
326
382
|
let getAuthConfig = () => config.get()?.value ?? {};
|
|
327
383
|
let getEmptyContext = () => new import_provider2.SlateContext({}, {}, {}, slate.spec, logger);
|
|
384
|
+
let getAuthContext = () => new import_provider2.SlateContext(getAuthConfig(), {}, {}, slate.spec, logger);
|
|
328
385
|
let withRequestTraces = (context, result) => {
|
|
329
386
|
let requestTraces = context.getHttpTraces();
|
|
330
387
|
return requestTraces.length > 0 ? { ...result, requestTraces } : result;
|
|
@@ -334,8 +391,8 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
334
391
|
});
|
|
335
392
|
manager.onNotification("slates/participant.set", async ({ params }) => {
|
|
336
393
|
if (!protocol.get()) {
|
|
337
|
-
throw new
|
|
338
|
-
(0,
|
|
394
|
+
throw new import_error4.ServiceError(
|
|
395
|
+
(0, import_error4.preconditionFailedError)({ message: "Connection protocol has not been initialized" })
|
|
339
396
|
);
|
|
340
397
|
}
|
|
341
398
|
participants.set(params.participants);
|
|
@@ -542,7 +599,7 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
542
599
|
);
|
|
543
600
|
}
|
|
544
601
|
if ("getOutput" in authMethod) {
|
|
545
|
-
let context =
|
|
602
|
+
let context = getAuthContext();
|
|
546
603
|
let outputRes = await traceProviderCall(
|
|
547
604
|
{
|
|
548
605
|
component: "auth",
|
|
@@ -555,12 +612,22 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
555
612
|
inputKeyCount: getObjectKeyCount(input)
|
|
556
613
|
},
|
|
557
614
|
onSuccess: (result) => ({
|
|
558
|
-
outputKeyCount: getObjectKeyCount(result.output)
|
|
615
|
+
outputKeyCount: getObjectKeyCount(result.output),
|
|
616
|
+
scopeCount: result.scopes?.length ?? 0
|
|
559
617
|
})
|
|
560
618
|
},
|
|
561
|
-
() => (0, import_provider2.runWithContext)(
|
|
619
|
+
() => (0, import_provider2.runWithContext)(
|
|
620
|
+
context,
|
|
621
|
+
() => authMethod.getOutput({
|
|
622
|
+
input,
|
|
623
|
+
config: getAuthConfig()
|
|
624
|
+
})
|
|
625
|
+
)
|
|
562
626
|
);
|
|
563
|
-
return withRequestTraces(context, {
|
|
627
|
+
return withRequestTraces(context, {
|
|
628
|
+
output: outputRes.output,
|
|
629
|
+
scopes: outputRes.scopes
|
|
630
|
+
});
|
|
564
631
|
}
|
|
565
632
|
return { output: input };
|
|
566
633
|
});
|
|
@@ -609,8 +676,8 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
609
676
|
scopes: callbackRes.scopes
|
|
610
677
|
});
|
|
611
678
|
}
|
|
612
|
-
throw new
|
|
613
|
-
(0,
|
|
679
|
+
throw new import_error4.ServiceError(
|
|
680
|
+
(0, import_error4.preconditionFailedError)({
|
|
614
681
|
message: `Authentication method does not support authorization callback handling: ${params.authenticationMethodId}`
|
|
615
682
|
})
|
|
616
683
|
);
|
|
@@ -656,8 +723,8 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
656
723
|
callbackState: urlRes.callbackState
|
|
657
724
|
});
|
|
658
725
|
}
|
|
659
|
-
throw new
|
|
660
|
-
(0,
|
|
726
|
+
throw new import_error4.ServiceError(
|
|
727
|
+
(0, import_error4.preconditionFailedError)({
|
|
661
728
|
message: `Authentication method does not support authorization URL retrieval: ${params.authenticationMethodId}`
|
|
662
729
|
})
|
|
663
730
|
);
|
|
@@ -666,7 +733,7 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
666
733
|
getContextBasic();
|
|
667
734
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
668
735
|
if (authMethod.getProfile) {
|
|
669
|
-
let context =
|
|
736
|
+
let context = getAuthContext();
|
|
670
737
|
let profileRes = await traceProviderCall(
|
|
671
738
|
{
|
|
672
739
|
component: "auth",
|
|
@@ -695,7 +762,9 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
695
762
|
}
|
|
696
763
|
return authMethod.getProfile({
|
|
697
764
|
output: params.output,
|
|
698
|
-
input: params.input
|
|
765
|
+
input: params.input,
|
|
766
|
+
scopes: params.scopes,
|
|
767
|
+
config: getAuthConfig()
|
|
699
768
|
});
|
|
700
769
|
})
|
|
701
770
|
);
|
|
@@ -703,8 +772,8 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
703
772
|
profile: profileRes.profile
|
|
704
773
|
});
|
|
705
774
|
}
|
|
706
|
-
throw new
|
|
707
|
-
(0,
|
|
775
|
+
throw new import_error4.ServiceError(
|
|
776
|
+
(0, import_error4.preconditionFailedError)({
|
|
708
777
|
message: `Authentication method does not support profile retrieval: ${params.authenticationMethodId}`
|
|
709
778
|
})
|
|
710
779
|
);
|
|
@@ -713,7 +782,7 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
713
782
|
getContextBasic();
|
|
714
783
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
715
784
|
if ("handleTokenRefresh" in authMethod && authMethod.handleTokenRefresh) {
|
|
716
|
-
let context =
|
|
785
|
+
let context = getAuthContext();
|
|
717
786
|
let refreshRes = await traceProviderCall(
|
|
718
787
|
{
|
|
719
788
|
component: "auth",
|
|
@@ -748,7 +817,8 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
748
817
|
input: params.input,
|
|
749
818
|
clientId: params.clientId,
|
|
750
819
|
clientSecret: params.clientSecret,
|
|
751
|
-
scopes: params.scopes
|
|
820
|
+
scopes: params.scopes,
|
|
821
|
+
config: getAuthConfig()
|
|
752
822
|
});
|
|
753
823
|
})
|
|
754
824
|
);
|
|
@@ -757,8 +827,8 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
757
827
|
input: refreshRes.input
|
|
758
828
|
});
|
|
759
829
|
}
|
|
760
|
-
throw new
|
|
761
|
-
(0,
|
|
830
|
+
throw new import_error4.ServiceError(
|
|
831
|
+
(0, import_error4.preconditionFailedError)({
|
|
762
832
|
message: `Authentication method does not support token refresh handling: ${params.authenticationMethodId}`
|
|
763
833
|
})
|
|
764
834
|
);
|
|
@@ -851,8 +921,8 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
851
921
|
let ctx = getContextFull();
|
|
852
922
|
let action = getActionWithType(slate, "trigger", params.actionId);
|
|
853
923
|
if (!action.pollEvents) {
|
|
854
|
-
throw new
|
|
855
|
-
(0,
|
|
924
|
+
throw new import_error4.ServiceError(
|
|
925
|
+
(0, import_error4.badRequestError)({
|
|
856
926
|
message: `Trigger action does not support polling: ${params.actionId}`
|
|
857
927
|
})
|
|
858
928
|
);
|
|
@@ -893,8 +963,8 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
893
963
|
let ctx = getContextFull();
|
|
894
964
|
let action = getActionWithType(slate, "trigger", params.actionId);
|
|
895
965
|
if (!action.handleRequest) {
|
|
896
|
-
throw new
|
|
897
|
-
(0,
|
|
966
|
+
throw new import_error4.ServiceError(
|
|
967
|
+
(0, import_error4.badRequestError)({
|
|
898
968
|
message: `Trigger action does not support webhook requests: ${params.actionId}`
|
|
899
969
|
})
|
|
900
970
|
);
|
|
@@ -906,7 +976,11 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
906
976
|
});
|
|
907
977
|
let context = new import_provider2.SlateContext(
|
|
908
978
|
ctx.config,
|
|
909
|
-
{
|
|
979
|
+
{
|
|
980
|
+
request: req,
|
|
981
|
+
state: params.state,
|
|
982
|
+
registrationDetails: params.registrationDetails ?? null
|
|
983
|
+
},
|
|
910
984
|
ctx.auth?.output,
|
|
911
985
|
slate.spec,
|
|
912
986
|
logger
|
|
@@ -928,22 +1002,25 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
928
1002
|
},
|
|
929
1003
|
onSuccess: (result) => ({
|
|
930
1004
|
inputCount: result.inputs.length,
|
|
931
|
-
hasUpdatedState: result.updatedState !== void 0
|
|
1005
|
+
hasUpdatedState: result.updatedState !== void 0,
|
|
1006
|
+
hasResponse: result.response !== void 0
|
|
932
1007
|
})
|
|
933
1008
|
},
|
|
934
1009
|
() => (0, import_provider2.runWithContext)(context, () => action.handleRequest(context))
|
|
935
1010
|
);
|
|
1011
|
+
let response = res.response === void 0 ? void 0 : await serializeWebhookHttpResponse(res.response);
|
|
936
1012
|
return withRequestTraces(context, {
|
|
937
1013
|
inputs: res.inputs,
|
|
938
|
-
updatedState: res.updatedState
|
|
1014
|
+
updatedState: res.updatedState,
|
|
1015
|
+
response
|
|
939
1016
|
});
|
|
940
1017
|
});
|
|
941
1018
|
manager.onRequest("slates/action.trigger.webhook_register", async ({ params }) => {
|
|
942
1019
|
let ctx = getContextFull();
|
|
943
1020
|
let action = getActionWithType(slate, "trigger", params.actionId);
|
|
944
1021
|
if (!action.autoRegisterWebhook) {
|
|
945
|
-
throw new
|
|
946
|
-
(0,
|
|
1022
|
+
throw new import_error4.ServiceError(
|
|
1023
|
+
(0, import_error4.badRequestError)({
|
|
947
1024
|
message: `Trigger action does not support webhook auto-registration: ${params.actionId}`
|
|
948
1025
|
})
|
|
949
1026
|
);
|
|
@@ -983,8 +1060,8 @@ var createProviderHandler = (slate, listeners) => (0, import_proto.createSlatesP
|
|
|
983
1060
|
let ctx = getContextFull();
|
|
984
1061
|
let action = getActionWithType(slate, "trigger", params.actionId);
|
|
985
1062
|
if (!action.autoUnregisterWebhook) {
|
|
986
|
-
throw new
|
|
987
|
-
(0,
|
|
1063
|
+
throw new import_error4.ServiceError(
|
|
1064
|
+
(0, import_error4.badRequestError)({
|
|
988
1065
|
message: `Trigger action does not support webhook auto-unregistration: ${params.actionId}`
|
|
989
1066
|
})
|
|
990
1067
|
);
|
package/dist/index.module.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { badRequestError as
|
|
2
|
+
import { badRequestError as badRequestError3, preconditionFailedError, ServiceError as ServiceError4 } from "@lowerdeck/error";
|
|
3
3
|
import {
|
|
4
4
|
createSlatesProviderProtoHandler,
|
|
5
5
|
SLATES_PROTOCOL_VERSION
|
|
@@ -112,6 +112,7 @@ var mapAction = (_slate, a) => {
|
|
|
112
112
|
tags: a.tags,
|
|
113
113
|
metadata: a.metadata,
|
|
114
114
|
scopes: a.scopes,
|
|
115
|
+
authMethods: a.authMethods,
|
|
115
116
|
docs: a.docs ?? [],
|
|
116
117
|
inputSchema: toJsonSchema(a.inputSchema),
|
|
117
118
|
outputSchema: toJsonSchema(a.outputSchema)
|
|
@@ -133,7 +134,8 @@ var mapAction = (_slate, a) => {
|
|
|
133
134
|
} : {
|
|
134
135
|
type: "webhook",
|
|
135
136
|
autoRegistration: !!a.autoRegisterWebhook,
|
|
136
|
-
autoUnregistration: !!a.autoUnregisterWebhook
|
|
137
|
+
autoUnregistration: !!a.autoUnregisterWebhook,
|
|
138
|
+
http: a.http
|
|
137
139
|
}
|
|
138
140
|
};
|
|
139
141
|
};
|
|
@@ -155,6 +157,60 @@ var State = class {
|
|
|
155
157
|
}
|
|
156
158
|
};
|
|
157
159
|
|
|
160
|
+
// src/webhook.ts
|
|
161
|
+
import { badRequestError as badRequestError2, ServiceError as ServiceError3 } from "@lowerdeck/error";
|
|
162
|
+
var SLATE_WEBHOOK_RESPONSE_MAX_BODY_BYTES = 1024 * 1024;
|
|
163
|
+
var serializeBody = (body) => {
|
|
164
|
+
if (body === null) return null;
|
|
165
|
+
if (body.byteLength > SLATE_WEBHOOK_RESPONSE_MAX_BODY_BYTES) {
|
|
166
|
+
throw new ServiceError3(
|
|
167
|
+
badRequestError2({
|
|
168
|
+
message: `Webhook response body exceeds the ${SLATE_WEBHOOK_RESPONSE_MAX_BODY_BYTES}-byte limit`
|
|
169
|
+
})
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
encoding: "base64",
|
|
174
|
+
content: Buffer.from(body).toString("base64")
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
var headersToObject = (headers) => {
|
|
178
|
+
let result = {};
|
|
179
|
+
headers.forEach((value, key) => {
|
|
180
|
+
result[key] = value;
|
|
181
|
+
});
|
|
182
|
+
return result;
|
|
183
|
+
};
|
|
184
|
+
var validateStatus = (status) => {
|
|
185
|
+
if (!Number.isInteger(status) || status < 100 || status > 599) {
|
|
186
|
+
throw new ServiceError3(
|
|
187
|
+
badRequestError2({
|
|
188
|
+
message: "Webhook response status must be an integer between 100 and 599"
|
|
189
|
+
})
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
var serializeWebhookHttpResponse = async (response) => {
|
|
194
|
+
if (response instanceof Response) {
|
|
195
|
+
validateStatus(response.status);
|
|
196
|
+
return {
|
|
197
|
+
status: response.status,
|
|
198
|
+
headers: headersToObject(response.headers),
|
|
199
|
+
body: serializeBody(
|
|
200
|
+
response.body === null ? null : new Uint8Array(await response.arrayBuffer())
|
|
201
|
+
)
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
let status = response.status ?? 200;
|
|
205
|
+
validateStatus(status);
|
|
206
|
+
let body = typeof response.body === "string" ? new TextEncoder().encode(response.body) : response.body ?? null;
|
|
207
|
+
return {
|
|
208
|
+
status,
|
|
209
|
+
headers: response.headers ?? {},
|
|
210
|
+
body: serializeBody(body)
|
|
211
|
+
};
|
|
212
|
+
};
|
|
213
|
+
|
|
158
214
|
// src/index.ts
|
|
159
215
|
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
160
216
|
var getObjectKeyCount = (value) => isRecord(value) ? Object.keys(value).length : void 0;
|
|
@@ -266,7 +322,7 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
266
322
|
let currentProtocol = protocol.get();
|
|
267
323
|
let currentParticipants = participants.get();
|
|
268
324
|
if (!currentProtocol || !currentParticipants) {
|
|
269
|
-
throw new
|
|
325
|
+
throw new ServiceError4(
|
|
270
326
|
preconditionFailedError({
|
|
271
327
|
message: "Connection context has not been initialized"
|
|
272
328
|
})
|
|
@@ -283,7 +339,7 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
283
339
|
let currentSession = session.get();
|
|
284
340
|
let currentAuth = auth.get();
|
|
285
341
|
if (!currentConfig || !currentSession || !currentAuth && slate.spec.auth.authStack.length > 0) {
|
|
286
|
-
throw new
|
|
342
|
+
throw new ServiceError4(
|
|
287
343
|
preconditionFailedError({
|
|
288
344
|
message: "Session context has not been initialized"
|
|
289
345
|
})
|
|
@@ -298,6 +354,7 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
298
354
|
};
|
|
299
355
|
let getAuthConfig = () => config.get()?.value ?? {};
|
|
300
356
|
let getEmptyContext = () => new SlateContext({}, {}, {}, slate.spec, logger);
|
|
357
|
+
let getAuthContext = () => new SlateContext(getAuthConfig(), {}, {}, slate.spec, logger);
|
|
301
358
|
let withRequestTraces = (context, result) => {
|
|
302
359
|
let requestTraces = context.getHttpTraces();
|
|
303
360
|
return requestTraces.length > 0 ? { ...result, requestTraces } : result;
|
|
@@ -307,7 +364,7 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
307
364
|
});
|
|
308
365
|
manager.onNotification("slates/participant.set", async ({ params }) => {
|
|
309
366
|
if (!protocol.get()) {
|
|
310
|
-
throw new
|
|
367
|
+
throw new ServiceError4(
|
|
311
368
|
preconditionFailedError({ message: "Connection protocol has not been initialized" })
|
|
312
369
|
);
|
|
313
370
|
}
|
|
@@ -515,7 +572,7 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
515
572
|
);
|
|
516
573
|
}
|
|
517
574
|
if ("getOutput" in authMethod) {
|
|
518
|
-
let context =
|
|
575
|
+
let context = getAuthContext();
|
|
519
576
|
let outputRes = await traceProviderCall(
|
|
520
577
|
{
|
|
521
578
|
component: "auth",
|
|
@@ -528,12 +585,22 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
528
585
|
inputKeyCount: getObjectKeyCount(input)
|
|
529
586
|
},
|
|
530
587
|
onSuccess: (result) => ({
|
|
531
|
-
outputKeyCount: getObjectKeyCount(result.output)
|
|
588
|
+
outputKeyCount: getObjectKeyCount(result.output),
|
|
589
|
+
scopeCount: result.scopes?.length ?? 0
|
|
532
590
|
})
|
|
533
591
|
},
|
|
534
|
-
() => runWithContext(
|
|
592
|
+
() => runWithContext(
|
|
593
|
+
context,
|
|
594
|
+
() => authMethod.getOutput({
|
|
595
|
+
input,
|
|
596
|
+
config: getAuthConfig()
|
|
597
|
+
})
|
|
598
|
+
)
|
|
535
599
|
);
|
|
536
|
-
return withRequestTraces(context, {
|
|
600
|
+
return withRequestTraces(context, {
|
|
601
|
+
output: outputRes.output,
|
|
602
|
+
scopes: outputRes.scopes
|
|
603
|
+
});
|
|
537
604
|
}
|
|
538
605
|
return { output: input };
|
|
539
606
|
});
|
|
@@ -582,7 +649,7 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
582
649
|
scopes: callbackRes.scopes
|
|
583
650
|
});
|
|
584
651
|
}
|
|
585
|
-
throw new
|
|
652
|
+
throw new ServiceError4(
|
|
586
653
|
preconditionFailedError({
|
|
587
654
|
message: `Authentication method does not support authorization callback handling: ${params.authenticationMethodId}`
|
|
588
655
|
})
|
|
@@ -629,7 +696,7 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
629
696
|
callbackState: urlRes.callbackState
|
|
630
697
|
});
|
|
631
698
|
}
|
|
632
|
-
throw new
|
|
699
|
+
throw new ServiceError4(
|
|
633
700
|
preconditionFailedError({
|
|
634
701
|
message: `Authentication method does not support authorization URL retrieval: ${params.authenticationMethodId}`
|
|
635
702
|
})
|
|
@@ -639,7 +706,7 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
639
706
|
getContextBasic();
|
|
640
707
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
641
708
|
if (authMethod.getProfile) {
|
|
642
|
-
let context =
|
|
709
|
+
let context = getAuthContext();
|
|
643
710
|
let profileRes = await traceProviderCall(
|
|
644
711
|
{
|
|
645
712
|
component: "auth",
|
|
@@ -668,7 +735,9 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
668
735
|
}
|
|
669
736
|
return authMethod.getProfile({
|
|
670
737
|
output: params.output,
|
|
671
|
-
input: params.input
|
|
738
|
+
input: params.input,
|
|
739
|
+
scopes: params.scopes,
|
|
740
|
+
config: getAuthConfig()
|
|
672
741
|
});
|
|
673
742
|
})
|
|
674
743
|
);
|
|
@@ -676,7 +745,7 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
676
745
|
profile: profileRes.profile
|
|
677
746
|
});
|
|
678
747
|
}
|
|
679
|
-
throw new
|
|
748
|
+
throw new ServiceError4(
|
|
680
749
|
preconditionFailedError({
|
|
681
750
|
message: `Authentication method does not support profile retrieval: ${params.authenticationMethodId}`
|
|
682
751
|
})
|
|
@@ -686,7 +755,7 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
686
755
|
getContextBasic();
|
|
687
756
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
688
757
|
if ("handleTokenRefresh" in authMethod && authMethod.handleTokenRefresh) {
|
|
689
|
-
let context =
|
|
758
|
+
let context = getAuthContext();
|
|
690
759
|
let refreshRes = await traceProviderCall(
|
|
691
760
|
{
|
|
692
761
|
component: "auth",
|
|
@@ -721,7 +790,8 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
721
790
|
input: params.input,
|
|
722
791
|
clientId: params.clientId,
|
|
723
792
|
clientSecret: params.clientSecret,
|
|
724
|
-
scopes: params.scopes
|
|
793
|
+
scopes: params.scopes,
|
|
794
|
+
config: getAuthConfig()
|
|
725
795
|
});
|
|
726
796
|
})
|
|
727
797
|
);
|
|
@@ -730,7 +800,7 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
730
800
|
input: refreshRes.input
|
|
731
801
|
});
|
|
732
802
|
}
|
|
733
|
-
throw new
|
|
803
|
+
throw new ServiceError4(
|
|
734
804
|
preconditionFailedError({
|
|
735
805
|
message: `Authentication method does not support token refresh handling: ${params.authenticationMethodId}`
|
|
736
806
|
})
|
|
@@ -824,8 +894,8 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
824
894
|
let ctx = getContextFull();
|
|
825
895
|
let action = getActionWithType(slate, "trigger", params.actionId);
|
|
826
896
|
if (!action.pollEvents) {
|
|
827
|
-
throw new
|
|
828
|
-
|
|
897
|
+
throw new ServiceError4(
|
|
898
|
+
badRequestError3({
|
|
829
899
|
message: `Trigger action does not support polling: ${params.actionId}`
|
|
830
900
|
})
|
|
831
901
|
);
|
|
@@ -866,8 +936,8 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
866
936
|
let ctx = getContextFull();
|
|
867
937
|
let action = getActionWithType(slate, "trigger", params.actionId);
|
|
868
938
|
if (!action.handleRequest) {
|
|
869
|
-
throw new
|
|
870
|
-
|
|
939
|
+
throw new ServiceError4(
|
|
940
|
+
badRequestError3({
|
|
871
941
|
message: `Trigger action does not support webhook requests: ${params.actionId}`
|
|
872
942
|
})
|
|
873
943
|
);
|
|
@@ -879,7 +949,11 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
879
949
|
});
|
|
880
950
|
let context = new SlateContext(
|
|
881
951
|
ctx.config,
|
|
882
|
-
{
|
|
952
|
+
{
|
|
953
|
+
request: req,
|
|
954
|
+
state: params.state,
|
|
955
|
+
registrationDetails: params.registrationDetails ?? null
|
|
956
|
+
},
|
|
883
957
|
ctx.auth?.output,
|
|
884
958
|
slate.spec,
|
|
885
959
|
logger
|
|
@@ -901,22 +975,25 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
901
975
|
},
|
|
902
976
|
onSuccess: (result) => ({
|
|
903
977
|
inputCount: result.inputs.length,
|
|
904
|
-
hasUpdatedState: result.updatedState !== void 0
|
|
978
|
+
hasUpdatedState: result.updatedState !== void 0,
|
|
979
|
+
hasResponse: result.response !== void 0
|
|
905
980
|
})
|
|
906
981
|
},
|
|
907
982
|
() => runWithContext(context, () => action.handleRequest(context))
|
|
908
983
|
);
|
|
984
|
+
let response = res.response === void 0 ? void 0 : await serializeWebhookHttpResponse(res.response);
|
|
909
985
|
return withRequestTraces(context, {
|
|
910
986
|
inputs: res.inputs,
|
|
911
|
-
updatedState: res.updatedState
|
|
987
|
+
updatedState: res.updatedState,
|
|
988
|
+
response
|
|
912
989
|
});
|
|
913
990
|
});
|
|
914
991
|
manager.onRequest("slates/action.trigger.webhook_register", async ({ params }) => {
|
|
915
992
|
let ctx = getContextFull();
|
|
916
993
|
let action = getActionWithType(slate, "trigger", params.actionId);
|
|
917
994
|
if (!action.autoRegisterWebhook) {
|
|
918
|
-
throw new
|
|
919
|
-
|
|
995
|
+
throw new ServiceError4(
|
|
996
|
+
badRequestError3({
|
|
920
997
|
message: `Trigger action does not support webhook auto-registration: ${params.actionId}`
|
|
921
998
|
})
|
|
922
999
|
);
|
|
@@ -956,8 +1033,8 @@ var createProviderHandler = (slate, listeners) => createSlatesProviderProtoHandl
|
|
|
956
1033
|
let ctx = getContextFull();
|
|
957
1034
|
let action = getActionWithType(slate, "trigger", params.actionId);
|
|
958
1035
|
if (!action.autoUnregisterWebhook) {
|
|
959
|
-
throw new
|
|
960
|
-
|
|
1036
|
+
throw new ServiceError4(
|
|
1037
|
+
badRequestError3({
|
|
961
1038
|
message: `Trigger action does not support webhook auto-unregistration: ${params.actionId}`
|
|
962
1039
|
})
|
|
963
1040
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slates/provider-handler",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.19",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@lowerdeck/error": "^1.1.0",
|
|
35
|
-
"@slates/proto": "1.0.0-rc.
|
|
36
|
-
"@slates/provider": "1.0.0-rc.
|
|
35
|
+
"@slates/proto": "1.0.0-rc.13",
|
|
36
|
+
"@slates/provider": "1.0.0-rc.17",
|
|
37
37
|
"zod": "^4.2.1"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
package/src/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
import { getAction, getActionWithType, getAuthMethod, mapAction, mapAuthMethod } from './spec';
|
|
16
16
|
import { State } from './state';
|
|
17
17
|
import { toJsonSchema, validate } from './validation';
|
|
18
|
+
import { serializeWebhookHttpResponse } from './webhook';
|
|
18
19
|
|
|
19
20
|
let isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
20
21
|
typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
@@ -228,6 +229,8 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
228
229
|
let getAuthConfig = (): Record<string, any> => config.get()?.value ?? {};
|
|
229
230
|
|
|
230
231
|
let getEmptyContext = () => new SlateContext({}, {}, {}, slate.spec as any, logger);
|
|
232
|
+
let getAuthContext = () =>
|
|
233
|
+
new SlateContext(getAuthConfig(), {}, {}, slate.spec as any, logger);
|
|
231
234
|
let withRequestTraces = <Result extends Record<string, any>>(
|
|
232
235
|
context: SlateContext<any, any, any>,
|
|
233
236
|
result: Result
|
|
@@ -487,7 +490,7 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
487
490
|
}
|
|
488
491
|
|
|
489
492
|
if ('getOutput' in authMethod) {
|
|
490
|
-
let context =
|
|
493
|
+
let context = getAuthContext();
|
|
491
494
|
let outputRes = await traceProviderCall(
|
|
492
495
|
{
|
|
493
496
|
component: 'auth',
|
|
@@ -500,12 +503,22 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
500
503
|
inputKeyCount: getObjectKeyCount(input)
|
|
501
504
|
},
|
|
502
505
|
onSuccess: result => ({
|
|
503
|
-
outputKeyCount: getObjectKeyCount(result.output)
|
|
506
|
+
outputKeyCount: getObjectKeyCount(result.output),
|
|
507
|
+
scopeCount: result.scopes?.length ?? 0
|
|
504
508
|
})
|
|
505
509
|
},
|
|
506
|
-
() =>
|
|
510
|
+
() =>
|
|
511
|
+
runWithContext(context, () =>
|
|
512
|
+
authMethod.getOutput({
|
|
513
|
+
input,
|
|
514
|
+
config: getAuthConfig()
|
|
515
|
+
})
|
|
516
|
+
)
|
|
507
517
|
);
|
|
508
|
-
return withRequestTraces(context, {
|
|
518
|
+
return withRequestTraces(context, {
|
|
519
|
+
output: outputRes.output,
|
|
520
|
+
scopes: outputRes.scopes
|
|
521
|
+
});
|
|
509
522
|
}
|
|
510
523
|
|
|
511
524
|
return { output: input as any };
|
|
@@ -622,7 +635,7 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
622
635
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
623
636
|
|
|
624
637
|
if (authMethod.getProfile) {
|
|
625
|
-
let context =
|
|
638
|
+
let context = getAuthContext();
|
|
626
639
|
let profileRes = await traceProviderCall(
|
|
627
640
|
{
|
|
628
641
|
component: 'auth',
|
|
@@ -653,7 +666,9 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
653
666
|
|
|
654
667
|
return authMethod.getProfile!({
|
|
655
668
|
output: params.output as any,
|
|
656
|
-
input: params.input
|
|
669
|
+
input: params.input,
|
|
670
|
+
scopes: params.scopes,
|
|
671
|
+
config: getAuthConfig()
|
|
657
672
|
})!;
|
|
658
673
|
})
|
|
659
674
|
);
|
|
@@ -675,7 +690,7 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
675
690
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
676
691
|
|
|
677
692
|
if ('handleTokenRefresh' in authMethod && authMethod.handleTokenRefresh) {
|
|
678
|
-
let context =
|
|
693
|
+
let context = getAuthContext();
|
|
679
694
|
let refreshRes = await traceProviderCall(
|
|
680
695
|
{
|
|
681
696
|
component: 'auth',
|
|
@@ -712,7 +727,8 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
712
727
|
input: params.input,
|
|
713
728
|
clientId: params.clientId,
|
|
714
729
|
clientSecret: params.clientSecret,
|
|
715
|
-
scopes: params.scopes
|
|
730
|
+
scopes: params.scopes,
|
|
731
|
+
config: getAuthConfig()
|
|
716
732
|
});
|
|
717
733
|
})
|
|
718
734
|
);
|
|
@@ -896,7 +912,11 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
896
912
|
|
|
897
913
|
let context = new SlateContext(
|
|
898
914
|
ctx.config,
|
|
899
|
-
{
|
|
915
|
+
{
|
|
916
|
+
request: req,
|
|
917
|
+
state: params.state,
|
|
918
|
+
registrationDetails: params.registrationDetails ?? null
|
|
919
|
+
},
|
|
900
920
|
ctx.auth?.output!,
|
|
901
921
|
slate.spec,
|
|
902
922
|
logger
|
|
@@ -919,15 +939,22 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
919
939
|
},
|
|
920
940
|
onSuccess: result => ({
|
|
921
941
|
inputCount: result.inputs.length,
|
|
922
|
-
hasUpdatedState: result.updatedState !== undefined
|
|
942
|
+
hasUpdatedState: result.updatedState !== undefined,
|
|
943
|
+
hasResponse: result.response !== undefined
|
|
923
944
|
})
|
|
924
945
|
},
|
|
925
946
|
() => runWithContext(context, () => action.handleRequest!(context))
|
|
926
947
|
);
|
|
927
948
|
|
|
949
|
+
let response =
|
|
950
|
+
res.response === undefined
|
|
951
|
+
? undefined
|
|
952
|
+
: await serializeWebhookHttpResponse(res.response);
|
|
953
|
+
|
|
928
954
|
return withRequestTraces(context, {
|
|
929
955
|
inputs: res.inputs,
|
|
930
|
-
updatedState: res.updatedState
|
|
956
|
+
updatedState: res.updatedState,
|
|
957
|
+
response
|
|
931
958
|
});
|
|
932
959
|
});
|
|
933
960
|
|
package/src/spec.ts
CHANGED
|
@@ -101,6 +101,7 @@ export let mapAction = <ConfigType extends {}, AuthType extends {}>(
|
|
|
101
101
|
tags: a.tags,
|
|
102
102
|
metadata: a.metadata,
|
|
103
103
|
scopes: a.scopes,
|
|
104
|
+
authMethods: a.authMethods,
|
|
104
105
|
docs: a.docs ?? [],
|
|
105
106
|
|
|
106
107
|
inputSchema: toJsonSchema(a.inputSchema),
|
|
@@ -129,7 +130,8 @@ export let mapAction = <ConfigType extends {}, AuthType extends {}>(
|
|
|
129
130
|
: {
|
|
130
131
|
type: 'webhook',
|
|
131
132
|
autoRegistration: !!a.autoRegisterWebhook,
|
|
132
|
-
autoUnregistration: !!a.autoUnregisterWebhook
|
|
133
|
+
autoUnregistration: !!a.autoUnregisterWebhook,
|
|
134
|
+
http: a.http
|
|
133
135
|
}
|
|
134
136
|
};
|
|
135
137
|
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
SLATE_WEBHOOK_RESPONSE_MAX_BODY_BYTES,
|
|
4
|
+
serializeWebhookHttpResponse
|
|
5
|
+
} from './webhook';
|
|
6
|
+
|
|
7
|
+
describe('serializeWebhookHttpResponse', () => {
|
|
8
|
+
it('serializes a Response with status, headers, and body', async () => {
|
|
9
|
+
await expect(
|
|
10
|
+
serializeWebhookHttpResponse(
|
|
11
|
+
new Response('created', {
|
|
12
|
+
status: 201,
|
|
13
|
+
headers: {
|
|
14
|
+
'content-type': 'text/plain',
|
|
15
|
+
'x-webhook-result': 'accepted'
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
)
|
|
19
|
+
).resolves.toEqual({
|
|
20
|
+
status: 201,
|
|
21
|
+
headers: {
|
|
22
|
+
'content-type': 'text/plain',
|
|
23
|
+
'x-webhook-result': 'accepted'
|
|
24
|
+
},
|
|
25
|
+
body: {
|
|
26
|
+
encoding: 'base64',
|
|
27
|
+
content: Buffer.from('created').toString('base64')
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('applies defaults to a plain response init', async () => {
|
|
33
|
+
await expect(serializeWebhookHttpResponse({ body: 'ok' })).resolves.toEqual({
|
|
34
|
+
status: 200,
|
|
35
|
+
headers: {},
|
|
36
|
+
body: {
|
|
37
|
+
encoding: 'base64',
|
|
38
|
+
content: Buffer.from('ok').toString('base64')
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('serializes binary response bodies without changing their bytes', async () => {
|
|
44
|
+
await expect(
|
|
45
|
+
serializeWebhookHttpResponse({
|
|
46
|
+
status: 202,
|
|
47
|
+
body: new Uint8Array([0, 127, 128, 255])
|
|
48
|
+
})
|
|
49
|
+
).resolves.toMatchObject({
|
|
50
|
+
status: 202,
|
|
51
|
+
body: {
|
|
52
|
+
encoding: 'base64',
|
|
53
|
+
content: Buffer.from([0, 127, 128, 255]).toString('base64')
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('rejects bodies larger than one MiB', async () => {
|
|
59
|
+
await expect(
|
|
60
|
+
serializeWebhookHttpResponse({
|
|
61
|
+
body: new Uint8Array(SLATE_WEBHOOK_RESPONSE_MAX_BODY_BYTES + 1)
|
|
62
|
+
})
|
|
63
|
+
).rejects.toThrow('Webhook response body exceeds');
|
|
64
|
+
});
|
|
65
|
+
});
|
package/src/webhook.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { badRequestError, ServiceError } from '@lowerdeck/error';
|
|
2
|
+
import type { SlatesWebhookHttpResponse } from '@slates/proto';
|
|
3
|
+
import type { SlateWebhookHttpResponseInit } from '@slates/provider';
|
|
4
|
+
|
|
5
|
+
export let SLATE_WEBHOOK_RESPONSE_MAX_BODY_BYTES = 1024 * 1024;
|
|
6
|
+
|
|
7
|
+
let serializeBody = (body: Uint8Array | null): SlatesWebhookHttpResponse['body'] => {
|
|
8
|
+
if (body === null) return null;
|
|
9
|
+
|
|
10
|
+
if (body.byteLength > SLATE_WEBHOOK_RESPONSE_MAX_BODY_BYTES) {
|
|
11
|
+
throw new ServiceError(
|
|
12
|
+
badRequestError({
|
|
13
|
+
message: `Webhook response body exceeds the ${SLATE_WEBHOOK_RESPONSE_MAX_BODY_BYTES}-byte limit`
|
|
14
|
+
})
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
encoding: 'base64',
|
|
20
|
+
content: Buffer.from(body).toString('base64')
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
let headersToObject = (headers: Headers) => {
|
|
25
|
+
let result: Record<string, string> = {};
|
|
26
|
+
headers.forEach((value, key) => {
|
|
27
|
+
result[key] = value;
|
|
28
|
+
});
|
|
29
|
+
return result;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
let validateStatus = (status: number) => {
|
|
33
|
+
if (!Number.isInteger(status) || status < 100 || status > 599) {
|
|
34
|
+
throw new ServiceError(
|
|
35
|
+
badRequestError({
|
|
36
|
+
message: 'Webhook response status must be an integer between 100 and 599'
|
|
37
|
+
})
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export let serializeWebhookHttpResponse = async (
|
|
43
|
+
response: Response | SlateWebhookHttpResponseInit
|
|
44
|
+
): Promise<SlatesWebhookHttpResponse> => {
|
|
45
|
+
if (response instanceof Response) {
|
|
46
|
+
validateStatus(response.status);
|
|
47
|
+
return {
|
|
48
|
+
status: response.status,
|
|
49
|
+
headers: headersToObject(response.headers),
|
|
50
|
+
body: serializeBody(
|
|
51
|
+
response.body === null ? null : new Uint8Array(await response.arrayBuffer())
|
|
52
|
+
)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let status = response.status ?? 200;
|
|
57
|
+
validateStatus(status);
|
|
58
|
+
|
|
59
|
+
let body =
|
|
60
|
+
typeof response.body === 'string'
|
|
61
|
+
? new TextEncoder().encode(response.body)
|
|
62
|
+
: (response.body ?? null);
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
status,
|
|
66
|
+
headers: response.headers ?? {},
|
|
67
|
+
body: serializeBody(body)
|
|
68
|
+
};
|
|
69
|
+
};
|