@isomorph.ai/app-sdk 1.12.0 → 1.13.0
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.d.ts
CHANGED
|
@@ -238,7 +238,24 @@ export interface GmailMessageSendRequest {
|
|
|
238
238
|
/** A fresh UUID per authorized Send action, reused only to retry that action. */
|
|
239
239
|
idempotencyKey: string;
|
|
240
240
|
}
|
|
241
|
-
export
|
|
241
|
+
export interface ServiceRequest {
|
|
242
|
+
operation: 'service.request';
|
|
243
|
+
resource?: never;
|
|
244
|
+
input: {
|
|
245
|
+
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
246
|
+
path: string;
|
|
247
|
+
pathParams?: Record<string, string | number>;
|
|
248
|
+
query?: Record<string, string | number | boolean>;
|
|
249
|
+
headers?: Record<string, string>;
|
|
250
|
+
body?: Record<string, unknown>;
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
export interface ServiceRequestResult {
|
|
254
|
+
status: number;
|
|
255
|
+
headers: Record<string, string>;
|
|
256
|
+
body: unknown;
|
|
257
|
+
}
|
|
258
|
+
export type IntegrationRequest = ServiceRequest | SlackChannelHistoryRequest | SlackMessagePostRequest | SlackMessageUpdateRequest | SlackMessageDeleteRequest | SlackDmSendRequest | SlackUserLookupRequest | WarehouseViewReadRequest | GmailThreadListRequest | GmailThreadReadRequest | GmailMessageReadRequest | GmailAttachmentReadRequest | GmailMessageSendRequest;
|
|
242
259
|
export type IntegrationOperation = IntegrationRequest['operation'];
|
|
243
260
|
export interface SlackMessage {
|
|
244
261
|
id: string;
|
|
@@ -324,7 +341,7 @@ export interface GmailMessageSendResult {
|
|
|
324
341
|
messageId: string;
|
|
325
342
|
threadId: string;
|
|
326
343
|
}
|
|
327
|
-
export type IntegrationResult<R extends IntegrationRequest> = R extends SlackChannelHistoryRequest ? SlackChannelHistoryResult : R extends SlackMessagePostRequest | SlackMessageUpdateRequest | SlackMessageDeleteRequest ? SlackMessagePostResult : R extends SlackDmSendRequest ? SlackDmSendResult : R extends SlackUserLookupRequest ? SlackUserLookupResult : R extends WarehouseViewReadRequest ? WarehouseViewReadResult : R extends GmailThreadListRequest ? GmailThreadListResult : R extends GmailThreadReadRequest ? GmailThreadReadResult : R extends GmailMessageReadRequest ? GmailMessageReadResult : R extends GmailAttachmentReadRequest ? GmailAttachmentReadResult : R extends GmailMessageSendRequest ? GmailMessageSendResult : never;
|
|
344
|
+
export type IntegrationResult<R extends IntegrationRequest> = R extends ServiceRequest ? ServiceRequestResult : R extends SlackChannelHistoryRequest ? SlackChannelHistoryResult : R extends SlackMessagePostRequest | SlackMessageUpdateRequest | SlackMessageDeleteRequest ? SlackMessagePostResult : R extends SlackDmSendRequest ? SlackDmSendResult : R extends SlackUserLookupRequest ? SlackUserLookupResult : R extends WarehouseViewReadRequest ? WarehouseViewReadResult : R extends GmailThreadListRequest ? GmailThreadListResult : R extends GmailThreadReadRequest ? GmailThreadReadResult : R extends GmailMessageReadRequest ? GmailMessageReadResult : R extends GmailAttachmentReadRequest ? GmailAttachmentReadResult : R extends GmailMessageSendRequest ? GmailMessageSendResult : never;
|
|
328
345
|
export type IntegrationConnectResult = {
|
|
329
346
|
status: 'connected';
|
|
330
347
|
accountLabel: string;
|
package/dist/index.js
CHANGED
|
@@ -189,7 +189,13 @@ class Transport {
|
|
|
189
189
|
const response = await this.fetch(`${this.baseUrl}${path}`, {
|
|
190
190
|
credentials: 'same-origin',
|
|
191
191
|
...init,
|
|
192
|
-
headers: mergeHeaders(
|
|
192
|
+
headers: mergeHeaders(
|
|
193
|
+
// No content type on a request without a body: a browser GET that
|
|
194
|
+
// carries one is not a "simple" request, so it costs a CORS preflight
|
|
195
|
+
// (OPTIONS, one more round trip, on a separate uncredentialed
|
|
196
|
+
// connection a preconnect cannot warm) before the GET itself. Without
|
|
197
|
+
// it the identity GET and every other read is one round trip.
|
|
198
|
+
init.body === undefined && ['GET', 'HEAD'].includes((init.method ?? 'GET').toUpperCase()) ? {} : { 'content-type': 'application/json' }, runnerIdentityHeaders(this.identity), init.headers, onProgress ? { accept: PROGRESS_MEDIA_TYPE } : undefined),
|
|
193
199
|
});
|
|
194
200
|
if (onProgress && response.ok && response.body && response.headers.get('content-type')?.startsWith(PROGRESS_MEDIA_TYPE)) {
|
|
195
201
|
return readProgress(response, onProgress);
|
|
@@ -737,7 +743,7 @@ export function createClient(options = {}) {
|
|
|
737
743
|
// operations accept `mode`; identity and stray fields are not sent.
|
|
738
744
|
const { operation, resource, input, idempotencyKey, mode } = request;
|
|
739
745
|
return transport.json('/_harbour/integrations/execute', {
|
|
740
|
-
method: 'POST', body: JSON.stringify({ connection, operation, resource, ...(input !== undefined ? { input } : {}), ...(idempotencyKey !== undefined ? { idempotencyKey } : {}), ...(IntegrationOperations[operation]?.declaredMode && mode !== undefined ? { mode } : {}) }),
|
|
746
|
+
method: 'POST', body: JSON.stringify({ connection, operation, ...(operation !== 'service.request' ? { resource } : {}), ...(input !== undefined ? { input } : {}), ...(idempotencyKey !== undefined ? { idempotencyKey } : {}), ...(IntegrationOperations[operation]?.declaredMode && mode !== undefined ? { mode } : {}) }),
|
|
741
747
|
});
|
|
742
748
|
},
|
|
743
749
|
// In a browser the consent returns the person to this page (without its
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
* same message wherever it is made.
|
|
7
7
|
*/
|
|
8
8
|
export type IntegrationExecuteInputFieldRule = {
|
|
9
|
+
kind: 'object';
|
|
10
|
+
required: boolean;
|
|
11
|
+
} | {
|
|
9
12
|
kind: 'integer';
|
|
10
13
|
required: boolean;
|
|
11
14
|
minimum: number;
|
|
@@ -461,6 +464,38 @@ export declare const IntegrationExecuteInputRules: {
|
|
|
461
464
|
};
|
|
462
465
|
};
|
|
463
466
|
};
|
|
467
|
+
readonly "service.request": {
|
|
468
|
+
readonly idempotencyKey: false;
|
|
469
|
+
readonly fields: {
|
|
470
|
+
readonly method: {
|
|
471
|
+
readonly kind: "enum";
|
|
472
|
+
readonly required: true;
|
|
473
|
+
readonly values: readonly ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
474
|
+
};
|
|
475
|
+
readonly path: {
|
|
476
|
+
readonly kind: "string";
|
|
477
|
+
readonly required: true;
|
|
478
|
+
readonly minLength: 0;
|
|
479
|
+
readonly maxLength: 16384;
|
|
480
|
+
};
|
|
481
|
+
readonly pathParams: {
|
|
482
|
+
readonly kind: "object";
|
|
483
|
+
readonly required: false;
|
|
484
|
+
};
|
|
485
|
+
readonly query: {
|
|
486
|
+
readonly kind: "object";
|
|
487
|
+
readonly required: false;
|
|
488
|
+
};
|
|
489
|
+
readonly headers: {
|
|
490
|
+
readonly kind: "object";
|
|
491
|
+
readonly required: false;
|
|
492
|
+
};
|
|
493
|
+
readonly body: {
|
|
494
|
+
readonly kind: "object";
|
|
495
|
+
readonly required: false;
|
|
496
|
+
};
|
|
497
|
+
};
|
|
498
|
+
};
|
|
464
499
|
};
|
|
465
500
|
export type IntegrationExecuteOperation = keyof typeof IntegrationExecuteInputRules;
|
|
466
501
|
/** The upper bound of one integer input as a literal type: integrationExecuteInputMaximum('slack.channel.history', 'limit') is 15. */
|
|
@@ -113,6 +113,17 @@ export const IntegrationExecuteInputRules = {
|
|
|
113
113
|
limit: { kind: "integer", required: false, minimum: 1, maximum: 1000, default: 100 },
|
|
114
114
|
},
|
|
115
115
|
},
|
|
116
|
+
"service.request": {
|
|
117
|
+
idempotencyKey: false,
|
|
118
|
+
fields: {
|
|
119
|
+
method: { kind: "enum", required: true, values: ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"] },
|
|
120
|
+
path: { kind: "string", required: true, minLength: 0, maxLength: 16384 },
|
|
121
|
+
pathParams: { kind: "object", required: false },
|
|
122
|
+
query: { kind: "object", required: false },
|
|
123
|
+
headers: { kind: "object", required: false },
|
|
124
|
+
body: { kind: "object", required: false },
|
|
125
|
+
},
|
|
126
|
+
},
|
|
116
127
|
};
|
|
117
128
|
/** The upper bound of one integer input as a literal type: integrationExecuteInputMaximum('slack.channel.history', 'limit') is 15. */
|
|
118
129
|
export function integrationExecuteInputMaximum(operation, field) {
|
|
@@ -173,6 +184,10 @@ function checkFields(operation, prefix, fields, given, nullIsAbsent) {
|
|
|
173
184
|
}
|
|
174
185
|
function checkField(operation, path, name, field, value) {
|
|
175
186
|
switch (field.kind) {
|
|
187
|
+
case 'object':
|
|
188
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
189
|
+
return refuse(path, `${path} must be a JSON object`);
|
|
190
|
+
return { ok: true, value };
|
|
176
191
|
case 'integer':
|
|
177
192
|
if (typeof value !== 'number' || !Number.isInteger(value) || value < field.minimum || value > field.maximum)
|
|
178
193
|
return refuse(path, `${path} must be an integer between ${field.minimum} and ${field.maximum}`);
|
|
@@ -84,4 +84,11 @@ export declare const IntegrationOperations: {
|
|
|
84
84
|
readonly declaredMode: false;
|
|
85
85
|
readonly idempotencyKey: false;
|
|
86
86
|
};
|
|
87
|
+
readonly "service.request": {
|
|
88
|
+
readonly kind: "service";
|
|
89
|
+
readonly identities: readonly ["app"];
|
|
90
|
+
readonly readOnly: false;
|
|
91
|
+
readonly declaredMode: false;
|
|
92
|
+
readonly idempotencyKey: false;
|
|
93
|
+
};
|
|
87
94
|
};
|
|
@@ -113,5 +113,14 @@ export const IntegrationOperations = {
|
|
|
113
113
|
"readOnly": true,
|
|
114
114
|
"declaredMode": false,
|
|
115
115
|
"idempotencyKey": false
|
|
116
|
+
},
|
|
117
|
+
"service.request": {
|
|
118
|
+
"kind": "service",
|
|
119
|
+
"identities": [
|
|
120
|
+
"app"
|
|
121
|
+
],
|
|
122
|
+
"readOnly": false,
|
|
123
|
+
"declaredMode": false,
|
|
124
|
+
"idempotencyKey": false
|
|
116
125
|
}
|
|
117
126
|
};
|