@slates/provider 1.0.0-rc.16 → 1.0.0-rc.18

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 (42) hide show
  1. package/dist/index.cjs +639 -21
  2. package/dist/index.d.cts +290 -29
  3. package/dist/index.d.ts +290 -29
  4. package/dist/index.module.js +606 -18
  5. package/package.json +2 -2
  6. package/src/action/action.ts +64 -2
  7. package/src/action/builder.test.ts +136 -0
  8. package/src/action/builder.ts +73 -13
  9. package/src/action/index.ts +2 -1
  10. package/src/action/publicTool.ts +36 -0
  11. package/src/action/tool.ts +15 -3
  12. package/src/action/trigger.ts +9 -1
  13. package/src/adapter/adapter.ts +38 -0
  14. package/src/adapter/index.test.ts +322 -0
  15. package/src/adapter/index.ts +2 -0
  16. package/src/adapter/spec.ts +154 -0
  17. package/src/auth/index.ts +1 -0
  18. package/src/auth/oauth.test.ts +83 -0
  19. package/src/auth/oauth.ts +150 -0
  20. package/src/auth/types.ts +22 -6
  21. package/src/axios/http.test.ts +83 -0
  22. package/src/axios/index.ts +59 -1
  23. package/src/axios/trace.ts +3 -3
  24. package/src/context/context.ts +37 -14
  25. package/src/context/hook.ts +5 -10
  26. package/src/crypto/hmac.test.ts +40 -0
  27. package/src/crypto/hmac.ts +32 -0
  28. package/src/crypto/index.ts +1 -0
  29. package/src/error/api.test.ts +114 -0
  30. package/src/error/api.ts +236 -0
  31. package/src/error/index.ts +1 -0
  32. package/src/file/index.test.ts +36 -0
  33. package/src/file/index.ts +27 -0
  34. package/src/index.ts +5 -0
  35. package/src/object/index.test.ts +38 -0
  36. package/src/object/index.ts +12 -0
  37. package/src/specification/slate.ts +38 -2
  38. package/src/webhook/graph.test.ts +37 -0
  39. package/src/webhook/graph.ts +22 -0
  40. package/src/webhook/index.ts +2 -0
  41. package/src/webhook/meta.test.ts +52 -0
  42. package/src/webhook/meta.ts +43 -0
package/dist/index.cjs CHANGED
@@ -32,6 +32,9 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  Slate: () => Slate,
34
34
  SlateAction: () => SlateAction,
35
+ SlateActionBuilder: () => SlateActionBuilder,
36
+ SlateAdapter: () => SlateAdapter,
37
+ SlateAdapterSpec: () => SlateAdapterSpec,
35
38
  SlateAuth: () => SlateAuth,
36
39
  SlateConfig: () => SlateConfig,
37
40
  SlateContext: () => SlateContext,
@@ -39,33 +42,60 @@ __export(index_exports, {
39
42
  SlateDefaultPollingIntervalSeconds: () => SlateDefaultPollingIntervalSeconds,
40
43
  SlateError: () => SlateError,
41
44
  SlateLogger: () => SlateLogger,
45
+ SlatePublicContext: () => SlatePublicContext,
46
+ SlatePublicTool: () => SlatePublicTool,
42
47
  SlateSpecification: () => SlateSpecification,
43
48
  SlateTool: () => SlateTool,
44
49
  SlateTrigger: () => SlateTrigger,
50
+ adapterSpec: () => adapterSpec,
45
51
  allOf: () => allOf,
46
52
  anyOf: () => anyOf,
47
53
  auth: () => auth,
48
54
  axios: () => axios,
55
+ buildApiServiceError: () => buildApiServiceError,
56
+ collectApiErrorDetails: () => collectApiErrorDetails,
49
57
  config: () => config,
58
+ createApiServiceError: () => createApiServiceError,
59
+ createAuthenticatedAxios: () => createAuthenticatedAxios,
50
60
  createAxios: () => createAxios,
51
61
  createBase64Attachment: () => createBase64Attachment,
62
+ createHmacSignature: () => createHmacSignature,
52
63
  createSlateError: () => createSlateError,
53
64
  createTextAttachment: () => createTextAttachment,
54
65
  createUrlAttachment: () => createUrlAttachment,
66
+ extractApiErrorMessage: () => extractApiErrorMessage,
67
+ getApiErrorResponse: () => getApiErrorResponse,
68
+ getApiErrorStatus: () => getApiErrorStatus,
69
+ getBase64ByteLength: () => getBase64ByteLength,
55
70
  getCurrentContext: () => getCurrentContext,
71
+ getGraphWebhookValidationResponse: () => getGraphWebhookValidationResponse,
72
+ getMetaWebhookVerificationResponse: () => getMetaWebhookVerificationResponse,
73
+ getOAuthExpiresAtFromExpiresIn: () => getOAuthExpiresAtFromExpiresIn,
74
+ getResponseHeaderValue: () => getResponseHeaderValue,
56
75
  getServiceErrorData: () => getServiceErrorData,
76
+ graphWebhookHttp: () => graphWebhookHttp,
57
77
  inferSlateErrorFromAxios: () => inferSlateErrorFromAxios,
78
+ isApiErrorRecord: () => isApiErrorRecord,
58
79
  isAxiosErrorLike: () => isAxiosErrorLike,
59
80
  isServiceErrorData: () => isServiceErrorData,
60
81
  mapServiceErrorCode: () => mapServiceErrorCode,
61
82
  mapServiceErrorToSlateErrorInput: () => mapServiceErrorToSlateErrorInput,
62
83
  mergeScopes: () => mergeScopes,
84
+ metaWebhookHttp: () => metaWebhookHttp,
85
+ normalizeOAuthTokenResponse: () => normalizeOAuthTokenResponse,
86
+ pickDefined: () => pickDefined,
87
+ publicTool: () => publicTool,
88
+ requestAxios: () => requestAxios,
89
+ requestAxiosData: () => requestAxiosData,
63
90
  runWithContext: () => runWithContext,
64
91
  scopeClause: () => scopeClause,
92
+ setIfDefined: () => setIfDefined,
65
93
  spec: () => spec,
94
+ statusLabelForApiError: () => statusLabelForApiError,
66
95
  tool: () => tool,
67
96
  trigger: () => trigger,
68
- validateScopes: () => validateScopes
97
+ validateScopes: () => validateScopes,
98
+ verifyHmacSignature: () => verifyHmacSignature
69
99
  });
70
100
  module.exports = __toCommonJS(index_exports);
71
101
 
@@ -125,6 +155,130 @@ var SlateAction = class {
125
155
  get docs() {
126
156
  return this._params.docs;
127
157
  }
158
+ get adapter() {
159
+ return this._params.adapter ?? null;
160
+ }
161
+ get isPublic() {
162
+ return this._params.isPublic === true;
163
+ }
164
+ };
165
+
166
+ // src/error/api.ts
167
+ var import_error = require("@lowerdeck/error");
168
+ var DEFAULT_DETAIL_KEYS = ["message", "detail", "error", "error_description", "code"];
169
+ var DEFAULT_NESTED_KEYS = ["errors"];
170
+ var isApiErrorRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
171
+ var pushDetail = (details, value, options = {}) => {
172
+ if (typeof value !== "string" && (options.includeNumbers === false || typeof value !== "number")) {
173
+ return;
174
+ }
175
+ let detail = String(value).trim();
176
+ if (detail && !details.includes(detail)) {
177
+ details.push(detail);
178
+ }
179
+ };
180
+ var collectApiErrorDetails = (value, details, options = {}) => {
181
+ if (Array.isArray(value)) {
182
+ for (let item of value) {
183
+ collectApiErrorDetails(item, details, options);
184
+ }
185
+ return;
186
+ }
187
+ if (!isApiErrorRecord(value)) {
188
+ pushDetail(details, value, options);
189
+ return;
190
+ }
191
+ for (let key of options.detailKeys ?? DEFAULT_DETAIL_KEYS) {
192
+ pushDetail(details, value[key], options);
193
+ }
194
+ for (let key of options.nestedKeys ?? DEFAULT_NESTED_KEYS) {
195
+ collectApiErrorDetails(value[key], details, options);
196
+ }
197
+ };
198
+ var getSlateErrorResponse = (error) => {
199
+ if (error.name !== "SlateError" || !isApiErrorRecord(error.data)) {
200
+ return void 0;
201
+ }
202
+ let data = error.data;
203
+ let upstream = isApiErrorRecord(data.upstream) ? data.upstream : void 0;
204
+ let status = upstream?.status ?? data.status;
205
+ return typeof status === "number" || typeof status === "string" ? { status } : void 0;
206
+ };
207
+ var getApiErrorResponse = (error) => {
208
+ if (!isApiErrorRecord(error)) {
209
+ return void 0;
210
+ }
211
+ if (!isApiErrorRecord(error.response)) {
212
+ return getSlateErrorResponse(error);
213
+ }
214
+ let response = error.response;
215
+ return {
216
+ status: typeof response.status === "number" || typeof response.status === "string" ? response.status : void 0,
217
+ statusText: typeof response.statusText === "string" ? response.statusText : void 0,
218
+ data: response.data
219
+ };
220
+ };
221
+ var getApiErrorStatus = (error) => getApiErrorResponse(error)?.status;
222
+ var statusLabelForApiError = (status, statusText) => status !== void 0 ? `HTTP ${status}${statusText ? ` ${statusText}` : ""}: ` : "";
223
+ var extractApiErrorMessage = (error, options = {}) => {
224
+ let details = [];
225
+ let response = options.response ?? getApiErrorResponse(error);
226
+ collectApiErrorDetails(response?.data, details, options);
227
+ if (details.length > 0) {
228
+ return details.join(options.separator ?? " - ");
229
+ }
230
+ if (error instanceof Error && error.message) {
231
+ return error.message;
232
+ }
233
+ return options.fallbackMessage ?? "Unknown error";
234
+ };
235
+ var createApiServiceError = (message, options = {}) => {
236
+ let error = new import_error.ServiceError((0, import_error.badRequestError)({ message }));
237
+ if (options.reason !== void 0) {
238
+ error.data.reason = options.reason;
239
+ }
240
+ if ("upstreamStatus" in options) {
241
+ error.data.upstreamStatus = options.upstreamStatus;
242
+ }
243
+ if ("upstreamCode" in options) {
244
+ error.data.upstreamCode = options.upstreamCode;
245
+ }
246
+ if (options.parent instanceof Error) {
247
+ error.setParent(options.parent);
248
+ }
249
+ return error;
250
+ };
251
+ var helpers = {
252
+ collectDetails: collectApiErrorDetails,
253
+ extractMessage: extractApiErrorMessage,
254
+ getResponse: getApiErrorResponse,
255
+ getStatus: getApiErrorStatus,
256
+ isRecord: isApiErrorRecord,
257
+ statusLabelFor: statusLabelForApiError
258
+ };
259
+ var buildApiServiceError = (error, options) => {
260
+ if (error instanceof import_error.ServiceError) {
261
+ return error;
262
+ }
263
+ let operation = options.operation ?? "request";
264
+ let response = options.extractResponse?.(error, helpers) ?? getApiErrorResponse(error);
265
+ let status = options.extractStatus?.(error, response, helpers) ?? response?.status;
266
+ let message = options.extractMessage?.(error, helpers) ?? extractApiErrorMessage(error, { ...options, response });
267
+ let statusLabel = statusLabelForApiError(status, response?.statusText);
268
+ let fullMessage = options.formatMessage?.({
269
+ providerLabel: options.providerLabel,
270
+ operation,
271
+ statusLabel,
272
+ message,
273
+ response,
274
+ status
275
+ }) ?? `${options.providerLabel} API ${operation} failed: ${statusLabel}${message}`;
276
+ return createApiServiceError(fullMessage, {
277
+ reason: options.reason,
278
+ upstreamStatus: status,
279
+ upstreamCode: options.extractUpstreamCode?.(error, response, helpers),
280
+ parent: options.parent ?? error
281
+ });
128
282
  };
129
283
 
130
284
  // src/error/axios.ts
@@ -468,7 +622,7 @@ var inferSlateErrorFromAxios = (error, options = {}) => {
468
622
  };
469
623
 
470
624
  // src/error/service.ts
471
- var import_error = require("@lowerdeck/error");
625
+ var import_error2 = require("@lowerdeck/error");
472
626
  var SERVICE_ERROR_DATA_RESERVED_KEYS = /* @__PURE__ */ new Set([
473
627
  "status",
474
628
  "code",
@@ -535,7 +689,7 @@ var getServiceErrorBaggage = (data) => {
535
689
  var mapServiceErrorCode = (code, status) => SERVICE_ERROR_CODE_MAP[code] ?? mapServiceErrorCodeByStatus(status);
536
690
  var isServiceErrorData = (value) => isRecord(value) && typeof value.status === "number" && typeof value.code === "string" && typeof value.message === "string" && !("config" in value) && !("request" in value) && !("response" in value) && !("isAxiosError" in value);
537
691
  var getServiceErrorData = (error) => {
538
- if ((0, import_error.isServiceError)(error)) {
692
+ if ((0, import_error2.isServiceError)(error)) {
539
693
  return isServiceErrorData(error.data) ? error.data : null;
540
694
  }
541
695
  if (isServiceErrorData(error)) {
@@ -751,11 +905,12 @@ var isScopes = (value) => typeof value === "object" && value !== null && "AND" i
751
905
 
752
906
  // src/action/builder.ts
753
907
  var SlateActionBuilder = class {
754
- constructor(type, spec2, params, factory) {
908
+ constructor(type, spec2, params, factory, isPublicTool = false) {
755
909
  this.type = type;
756
910
  this.spec = spec2;
757
911
  this.params = params;
758
912
  this.factory = factory;
913
+ this.isPublicTool = isPublicTool;
759
914
  this.#configSchema = spec2.configSchema;
760
915
  this.#authSchema = spec2.authSchema;
761
916
  }
@@ -763,6 +918,7 @@ var SlateActionBuilder = class {
763
918
  spec;
764
919
  params;
765
920
  factory;
921
+ isPublicTool;
766
922
  #configSchema;
767
923
  #authSchema;
768
924
  #inputSchema = null;
@@ -771,20 +927,34 @@ var SlateActionBuilder = class {
771
927
  #authMethods;
772
928
  #toolParams = null;
773
929
  #triggerParams = null;
930
+ #interfaceLocked = false;
774
931
  input(schema) {
932
+ if (this.#interfaceLocked) {
933
+ throw new SlateDeclarationError("Adapter contract input schema cannot be changed");
934
+ }
775
935
  this.#inputSchema = schema;
776
936
  return this;
777
937
  }
778
938
  output(schema) {
939
+ if (this.#interfaceLocked) {
940
+ throw new SlateDeclarationError("Adapter contract output schema cannot be changed");
941
+ }
779
942
  this.#outputSchema = schema;
780
943
  return this;
781
944
  }
945
+ lockInterface() {
946
+ this.#interfaceLocked = true;
947
+ return this;
948
+ }
782
949
  scopes(scopes) {
783
950
  validateScopes(scopes);
784
951
  this.#scopes = scopes;
785
952
  return this;
786
953
  }
787
954
  authMethods(authMethods) {
955
+ if (this.isPublicTool) {
956
+ throw new SlateDeclarationError("Public tools cannot require authentication methods");
957
+ }
788
958
  this.#authMethods = this.validateAuthMethods(authMethods);
789
959
  return this;
790
960
  }
@@ -816,7 +986,8 @@ var SlateActionBuilder = class {
816
986
  handleEvent: props.handleEvent,
817
987
  handleRequest: props.handleRequest,
818
988
  autoRegisterWebhook: props.autoRegisterWebhook,
819
- autoUnregisterWebhook: props.autoUnregisterWebhook
989
+ autoUnregisterWebhook: props.autoUnregisterWebhook,
990
+ http: props.http
820
991
  };
821
992
  return this;
822
993
  }
@@ -839,6 +1010,9 @@ var SlateActionBuilder = class {
839
1010
  validateScopes(scopes);
840
1011
  }
841
1012
  let authMethods = this.validateAuthMethods(this.#authMethods ?? this.params.authMethods);
1013
+ if (this.isPublicTool && authMethods) {
1014
+ throw new SlateDeclarationError("Public tools cannot require authentication methods");
1015
+ }
842
1016
  if (!this.#inputSchema) {
843
1017
  throw new SlateDeclarationError("Input schema is not defined");
844
1018
  }
@@ -855,6 +1029,7 @@ var SlateActionBuilder = class {
855
1029
  ...this.params,
856
1030
  scopes,
857
1031
  authMethods,
1032
+ isPublic: this.isPublicTool === true,
858
1033
  configSchema: this.#configSchema,
859
1034
  authSchema: this.#authSchema,
860
1035
  inputSchema: this.#inputSchema,
@@ -874,16 +1049,40 @@ var SlateTool = class _SlateTool extends SlateAction {
874
1049
  }
875
1050
  static create(spec2, params) {
876
1051
  return new SlateActionBuilder("tool", spec2, params, (params2) => {
877
- if (params2.type !== "tool") throw new Error("Invalid action type for tool");
878
- return new _SlateTool(spec2, params2.inputSchema, params2.outputSchema, params2);
1052
+ return _SlateTool.fromCreateParameters(spec2, params2);
879
1053
  });
880
1054
  }
1055
+ static fromCreateParameters(spec2, params) {
1056
+ if (params.type !== "tool") throw new Error("Invalid action type for tool");
1057
+ return new _SlateTool(spec2, params.inputSchema, params.outputSchema, params);
1058
+ }
881
1059
  get handleInvocation() {
882
1060
  return this.#handleInvocation;
883
1061
  }
884
1062
  };
885
1063
  var tool = (spec2, params) => SlateTool.create(spec2, params);
886
1064
 
1065
+ // src/action/publicTool.ts
1066
+ var SlatePublicTool = class {
1067
+ constructor() {
1068
+ }
1069
+ static create(spec2, params) {
1070
+ return new SlateActionBuilder(
1071
+ "tool",
1072
+ spec2,
1073
+ params,
1074
+ (params2) => {
1075
+ return SlateTool.fromCreateParameters(spec2, {
1076
+ ...params2,
1077
+ isPublic: true
1078
+ });
1079
+ },
1080
+ true
1081
+ );
1082
+ }
1083
+ };
1084
+ var publicTool = (spec2, params) => SlatePublicTool.create(spec2, params);
1085
+
887
1086
  // src/action/trigger.ts
888
1087
  var SlateDefaultPollingIntervalSeconds = 60 * 10;
889
1088
  var SlateTrigger = class _SlateTrigger extends SlateAction {
@@ -891,6 +1090,7 @@ var SlateTrigger = class _SlateTrigger extends SlateAction {
891
1090
  #polling;
892
1091
  #handleEvent;
893
1092
  #handleRequest;
1093
+ #http;
894
1094
  #pollEvents;
895
1095
  #autoRegisterWebhook;
896
1096
  #autoUnregisterWebhook;
@@ -902,6 +1102,7 @@ var SlateTrigger = class _SlateTrigger extends SlateAction {
902
1102
  };
903
1103
  this.#handleEvent = params.handleEvent;
904
1104
  this.#handleRequest = params.handleRequest;
1105
+ this.#http = params.http;
905
1106
  this.#pollEvents = params.pollEvents;
906
1107
  this.#autoRegisterWebhook = params.autoRegisterWebhook;
907
1108
  this.#autoUnregisterWebhook = params.autoUnregisterWebhook;
@@ -924,6 +1125,9 @@ var SlateTrigger = class _SlateTrigger extends SlateAction {
924
1125
  get handleRequest() {
925
1126
  return this.#handleRequest;
926
1127
  }
1128
+ get http() {
1129
+ return this.#http;
1130
+ }
927
1131
  get pollEvents() {
928
1132
  return this.#pollEvents;
929
1133
  }
@@ -961,6 +1165,135 @@ var createTextAttachment = (content, mimeType) => ({
961
1165
  }
962
1166
  });
963
1167
 
1168
+ // src/adapter/adapter.ts
1169
+ var SlateAdapter = class {
1170
+ constructor(_spec, _tools, _triggers) {
1171
+ this._spec = _spec;
1172
+ this._tools = _tools;
1173
+ this._triggers = _triggers;
1174
+ }
1175
+ _spec;
1176
+ _tools;
1177
+ _triggers;
1178
+ get spec() {
1179
+ return this._spec;
1180
+ }
1181
+ get id() {
1182
+ return this._spec.id;
1183
+ }
1184
+ get name() {
1185
+ return this._spec.name;
1186
+ }
1187
+ get capabilities() {
1188
+ return this._spec.capabilities;
1189
+ }
1190
+ get tools() {
1191
+ return this._tools;
1192
+ }
1193
+ get triggers() {
1194
+ return this._triggers;
1195
+ }
1196
+ get actions() {
1197
+ return [...this._triggers, ...this._tools];
1198
+ }
1199
+ };
1200
+
1201
+ // src/adapter/spec.ts
1202
+ var SlateAdapterSpec = class _SlateAdapterSpec {
1203
+ constructor(_params) {
1204
+ this._params = _params;
1205
+ }
1206
+ _params;
1207
+ static create(params) {
1208
+ let id = params.id?.trim();
1209
+ let name = params.name?.trim();
1210
+ if (!id) {
1211
+ throw new SlateDeclarationError("Adapter id must be a non-empty string");
1212
+ }
1213
+ if (!name) {
1214
+ throw new SlateDeclarationError("Adapter name must be a non-empty string");
1215
+ }
1216
+ return new _SlateAdapterSpec({
1217
+ id,
1218
+ name,
1219
+ capabilities: validateCapabilities(params.capabilities ?? [])
1220
+ });
1221
+ }
1222
+ get id() {
1223
+ return this._params.id;
1224
+ }
1225
+ get name() {
1226
+ return this._params.name;
1227
+ }
1228
+ get capabilities() {
1229
+ return this._params.capabilities;
1230
+ }
1231
+ get parameters() {
1232
+ return this._params;
1233
+ }
1234
+ tool(spec2, params) {
1235
+ return SlateTool.create(spec2, this.linkAction(params));
1236
+ }
1237
+ publicTool(spec2, params) {
1238
+ return SlatePublicTool.create(spec2, this.linkAction(params));
1239
+ }
1240
+ trigger(spec2, params) {
1241
+ return SlateTrigger.create(spec2, this.linkAction(params));
1242
+ }
1243
+ register(params) {
1244
+ let actions = [...params.tools, ...params.triggers];
1245
+ let seenKeys = /* @__PURE__ */ new Set();
1246
+ for (let action of actions) {
1247
+ if (action.adapter && action.adapter !== this.id) {
1248
+ throw new SlateDeclarationError(
1249
+ `Action "${action.key}" is linked to adapter "${action.adapter}", not "${this.id}"`
1250
+ );
1251
+ }
1252
+ if (!action.adapter) {
1253
+ throw new SlateDeclarationError(
1254
+ `Action "${action.key}" must be created with this adapter's tool(), publicTool(), or trigger() helpers`
1255
+ );
1256
+ }
1257
+ if (seenKeys.has(action.key)) {
1258
+ throw new SlateDeclarationError(
1259
+ `Adapter "${this.id}" already has an action with key "${action.key}"`
1260
+ );
1261
+ }
1262
+ seenKeys.add(action.key);
1263
+ }
1264
+ return new SlateAdapter(this, params.tools, params.triggers);
1265
+ }
1266
+ linkAction(params) {
1267
+ if (params.adapter != null && params.adapter !== this.id) {
1268
+ throw new SlateDeclarationError(
1269
+ `Action "${params.key}" cannot be linked to adapter "${this.id}" because it is already linked to "${params.adapter}"`
1270
+ );
1271
+ }
1272
+ return {
1273
+ ...params,
1274
+ adapter: this.id
1275
+ };
1276
+ }
1277
+ };
1278
+ var adapterSpec = (params) => SlateAdapterSpec.create(params);
1279
+ var validateCapabilities = (capabilities) => {
1280
+ let seenIds = /* @__PURE__ */ new Set();
1281
+ return capabilities.map((capability) => {
1282
+ let id = capability.id?.trim();
1283
+ if (!id) {
1284
+ throw new SlateDeclarationError("Adapter capability ids must be non-empty strings");
1285
+ }
1286
+ if (seenIds.has(id)) {
1287
+ throw new SlateDeclarationError(`Adapter capability "${id}" is defined more than once`);
1288
+ }
1289
+ seenIds.add(id);
1290
+ return {
1291
+ id,
1292
+ value: capability.value
1293
+ };
1294
+ });
1295
+ };
1296
+
964
1297
  // src/auth/auth.ts
965
1298
  var SlateAuth = class _SlateAuth {
966
1299
  #outputSchema = null;
@@ -1018,6 +1351,90 @@ var SlateAuth = class _SlateAuth {
1018
1351
  };
1019
1352
  var auth = () => SlateAuth.create();
1020
1353
 
1354
+ // src/auth/oauth.ts
1355
+ var isOAuthTokenResponse = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1356
+ var formatOAuthTokenResponseMessage = (fieldLabel, providerLabel = "OAuth provider", operation = "token response") => `${providerLabel} OAuth ${operation} did not return ${fieldLabel}.`;
1357
+ var getOAuthExpiresAtFromExpiresIn = (expiresIn, options = {}) => {
1358
+ let {
1359
+ nowMs = Date.now(),
1360
+ providerLabel,
1361
+ operation,
1362
+ required = false,
1363
+ expiresInType = "numberLike",
1364
+ message
1365
+ } = options;
1366
+ if (expiresIn === void 0 || expiresIn === null || expiresIn === "") {
1367
+ if (required) {
1368
+ throw createApiServiceError(
1369
+ message ?? formatOAuthTokenResponseMessage(
1370
+ "a valid expires_in value",
1371
+ providerLabel,
1372
+ operation
1373
+ ),
1374
+ { reason: "oauth_token_response" }
1375
+ );
1376
+ }
1377
+ return void 0;
1378
+ }
1379
+ let seconds = typeof expiresIn === "number" ? expiresIn : expiresInType === "numberLike" && typeof expiresIn === "string" ? Number(expiresIn) : Number.NaN;
1380
+ if (!Number.isFinite(seconds)) {
1381
+ throw createApiServiceError(
1382
+ message ?? formatOAuthTokenResponseMessage("a valid expires_in value", providerLabel, operation),
1383
+ { reason: "oauth_token_response" }
1384
+ );
1385
+ }
1386
+ return new Date(nowMs + seconds * 1e3).toISOString();
1387
+ };
1388
+ var getRefreshToken = (refreshToken, previousRefreshToken, fallbackMode) => {
1389
+ if (typeof refreshToken === "string") {
1390
+ if (fallbackMode === "falsy" && !refreshToken) {
1391
+ return previousRefreshToken;
1392
+ }
1393
+ return refreshToken;
1394
+ }
1395
+ if (fallbackMode === "falsy" && !refreshToken) {
1396
+ return previousRefreshToken;
1397
+ }
1398
+ return refreshToken === void 0 || refreshToken === null ? previousRefreshToken : void 0;
1399
+ };
1400
+ var normalizeOAuthTokenResponse = (data, options = {}) => {
1401
+ let {
1402
+ providerLabel,
1403
+ operation,
1404
+ previousRefreshToken,
1405
+ refreshTokenFallbackMode = "nullish",
1406
+ accessTokenMessage,
1407
+ expiresInMessage,
1408
+ ...expiresAtOptions
1409
+ } = options;
1410
+ if (!isOAuthTokenResponse(data)) {
1411
+ throw createApiServiceError(
1412
+ accessTokenMessage ?? formatOAuthTokenResponseMessage("a token response object", providerLabel, operation),
1413
+ { reason: "oauth_token_response" }
1414
+ );
1415
+ }
1416
+ if (typeof data.access_token !== "string" || !data.access_token) {
1417
+ throw createApiServiceError(
1418
+ accessTokenMessage ?? formatOAuthTokenResponseMessage("an access token", providerLabel, operation),
1419
+ { reason: "oauth_token_response" }
1420
+ );
1421
+ }
1422
+ return {
1423
+ token: data.access_token,
1424
+ refreshToken: getRefreshToken(
1425
+ data.refresh_token,
1426
+ previousRefreshToken,
1427
+ refreshTokenFallbackMode
1428
+ ),
1429
+ expiresAt: getOAuthExpiresAtFromExpiresIn(data.expires_in, {
1430
+ ...expiresAtOptions,
1431
+ providerLabel,
1432
+ operation,
1433
+ message: expiresInMessage
1434
+ })
1435
+ };
1436
+ };
1437
+
1021
1438
  // src/axios/index.ts
1022
1439
  var import_axios3 = __toESM(require("axios"), 1);
1023
1440
 
@@ -1601,6 +2018,35 @@ var createAxios = (config2) => {
1601
2018
  applySlateInterceptors(instance, errorMapping);
1602
2019
  return instance;
1603
2020
  };
2021
+ var createAuthenticatedAxios = (config2) => {
2022
+ let { authHeader, contentType = "application/json", errorAdapter, ...axiosConfig } = config2;
2023
+ let instance = createAxios({
2024
+ ...axiosConfig,
2025
+ headers: {
2026
+ ...contentType === false ? {} : { "Content-Type": contentType },
2027
+ ...authHeader ? { [authHeader.name ?? "Authorization"]: authHeader.value } : {},
2028
+ ...axiosConfig.headers
2029
+ }
2030
+ });
2031
+ if (errorAdapter) {
2032
+ instance.interceptors.response.use(
2033
+ (response) => response,
2034
+ (error) => Promise.reject(errorAdapter(error))
2035
+ );
2036
+ }
2037
+ return instance;
2038
+ };
2039
+ var requestAxios = async (operation, request, errorAdapter) => {
2040
+ try {
2041
+ return await request();
2042
+ } catch (error) {
2043
+ throw errorAdapter(error, operation);
2044
+ }
2045
+ };
2046
+ var requestAxiosData = async (operation, request, errorAdapter) => {
2047
+ let response = await requestAxios(operation, request, errorAdapter);
2048
+ return response.data;
2049
+ };
1604
2050
  var axios = createAxios();
1605
2051
 
1606
2052
  // src/config/config.ts
@@ -1647,26 +2093,19 @@ var SlateConfig = class _SlateConfig {
1647
2093
  var config = (schema) => SlateConfig.create(schema);
1648
2094
 
1649
2095
  // src/context/context.ts
1650
- var SlateContext = class {
1651
- constructor(config2, input, auth2, spec2, logger) {
2096
+ var SlatePublicContext = class {
2097
+ constructor(input, spec2, logger) {
1652
2098
  this.spec = spec2;
1653
2099
  this.logger = logger;
1654
- this.#config = config2;
1655
2100
  this.#input = input;
1656
- this.#auth = auth2;
1657
2101
  }
1658
2102
  spec;
1659
2103
  logger;
1660
- #config;
1661
2104
  #input;
1662
- #auth;
1663
2105
  #httpTraces = [];
1664
2106
  get specification() {
1665
2107
  return this.spec;
1666
2108
  }
1667
- get config() {
1668
- return Object.freeze(this.#config);
1669
- }
1670
2109
  get input() {
1671
2110
  return Object.freeze(this.#input);
1672
2111
  }
@@ -1679,8 +2118,10 @@ var SlateContext = class {
1679
2118
  get request() {
1680
2119
  return Object.freeze(this.#input.request);
1681
2120
  }
1682
- get auth() {
1683
- return Object.freeze(this.#auth);
2121
+ get registrationDetails() {
2122
+ return Object.freeze(
2123
+ this.#input.registrationDetails
2124
+ );
1684
2125
  }
1685
2126
  recordHttpTrace(trace) {
1686
2127
  this.#httpTraces.push(trace);
@@ -1716,6 +2157,60 @@ var SlateContext = class {
1716
2157
  this.logger.progress(message);
1717
2158
  }
1718
2159
  };
2160
+ var SlateContext = class extends SlatePublicContext {
2161
+ #config;
2162
+ #auth;
2163
+ constructor(config2, input, auth2, spec2, logger) {
2164
+ super(input, spec2, logger);
2165
+ this.#config = config2;
2166
+ this.#auth = auth2;
2167
+ }
2168
+ get config() {
2169
+ return Object.freeze(this.#config);
2170
+ }
2171
+ get auth() {
2172
+ return Object.freeze(this.#auth);
2173
+ }
2174
+ };
2175
+
2176
+ // src/crypto/hmac.ts
2177
+ var import_crypto = require("crypto");
2178
+ var createHmacSignature = ({
2179
+ secret,
2180
+ payload,
2181
+ algorithm = "sha256",
2182
+ digest,
2183
+ prefix = ""
2184
+ }) => `${prefix}${(0, import_crypto.createHmac)(algorithm, secret).update(payload).digest(digest)}`;
2185
+ var verifyHmacSignature = (options) => {
2186
+ let expected = createHmacSignature(options);
2187
+ let expectedBytes = Buffer.from(expected);
2188
+ let signatureBytes = Buffer.from(options.signature);
2189
+ let lengthsMatch = signatureBytes.length === expectedBytes.length;
2190
+ let comparableSignature = lengthsMatch ? signatureBytes : Buffer.alloc(expectedBytes.length);
2191
+ return (0, import_crypto.timingSafeEqual)(comparableSignature, expectedBytes) && lengthsMatch;
2192
+ };
2193
+
2194
+ // src/file/index.ts
2195
+ var getResponseHeaderValue = (headers, name) => {
2196
+ if (!headers) return void 0;
2197
+ if (typeof headers.get === "function") {
2198
+ let value = headers.get(name);
2199
+ return typeof value === "string" ? value : void 0;
2200
+ }
2201
+ if (typeof headers !== "object") return void 0;
2202
+ let lowerName = name.toLowerCase();
2203
+ for (let [headerName, value] of Object.entries(headers)) {
2204
+ if (headerName.toLowerCase() !== lowerName) continue;
2205
+ if (Array.isArray(value)) {
2206
+ let first = value.find((item) => typeof item === "string");
2207
+ return typeof first === "string" ? first : void 0;
2208
+ }
2209
+ return typeof value === "string" ? value : void 0;
2210
+ }
2211
+ return void 0;
2212
+ };
2213
+ var getBase64ByteLength = (contentBase64) => Buffer.from(contentBase64, "base64").byteLength;
1719
2214
 
1720
2215
  // src/logger/logger.ts
1721
2216
  var import_toon = require("@toon-format/toon");
@@ -1812,16 +2307,53 @@ var SlateLogger = class {
1812
2307
  }
1813
2308
  };
1814
2309
 
2310
+ // src/object/index.ts
2311
+ var pickDefined = (value) => Object.fromEntries(
2312
+ Object.entries(value).filter(([, child]) => child !== void 0)
2313
+ );
2314
+ var setIfDefined = (target, key, value) => {
2315
+ if (value !== void 0) {
2316
+ target[key] = value;
2317
+ }
2318
+ return target;
2319
+ };
2320
+
1815
2321
  // src/specification/slate.ts
1816
2322
  var Slate = class _Slate {
1817
- constructor(_spec, _actions) {
2323
+ constructor(_spec, _actions, _adapters) {
1818
2324
  this._spec = _spec;
1819
2325
  this._actions = _actions;
2326
+ this._adapters = _adapters;
1820
2327
  }
1821
2328
  _spec;
1822
2329
  _actions;
2330
+ _adapters;
1823
2331
  static create(params) {
1824
- return new _Slate(params.spec, [...params.triggers, ...params.tools]);
2332
+ let adapters = params.adapters ?? [];
2333
+ let actions = [...params.triggers, ...params.tools];
2334
+ let seenAdapterIds = /* @__PURE__ */ new Set();
2335
+ let seenActionKeys = new Map(actions.map((action) => [action.key, action]));
2336
+ for (let adapter of adapters) {
2337
+ if (seenAdapterIds.has(adapter.id)) {
2338
+ throw new SlateDeclarationError(
2339
+ `Adapter "${adapter.id}" is registered more than once`
2340
+ );
2341
+ }
2342
+ seenAdapterIds.add(adapter.id);
2343
+ for (let action of adapter.actions) {
2344
+ let existing = seenActionKeys.get(action.key);
2345
+ if (existing && existing !== action) {
2346
+ throw new SlateDeclarationError(
2347
+ `Adapter "${adapter.id}" action "${action.key}" conflicts with another action`
2348
+ );
2349
+ }
2350
+ if (!existing) {
2351
+ actions.push(action);
2352
+ seenActionKeys.set(action.key, action);
2353
+ }
2354
+ }
2355
+ }
2356
+ return new _Slate(params.spec, actions, adapters);
1825
2357
  }
1826
2358
  get spec() {
1827
2359
  return this._spec;
@@ -1829,6 +2361,9 @@ var Slate = class _Slate {
1829
2361
  get actions() {
1830
2362
  return this._actions;
1831
2363
  }
2364
+ get adapters() {
2365
+ return this._adapters;
2366
+ }
1832
2367
  };
1833
2368
 
1834
2369
  // src/specification/specification.ts
@@ -1874,10 +2409,66 @@ var SlateSpecification = class _SlateSpecification {
1874
2409
  }
1875
2410
  };
1876
2411
  var spec = (params) => SlateSpecification.create(params);
2412
+
2413
+ // src/webhook/graph.ts
2414
+ var graphWebhookHttp = {
2415
+ methods: ["POST"],
2416
+ sync: {
2417
+ mode: "match",
2418
+ match: [{ hasQueryParam: "validationToken" }]
2419
+ }
2420
+ };
2421
+ var getGraphWebhookValidationResponse = (request) => {
2422
+ let validationToken = new URL(request.url).searchParams.get("validationToken");
2423
+ if (validationToken === null) return null;
2424
+ return {
2425
+ status: 200,
2426
+ headers: { "content-type": "text/plain" },
2427
+ body: validationToken
2428
+ };
2429
+ };
2430
+
2431
+ // src/webhook/meta.ts
2432
+ var metaWebhookHttp = {
2433
+ methods: ["GET", "POST"],
2434
+ sync: {
2435
+ mode: "match",
2436
+ match: [{ method: "GET", hasQueryParam: "hub.mode" }]
2437
+ }
2438
+ };
2439
+ var getMetaWebhookVerificationResponse = (request, expectedVerifyToken) => {
2440
+ if (request.method !== "GET") return null;
2441
+ let url = new URL(request.url);
2442
+ let mode = url.searchParams.get("hub.mode");
2443
+ let verifyToken = url.searchParams.get("hub.verify_token");
2444
+ let challenge = url.searchParams.get("hub.challenge");
2445
+ if (mode !== "subscribe" || challenge === null) {
2446
+ return {
2447
+ status: 400,
2448
+ headers: { "content-type": "text/plain" },
2449
+ body: "invalid webhook verification request"
2450
+ };
2451
+ }
2452
+ if (expectedVerifyToken !== void 0 && verifyToken !== expectedVerifyToken) {
2453
+ return {
2454
+ status: 403,
2455
+ headers: { "content-type": "text/plain" },
2456
+ body: "invalid verify token"
2457
+ };
2458
+ }
2459
+ return {
2460
+ status: 200,
2461
+ headers: { "content-type": "text/plain" },
2462
+ body: challenge
2463
+ };
2464
+ };
1877
2465
  // Annotate the CommonJS export names for ESM import in node:
1878
2466
  0 && (module.exports = {
1879
2467
  Slate,
1880
2468
  SlateAction,
2469
+ SlateActionBuilder,
2470
+ SlateAdapter,
2471
+ SlateAdapterSpec,
1881
2472
  SlateAuth,
1882
2473
  SlateConfig,
1883
2474
  SlateContext,
@@ -1885,31 +2476,58 @@ var spec = (params) => SlateSpecification.create(params);
1885
2476
  SlateDefaultPollingIntervalSeconds,
1886
2477
  SlateError,
1887
2478
  SlateLogger,
2479
+ SlatePublicContext,
2480
+ SlatePublicTool,
1888
2481
  SlateSpecification,
1889
2482
  SlateTool,
1890
2483
  SlateTrigger,
2484
+ adapterSpec,
1891
2485
  allOf,
1892
2486
  anyOf,
1893
2487
  auth,
1894
2488
  axios,
2489
+ buildApiServiceError,
2490
+ collectApiErrorDetails,
1895
2491
  config,
2492
+ createApiServiceError,
2493
+ createAuthenticatedAxios,
1896
2494
  createAxios,
1897
2495
  createBase64Attachment,
2496
+ createHmacSignature,
1898
2497
  createSlateError,
1899
2498
  createTextAttachment,
1900
2499
  createUrlAttachment,
2500
+ extractApiErrorMessage,
2501
+ getApiErrorResponse,
2502
+ getApiErrorStatus,
2503
+ getBase64ByteLength,
1901
2504
  getCurrentContext,
2505
+ getGraphWebhookValidationResponse,
2506
+ getMetaWebhookVerificationResponse,
2507
+ getOAuthExpiresAtFromExpiresIn,
2508
+ getResponseHeaderValue,
1902
2509
  getServiceErrorData,
2510
+ graphWebhookHttp,
1903
2511
  inferSlateErrorFromAxios,
2512
+ isApiErrorRecord,
1904
2513
  isAxiosErrorLike,
1905
2514
  isServiceErrorData,
1906
2515
  mapServiceErrorCode,
1907
2516
  mapServiceErrorToSlateErrorInput,
1908
2517
  mergeScopes,
2518
+ metaWebhookHttp,
2519
+ normalizeOAuthTokenResponse,
2520
+ pickDefined,
2521
+ publicTool,
2522
+ requestAxios,
2523
+ requestAxiosData,
1909
2524
  runWithContext,
1910
2525
  scopeClause,
2526
+ setIfDefined,
1911
2527
  spec,
2528
+ statusLabelForApiError,
1912
2529
  tool,
1913
2530
  trigger,
1914
- validateScopes
2531
+ validateScopes,
2532
+ verifyHmacSignature
1915
2533
  });