@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
@@ -54,6 +54,130 @@ var SlateAction = class {
54
54
  get docs() {
55
55
  return this._params.docs;
56
56
  }
57
+ get adapter() {
58
+ return this._params.adapter ?? null;
59
+ }
60
+ get isPublic() {
61
+ return this._params.isPublic === true;
62
+ }
63
+ };
64
+
65
+ // src/error/api.ts
66
+ import { badRequestError, ServiceError } from "@lowerdeck/error";
67
+ var DEFAULT_DETAIL_KEYS = ["message", "detail", "error", "error_description", "code"];
68
+ var DEFAULT_NESTED_KEYS = ["errors"];
69
+ var isApiErrorRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
70
+ var pushDetail = (details, value, options = {}) => {
71
+ if (typeof value !== "string" && (options.includeNumbers === false || typeof value !== "number")) {
72
+ return;
73
+ }
74
+ let detail = String(value).trim();
75
+ if (detail && !details.includes(detail)) {
76
+ details.push(detail);
77
+ }
78
+ };
79
+ var collectApiErrorDetails = (value, details, options = {}) => {
80
+ if (Array.isArray(value)) {
81
+ for (let item of value) {
82
+ collectApiErrorDetails(item, details, options);
83
+ }
84
+ return;
85
+ }
86
+ if (!isApiErrorRecord(value)) {
87
+ pushDetail(details, value, options);
88
+ return;
89
+ }
90
+ for (let key of options.detailKeys ?? DEFAULT_DETAIL_KEYS) {
91
+ pushDetail(details, value[key], options);
92
+ }
93
+ for (let key of options.nestedKeys ?? DEFAULT_NESTED_KEYS) {
94
+ collectApiErrorDetails(value[key], details, options);
95
+ }
96
+ };
97
+ var getSlateErrorResponse = (error) => {
98
+ if (error.name !== "SlateError" || !isApiErrorRecord(error.data)) {
99
+ return void 0;
100
+ }
101
+ let data = error.data;
102
+ let upstream = isApiErrorRecord(data.upstream) ? data.upstream : void 0;
103
+ let status = upstream?.status ?? data.status;
104
+ return typeof status === "number" || typeof status === "string" ? { status } : void 0;
105
+ };
106
+ var getApiErrorResponse = (error) => {
107
+ if (!isApiErrorRecord(error)) {
108
+ return void 0;
109
+ }
110
+ if (!isApiErrorRecord(error.response)) {
111
+ return getSlateErrorResponse(error);
112
+ }
113
+ let response = error.response;
114
+ return {
115
+ status: typeof response.status === "number" || typeof response.status === "string" ? response.status : void 0,
116
+ statusText: typeof response.statusText === "string" ? response.statusText : void 0,
117
+ data: response.data
118
+ };
119
+ };
120
+ var getApiErrorStatus = (error) => getApiErrorResponse(error)?.status;
121
+ var statusLabelForApiError = (status, statusText) => status !== void 0 ? `HTTP ${status}${statusText ? ` ${statusText}` : ""}: ` : "";
122
+ var extractApiErrorMessage = (error, options = {}) => {
123
+ let details = [];
124
+ let response = options.response ?? getApiErrorResponse(error);
125
+ collectApiErrorDetails(response?.data, details, options);
126
+ if (details.length > 0) {
127
+ return details.join(options.separator ?? " - ");
128
+ }
129
+ if (error instanceof Error && error.message) {
130
+ return error.message;
131
+ }
132
+ return options.fallbackMessage ?? "Unknown error";
133
+ };
134
+ var createApiServiceError = (message, options = {}) => {
135
+ let error = new ServiceError(badRequestError({ message }));
136
+ if (options.reason !== void 0) {
137
+ error.data.reason = options.reason;
138
+ }
139
+ if ("upstreamStatus" in options) {
140
+ error.data.upstreamStatus = options.upstreamStatus;
141
+ }
142
+ if ("upstreamCode" in options) {
143
+ error.data.upstreamCode = options.upstreamCode;
144
+ }
145
+ if (options.parent instanceof Error) {
146
+ error.setParent(options.parent);
147
+ }
148
+ return error;
149
+ };
150
+ var helpers = {
151
+ collectDetails: collectApiErrorDetails,
152
+ extractMessage: extractApiErrorMessage,
153
+ getResponse: getApiErrorResponse,
154
+ getStatus: getApiErrorStatus,
155
+ isRecord: isApiErrorRecord,
156
+ statusLabelFor: statusLabelForApiError
157
+ };
158
+ var buildApiServiceError = (error, options) => {
159
+ if (error instanceof ServiceError) {
160
+ return error;
161
+ }
162
+ let operation = options.operation ?? "request";
163
+ let response = options.extractResponse?.(error, helpers) ?? getApiErrorResponse(error);
164
+ let status = options.extractStatus?.(error, response, helpers) ?? response?.status;
165
+ let message = options.extractMessage?.(error, helpers) ?? extractApiErrorMessage(error, { ...options, response });
166
+ let statusLabel = statusLabelForApiError(status, response?.statusText);
167
+ let fullMessage = options.formatMessage?.({
168
+ providerLabel: options.providerLabel,
169
+ operation,
170
+ statusLabel,
171
+ message,
172
+ response,
173
+ status
174
+ }) ?? `${options.providerLabel} API ${operation} failed: ${statusLabel}${message}`;
175
+ return createApiServiceError(fullMessage, {
176
+ reason: options.reason,
177
+ upstreamStatus: status,
178
+ upstreamCode: options.extractUpstreamCode?.(error, response, helpers),
179
+ parent: options.parent ?? error
180
+ });
57
181
  };
58
182
 
59
183
  // src/error/axios.ts
@@ -680,11 +804,12 @@ var isScopes = (value) => typeof value === "object" && value !== null && "AND" i
680
804
 
681
805
  // src/action/builder.ts
682
806
  var SlateActionBuilder = class {
683
- constructor(type, spec2, params, factory) {
807
+ constructor(type, spec2, params, factory, isPublicTool = false) {
684
808
  this.type = type;
685
809
  this.spec = spec2;
686
810
  this.params = params;
687
811
  this.factory = factory;
812
+ this.isPublicTool = isPublicTool;
688
813
  this.#configSchema = spec2.configSchema;
689
814
  this.#authSchema = spec2.authSchema;
690
815
  }
@@ -692,6 +817,7 @@ var SlateActionBuilder = class {
692
817
  spec;
693
818
  params;
694
819
  factory;
820
+ isPublicTool;
695
821
  #configSchema;
696
822
  #authSchema;
697
823
  #inputSchema = null;
@@ -700,20 +826,34 @@ var SlateActionBuilder = class {
700
826
  #authMethods;
701
827
  #toolParams = null;
702
828
  #triggerParams = null;
829
+ #interfaceLocked = false;
703
830
  input(schema) {
831
+ if (this.#interfaceLocked) {
832
+ throw new SlateDeclarationError("Adapter contract input schema cannot be changed");
833
+ }
704
834
  this.#inputSchema = schema;
705
835
  return this;
706
836
  }
707
837
  output(schema) {
838
+ if (this.#interfaceLocked) {
839
+ throw new SlateDeclarationError("Adapter contract output schema cannot be changed");
840
+ }
708
841
  this.#outputSchema = schema;
709
842
  return this;
710
843
  }
844
+ lockInterface() {
845
+ this.#interfaceLocked = true;
846
+ return this;
847
+ }
711
848
  scopes(scopes) {
712
849
  validateScopes(scopes);
713
850
  this.#scopes = scopes;
714
851
  return this;
715
852
  }
716
853
  authMethods(authMethods) {
854
+ if (this.isPublicTool) {
855
+ throw new SlateDeclarationError("Public tools cannot require authentication methods");
856
+ }
717
857
  this.#authMethods = this.validateAuthMethods(authMethods);
718
858
  return this;
719
859
  }
@@ -745,7 +885,8 @@ var SlateActionBuilder = class {
745
885
  handleEvent: props.handleEvent,
746
886
  handleRequest: props.handleRequest,
747
887
  autoRegisterWebhook: props.autoRegisterWebhook,
748
- autoUnregisterWebhook: props.autoUnregisterWebhook
888
+ autoUnregisterWebhook: props.autoUnregisterWebhook,
889
+ http: props.http
749
890
  };
750
891
  return this;
751
892
  }
@@ -768,6 +909,9 @@ var SlateActionBuilder = class {
768
909
  validateScopes(scopes);
769
910
  }
770
911
  let authMethods = this.validateAuthMethods(this.#authMethods ?? this.params.authMethods);
912
+ if (this.isPublicTool && authMethods) {
913
+ throw new SlateDeclarationError("Public tools cannot require authentication methods");
914
+ }
771
915
  if (!this.#inputSchema) {
772
916
  throw new SlateDeclarationError("Input schema is not defined");
773
917
  }
@@ -784,6 +928,7 @@ var SlateActionBuilder = class {
784
928
  ...this.params,
785
929
  scopes,
786
930
  authMethods,
931
+ isPublic: this.isPublicTool === true,
787
932
  configSchema: this.#configSchema,
788
933
  authSchema: this.#authSchema,
789
934
  inputSchema: this.#inputSchema,
@@ -803,16 +948,40 @@ var SlateTool = class _SlateTool extends SlateAction {
803
948
  }
804
949
  static create(spec2, params) {
805
950
  return new SlateActionBuilder("tool", spec2, params, (params2) => {
806
- if (params2.type !== "tool") throw new Error("Invalid action type for tool");
807
- return new _SlateTool(spec2, params2.inputSchema, params2.outputSchema, params2);
951
+ return _SlateTool.fromCreateParameters(spec2, params2);
808
952
  });
809
953
  }
954
+ static fromCreateParameters(spec2, params) {
955
+ if (params.type !== "tool") throw new Error("Invalid action type for tool");
956
+ return new _SlateTool(spec2, params.inputSchema, params.outputSchema, params);
957
+ }
810
958
  get handleInvocation() {
811
959
  return this.#handleInvocation;
812
960
  }
813
961
  };
814
962
  var tool = (spec2, params) => SlateTool.create(spec2, params);
815
963
 
964
+ // src/action/publicTool.ts
965
+ var SlatePublicTool = class {
966
+ constructor() {
967
+ }
968
+ static create(spec2, params) {
969
+ return new SlateActionBuilder(
970
+ "tool",
971
+ spec2,
972
+ params,
973
+ (params2) => {
974
+ return SlateTool.fromCreateParameters(spec2, {
975
+ ...params2,
976
+ isPublic: true
977
+ });
978
+ },
979
+ true
980
+ );
981
+ }
982
+ };
983
+ var publicTool = (spec2, params) => SlatePublicTool.create(spec2, params);
984
+
816
985
  // src/action/trigger.ts
817
986
  var SlateDefaultPollingIntervalSeconds = 60 * 10;
818
987
  var SlateTrigger = class _SlateTrigger extends SlateAction {
@@ -820,6 +989,7 @@ var SlateTrigger = class _SlateTrigger extends SlateAction {
820
989
  #polling;
821
990
  #handleEvent;
822
991
  #handleRequest;
992
+ #http;
823
993
  #pollEvents;
824
994
  #autoRegisterWebhook;
825
995
  #autoUnregisterWebhook;
@@ -831,6 +1001,7 @@ var SlateTrigger = class _SlateTrigger extends SlateAction {
831
1001
  };
832
1002
  this.#handleEvent = params.handleEvent;
833
1003
  this.#handleRequest = params.handleRequest;
1004
+ this.#http = params.http;
834
1005
  this.#pollEvents = params.pollEvents;
835
1006
  this.#autoRegisterWebhook = params.autoRegisterWebhook;
836
1007
  this.#autoUnregisterWebhook = params.autoUnregisterWebhook;
@@ -853,6 +1024,9 @@ var SlateTrigger = class _SlateTrigger extends SlateAction {
853
1024
  get handleRequest() {
854
1025
  return this.#handleRequest;
855
1026
  }
1027
+ get http() {
1028
+ return this.#http;
1029
+ }
856
1030
  get pollEvents() {
857
1031
  return this.#pollEvents;
858
1032
  }
@@ -890,6 +1064,135 @@ var createTextAttachment = (content, mimeType) => ({
890
1064
  }
891
1065
  });
892
1066
 
1067
+ // src/adapter/adapter.ts
1068
+ var SlateAdapter = class {
1069
+ constructor(_spec, _tools, _triggers) {
1070
+ this._spec = _spec;
1071
+ this._tools = _tools;
1072
+ this._triggers = _triggers;
1073
+ }
1074
+ _spec;
1075
+ _tools;
1076
+ _triggers;
1077
+ get spec() {
1078
+ return this._spec;
1079
+ }
1080
+ get id() {
1081
+ return this._spec.id;
1082
+ }
1083
+ get name() {
1084
+ return this._spec.name;
1085
+ }
1086
+ get capabilities() {
1087
+ return this._spec.capabilities;
1088
+ }
1089
+ get tools() {
1090
+ return this._tools;
1091
+ }
1092
+ get triggers() {
1093
+ return this._triggers;
1094
+ }
1095
+ get actions() {
1096
+ return [...this._triggers, ...this._tools];
1097
+ }
1098
+ };
1099
+
1100
+ // src/adapter/spec.ts
1101
+ var SlateAdapterSpec = class _SlateAdapterSpec {
1102
+ constructor(_params) {
1103
+ this._params = _params;
1104
+ }
1105
+ _params;
1106
+ static create(params) {
1107
+ let id = params.id?.trim();
1108
+ let name = params.name?.trim();
1109
+ if (!id) {
1110
+ throw new SlateDeclarationError("Adapter id must be a non-empty string");
1111
+ }
1112
+ if (!name) {
1113
+ throw new SlateDeclarationError("Adapter name must be a non-empty string");
1114
+ }
1115
+ return new _SlateAdapterSpec({
1116
+ id,
1117
+ name,
1118
+ capabilities: validateCapabilities(params.capabilities ?? [])
1119
+ });
1120
+ }
1121
+ get id() {
1122
+ return this._params.id;
1123
+ }
1124
+ get name() {
1125
+ return this._params.name;
1126
+ }
1127
+ get capabilities() {
1128
+ return this._params.capabilities;
1129
+ }
1130
+ get parameters() {
1131
+ return this._params;
1132
+ }
1133
+ tool(spec2, params) {
1134
+ return SlateTool.create(spec2, this.linkAction(params));
1135
+ }
1136
+ publicTool(spec2, params) {
1137
+ return SlatePublicTool.create(spec2, this.linkAction(params));
1138
+ }
1139
+ trigger(spec2, params) {
1140
+ return SlateTrigger.create(spec2, this.linkAction(params));
1141
+ }
1142
+ register(params) {
1143
+ let actions = [...params.tools, ...params.triggers];
1144
+ let seenKeys = /* @__PURE__ */ new Set();
1145
+ for (let action of actions) {
1146
+ if (action.adapter && action.adapter !== this.id) {
1147
+ throw new SlateDeclarationError(
1148
+ `Action "${action.key}" is linked to adapter "${action.adapter}", not "${this.id}"`
1149
+ );
1150
+ }
1151
+ if (!action.adapter) {
1152
+ throw new SlateDeclarationError(
1153
+ `Action "${action.key}" must be created with this adapter's tool(), publicTool(), or trigger() helpers`
1154
+ );
1155
+ }
1156
+ if (seenKeys.has(action.key)) {
1157
+ throw new SlateDeclarationError(
1158
+ `Adapter "${this.id}" already has an action with key "${action.key}"`
1159
+ );
1160
+ }
1161
+ seenKeys.add(action.key);
1162
+ }
1163
+ return new SlateAdapter(this, params.tools, params.triggers);
1164
+ }
1165
+ linkAction(params) {
1166
+ if (params.adapter != null && params.adapter !== this.id) {
1167
+ throw new SlateDeclarationError(
1168
+ `Action "${params.key}" cannot be linked to adapter "${this.id}" because it is already linked to "${params.adapter}"`
1169
+ );
1170
+ }
1171
+ return {
1172
+ ...params,
1173
+ adapter: this.id
1174
+ };
1175
+ }
1176
+ };
1177
+ var adapterSpec = (params) => SlateAdapterSpec.create(params);
1178
+ var validateCapabilities = (capabilities) => {
1179
+ let seenIds = /* @__PURE__ */ new Set();
1180
+ return capabilities.map((capability) => {
1181
+ let id = capability.id?.trim();
1182
+ if (!id) {
1183
+ throw new SlateDeclarationError("Adapter capability ids must be non-empty strings");
1184
+ }
1185
+ if (seenIds.has(id)) {
1186
+ throw new SlateDeclarationError(`Adapter capability "${id}" is defined more than once`);
1187
+ }
1188
+ seenIds.add(id);
1189
+ return {
1190
+ id,
1191
+ value: capability.value
1192
+ };
1193
+ });
1194
+ };
1195
+
893
1196
  // src/auth/auth.ts
894
1197
  var SlateAuth = class _SlateAuth {
895
1198
  #outputSchema = null;
@@ -947,6 +1250,90 @@ var SlateAuth = class _SlateAuth {
947
1250
  };
948
1251
  var auth = () => SlateAuth.create();
949
1252
 
1253
+ // src/auth/oauth.ts
1254
+ var isOAuthTokenResponse = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1255
+ var formatOAuthTokenResponseMessage = (fieldLabel, providerLabel = "OAuth provider", operation = "token response") => `${providerLabel} OAuth ${operation} did not return ${fieldLabel}.`;
1256
+ var getOAuthExpiresAtFromExpiresIn = (expiresIn, options = {}) => {
1257
+ let {
1258
+ nowMs = Date.now(),
1259
+ providerLabel,
1260
+ operation,
1261
+ required = false,
1262
+ expiresInType = "numberLike",
1263
+ message
1264
+ } = options;
1265
+ if (expiresIn === void 0 || expiresIn === null || expiresIn === "") {
1266
+ if (required) {
1267
+ throw createApiServiceError(
1268
+ message ?? formatOAuthTokenResponseMessage(
1269
+ "a valid expires_in value",
1270
+ providerLabel,
1271
+ operation
1272
+ ),
1273
+ { reason: "oauth_token_response" }
1274
+ );
1275
+ }
1276
+ return void 0;
1277
+ }
1278
+ let seconds = typeof expiresIn === "number" ? expiresIn : expiresInType === "numberLike" && typeof expiresIn === "string" ? Number(expiresIn) : Number.NaN;
1279
+ if (!Number.isFinite(seconds)) {
1280
+ throw createApiServiceError(
1281
+ message ?? formatOAuthTokenResponseMessage("a valid expires_in value", providerLabel, operation),
1282
+ { reason: "oauth_token_response" }
1283
+ );
1284
+ }
1285
+ return new Date(nowMs + seconds * 1e3).toISOString();
1286
+ };
1287
+ var getRefreshToken = (refreshToken, previousRefreshToken, fallbackMode) => {
1288
+ if (typeof refreshToken === "string") {
1289
+ if (fallbackMode === "falsy" && !refreshToken) {
1290
+ return previousRefreshToken;
1291
+ }
1292
+ return refreshToken;
1293
+ }
1294
+ if (fallbackMode === "falsy" && !refreshToken) {
1295
+ return previousRefreshToken;
1296
+ }
1297
+ return refreshToken === void 0 || refreshToken === null ? previousRefreshToken : void 0;
1298
+ };
1299
+ var normalizeOAuthTokenResponse = (data, options = {}) => {
1300
+ let {
1301
+ providerLabel,
1302
+ operation,
1303
+ previousRefreshToken,
1304
+ refreshTokenFallbackMode = "nullish",
1305
+ accessTokenMessage,
1306
+ expiresInMessage,
1307
+ ...expiresAtOptions
1308
+ } = options;
1309
+ if (!isOAuthTokenResponse(data)) {
1310
+ throw createApiServiceError(
1311
+ accessTokenMessage ?? formatOAuthTokenResponseMessage("a token response object", providerLabel, operation),
1312
+ { reason: "oauth_token_response" }
1313
+ );
1314
+ }
1315
+ if (typeof data.access_token !== "string" || !data.access_token) {
1316
+ throw createApiServiceError(
1317
+ accessTokenMessage ?? formatOAuthTokenResponseMessage("an access token", providerLabel, operation),
1318
+ { reason: "oauth_token_response" }
1319
+ );
1320
+ }
1321
+ return {
1322
+ token: data.access_token,
1323
+ refreshToken: getRefreshToken(
1324
+ data.refresh_token,
1325
+ previousRefreshToken,
1326
+ refreshTokenFallbackMode
1327
+ ),
1328
+ expiresAt: getOAuthExpiresAtFromExpiresIn(data.expires_in, {
1329
+ ...expiresAtOptions,
1330
+ providerLabel,
1331
+ operation,
1332
+ message: expiresInMessage
1333
+ })
1334
+ };
1335
+ };
1336
+
950
1337
  // src/axios/index.ts
951
1338
  import baseAxios, { getAdapter, isAxiosError as isAxiosError2 } from "axios";
952
1339
 
@@ -1530,6 +1917,35 @@ var createAxios = (config2) => {
1530
1917
  applySlateInterceptors(instance, errorMapping);
1531
1918
  return instance;
1532
1919
  };
1920
+ var createAuthenticatedAxios = (config2) => {
1921
+ let { authHeader, contentType = "application/json", errorAdapter, ...axiosConfig } = config2;
1922
+ let instance = createAxios({
1923
+ ...axiosConfig,
1924
+ headers: {
1925
+ ...contentType === false ? {} : { "Content-Type": contentType },
1926
+ ...authHeader ? { [authHeader.name ?? "Authorization"]: authHeader.value } : {},
1927
+ ...axiosConfig.headers
1928
+ }
1929
+ });
1930
+ if (errorAdapter) {
1931
+ instance.interceptors.response.use(
1932
+ (response) => response,
1933
+ (error) => Promise.reject(errorAdapter(error))
1934
+ );
1935
+ }
1936
+ return instance;
1937
+ };
1938
+ var requestAxios = async (operation, request, errorAdapter) => {
1939
+ try {
1940
+ return await request();
1941
+ } catch (error) {
1942
+ throw errorAdapter(error, operation);
1943
+ }
1944
+ };
1945
+ var requestAxiosData = async (operation, request, errorAdapter) => {
1946
+ let response = await requestAxios(operation, request, errorAdapter);
1947
+ return response.data;
1948
+ };
1533
1949
  var axios = createAxios();
1534
1950
 
1535
1951
  // src/config/config.ts
@@ -1576,26 +1992,19 @@ var SlateConfig = class _SlateConfig {
1576
1992
  var config = (schema) => SlateConfig.create(schema);
1577
1993
 
1578
1994
  // src/context/context.ts
1579
- var SlateContext = class {
1580
- constructor(config2, input, auth2, spec2, logger) {
1995
+ var SlatePublicContext = class {
1996
+ constructor(input, spec2, logger) {
1581
1997
  this.spec = spec2;
1582
1998
  this.logger = logger;
1583
- this.#config = config2;
1584
1999
  this.#input = input;
1585
- this.#auth = auth2;
1586
2000
  }
1587
2001
  spec;
1588
2002
  logger;
1589
- #config;
1590
2003
  #input;
1591
- #auth;
1592
2004
  #httpTraces = [];
1593
2005
  get specification() {
1594
2006
  return this.spec;
1595
2007
  }
1596
- get config() {
1597
- return Object.freeze(this.#config);
1598
- }
1599
2008
  get input() {
1600
2009
  return Object.freeze(this.#input);
1601
2010
  }
@@ -1608,8 +2017,10 @@ var SlateContext = class {
1608
2017
  get request() {
1609
2018
  return Object.freeze(this.#input.request);
1610
2019
  }
1611
- get auth() {
1612
- return Object.freeze(this.#auth);
2020
+ get registrationDetails() {
2021
+ return Object.freeze(
2022
+ this.#input.registrationDetails
2023
+ );
1613
2024
  }
1614
2025
  recordHttpTrace(trace) {
1615
2026
  this.#httpTraces.push(trace);
@@ -1645,6 +2056,60 @@ var SlateContext = class {
1645
2056
  this.logger.progress(message);
1646
2057
  }
1647
2058
  };
2059
+ var SlateContext = class extends SlatePublicContext {
2060
+ #config;
2061
+ #auth;
2062
+ constructor(config2, input, auth2, spec2, logger) {
2063
+ super(input, spec2, logger);
2064
+ this.#config = config2;
2065
+ this.#auth = auth2;
2066
+ }
2067
+ get config() {
2068
+ return Object.freeze(this.#config);
2069
+ }
2070
+ get auth() {
2071
+ return Object.freeze(this.#auth);
2072
+ }
2073
+ };
2074
+
2075
+ // src/crypto/hmac.ts
2076
+ import { createHmac, timingSafeEqual } from "crypto";
2077
+ var createHmacSignature = ({
2078
+ secret,
2079
+ payload,
2080
+ algorithm = "sha256",
2081
+ digest,
2082
+ prefix = ""
2083
+ }) => `${prefix}${createHmac(algorithm, secret).update(payload).digest(digest)}`;
2084
+ var verifyHmacSignature = (options) => {
2085
+ let expected = createHmacSignature(options);
2086
+ let expectedBytes = Buffer.from(expected);
2087
+ let signatureBytes = Buffer.from(options.signature);
2088
+ let lengthsMatch = signatureBytes.length === expectedBytes.length;
2089
+ let comparableSignature = lengthsMatch ? signatureBytes : Buffer.alloc(expectedBytes.length);
2090
+ return timingSafeEqual(comparableSignature, expectedBytes) && lengthsMatch;
2091
+ };
2092
+
2093
+ // src/file/index.ts
2094
+ var getResponseHeaderValue = (headers, name) => {
2095
+ if (!headers) return void 0;
2096
+ if (typeof headers.get === "function") {
2097
+ let value = headers.get(name);
2098
+ return typeof value === "string" ? value : void 0;
2099
+ }
2100
+ if (typeof headers !== "object") return void 0;
2101
+ let lowerName = name.toLowerCase();
2102
+ for (let [headerName, value] of Object.entries(headers)) {
2103
+ if (headerName.toLowerCase() !== lowerName) continue;
2104
+ if (Array.isArray(value)) {
2105
+ let first = value.find((item) => typeof item === "string");
2106
+ return typeof first === "string" ? first : void 0;
2107
+ }
2108
+ return typeof value === "string" ? value : void 0;
2109
+ }
2110
+ return void 0;
2111
+ };
2112
+ var getBase64ByteLength = (contentBase64) => Buffer.from(contentBase64, "base64").byteLength;
1648
2113
 
1649
2114
  // src/logger/logger.ts
1650
2115
  import { encode } from "@toon-format/toon";
@@ -1741,16 +2206,53 @@ var SlateLogger = class {
1741
2206
  }
1742
2207
  };
1743
2208
 
2209
+ // src/object/index.ts
2210
+ var pickDefined = (value) => Object.fromEntries(
2211
+ Object.entries(value).filter(([, child]) => child !== void 0)
2212
+ );
2213
+ var setIfDefined = (target, key, value) => {
2214
+ if (value !== void 0) {
2215
+ target[key] = value;
2216
+ }
2217
+ return target;
2218
+ };
2219
+
1744
2220
  // src/specification/slate.ts
1745
2221
  var Slate = class _Slate {
1746
- constructor(_spec, _actions) {
2222
+ constructor(_spec, _actions, _adapters) {
1747
2223
  this._spec = _spec;
1748
2224
  this._actions = _actions;
2225
+ this._adapters = _adapters;
1749
2226
  }
1750
2227
  _spec;
1751
2228
  _actions;
2229
+ _adapters;
1752
2230
  static create(params) {
1753
- return new _Slate(params.spec, [...params.triggers, ...params.tools]);
2231
+ let adapters = params.adapters ?? [];
2232
+ let actions = [...params.triggers, ...params.tools];
2233
+ let seenAdapterIds = /* @__PURE__ */ new Set();
2234
+ let seenActionKeys = new Map(actions.map((action) => [action.key, action]));
2235
+ for (let adapter of adapters) {
2236
+ if (seenAdapterIds.has(adapter.id)) {
2237
+ throw new SlateDeclarationError(
2238
+ `Adapter "${adapter.id}" is registered more than once`
2239
+ );
2240
+ }
2241
+ seenAdapterIds.add(adapter.id);
2242
+ for (let action of adapter.actions) {
2243
+ let existing = seenActionKeys.get(action.key);
2244
+ if (existing && existing !== action) {
2245
+ throw new SlateDeclarationError(
2246
+ `Adapter "${adapter.id}" action "${action.key}" conflicts with another action`
2247
+ );
2248
+ }
2249
+ if (!existing) {
2250
+ actions.push(action);
2251
+ seenActionKeys.set(action.key, action);
2252
+ }
2253
+ }
2254
+ }
2255
+ return new _Slate(params.spec, actions, adapters);
1754
2256
  }
1755
2257
  get spec() {
1756
2258
  return this._spec;
@@ -1758,6 +2260,9 @@ var Slate = class _Slate {
1758
2260
  get actions() {
1759
2261
  return this._actions;
1760
2262
  }
2263
+ get adapters() {
2264
+ return this._adapters;
2265
+ }
1761
2266
  };
1762
2267
 
1763
2268
  // src/specification/specification.ts
@@ -1803,9 +2308,65 @@ var SlateSpecification = class _SlateSpecification {
1803
2308
  }
1804
2309
  };
1805
2310
  var spec = (params) => SlateSpecification.create(params);
2311
+
2312
+ // src/webhook/graph.ts
2313
+ var graphWebhookHttp = {
2314
+ methods: ["POST"],
2315
+ sync: {
2316
+ mode: "match",
2317
+ match: [{ hasQueryParam: "validationToken" }]
2318
+ }
2319
+ };
2320
+ var getGraphWebhookValidationResponse = (request) => {
2321
+ let validationToken = new URL(request.url).searchParams.get("validationToken");
2322
+ if (validationToken === null) return null;
2323
+ return {
2324
+ status: 200,
2325
+ headers: { "content-type": "text/plain" },
2326
+ body: validationToken
2327
+ };
2328
+ };
2329
+
2330
+ // src/webhook/meta.ts
2331
+ var metaWebhookHttp = {
2332
+ methods: ["GET", "POST"],
2333
+ sync: {
2334
+ mode: "match",
2335
+ match: [{ method: "GET", hasQueryParam: "hub.mode" }]
2336
+ }
2337
+ };
2338
+ var getMetaWebhookVerificationResponse = (request, expectedVerifyToken) => {
2339
+ if (request.method !== "GET") return null;
2340
+ let url = new URL(request.url);
2341
+ let mode = url.searchParams.get("hub.mode");
2342
+ let verifyToken = url.searchParams.get("hub.verify_token");
2343
+ let challenge = url.searchParams.get("hub.challenge");
2344
+ if (mode !== "subscribe" || challenge === null) {
2345
+ return {
2346
+ status: 400,
2347
+ headers: { "content-type": "text/plain" },
2348
+ body: "invalid webhook verification request"
2349
+ };
2350
+ }
2351
+ if (expectedVerifyToken !== void 0 && verifyToken !== expectedVerifyToken) {
2352
+ return {
2353
+ status: 403,
2354
+ headers: { "content-type": "text/plain" },
2355
+ body: "invalid verify token"
2356
+ };
2357
+ }
2358
+ return {
2359
+ status: 200,
2360
+ headers: { "content-type": "text/plain" },
2361
+ body: challenge
2362
+ };
2363
+ };
1806
2364
  export {
1807
2365
  Slate,
1808
2366
  SlateAction,
2367
+ SlateActionBuilder,
2368
+ SlateAdapter,
2369
+ SlateAdapterSpec,
1809
2370
  SlateAuth,
1810
2371
  SlateConfig,
1811
2372
  SlateContext,
@@ -1813,31 +2374,58 @@ export {
1813
2374
  SlateDefaultPollingIntervalSeconds,
1814
2375
  SlateError,
1815
2376
  SlateLogger,
2377
+ SlatePublicContext,
2378
+ SlatePublicTool,
1816
2379
  SlateSpecification,
1817
2380
  SlateTool,
1818
2381
  SlateTrigger,
2382
+ adapterSpec,
1819
2383
  allOf,
1820
2384
  anyOf,
1821
2385
  auth,
1822
2386
  axios,
2387
+ buildApiServiceError,
2388
+ collectApiErrorDetails,
1823
2389
  config,
2390
+ createApiServiceError,
2391
+ createAuthenticatedAxios,
1824
2392
  createAxios,
1825
2393
  createBase64Attachment,
2394
+ createHmacSignature,
1826
2395
  createSlateError,
1827
2396
  createTextAttachment,
1828
2397
  createUrlAttachment,
2398
+ extractApiErrorMessage,
2399
+ getApiErrorResponse,
2400
+ getApiErrorStatus,
2401
+ getBase64ByteLength,
1829
2402
  getCurrentContext,
2403
+ getGraphWebhookValidationResponse,
2404
+ getMetaWebhookVerificationResponse,
2405
+ getOAuthExpiresAtFromExpiresIn,
2406
+ getResponseHeaderValue,
1830
2407
  getServiceErrorData,
2408
+ graphWebhookHttp,
1831
2409
  inferSlateErrorFromAxios,
2410
+ isApiErrorRecord,
1832
2411
  isAxiosErrorLike,
1833
2412
  isServiceErrorData,
1834
2413
  mapServiceErrorCode,
1835
2414
  mapServiceErrorToSlateErrorInput,
1836
2415
  mergeScopes,
2416
+ metaWebhookHttp,
2417
+ normalizeOAuthTokenResponse,
2418
+ pickDefined,
2419
+ publicTool,
2420
+ requestAxios,
2421
+ requestAxiosData,
1837
2422
  runWithContext,
1838
2423
  scopeClause,
2424
+ setIfDefined,
1839
2425
  spec,
2426
+ statusLabelForApiError,
1840
2427
  tool,
1841
2428
  trigger,
1842
- validateScopes
2429
+ validateScopes,
2430
+ verifyHmacSignature
1843
2431
  };