@relayfile/sdk 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -20,10 +20,15 @@ const client = new RelayFileClient({
20
20
 
21
21
  const workspaceId = "workspace_123";
22
22
 
23
- const tree = await client.listTree(workspaceId, { path: "/", depth: 2 });
23
+ const tree = await client.listTree(workspaceId, {
24
+ path: "/",
25
+ depth: 2
26
+ });
27
+
24
28
  console.log(tree.entries.map((entry) => entry.path));
25
29
 
26
30
  const file = await client.readFile(workspaceId, "/notes/todo.md");
31
+
27
32
  console.log(file.content);
28
33
 
29
34
  await client.writeFile({
@@ -37,4 +42,4 @@ await client.writeFile({
37
42
 
38
43
  ## Full Docs
39
44
 
40
- Full documentation is available at https://github.com/AgentWorkforce/relayfile
45
+ Full documentation is available in the [relayfile docs](https://github.com/AgentWorkforce/relayfile/tree/main/docs).
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type AdminIngressStatusResponse, type AdminSyncStatusResponse, type BulkWriteInput, type BulkWriteResponse, type BackendStatusResponse, type AckResponse, type DeleteFileInput, type DeadLetterItem, type DeadLetterFeedResponse, type EventFeedResponse, type ExportJsonResponse, type ExportOptions, type FileQueryResponse, type FileReadResponse, type FilesystemEvent, type GetEventsOptions, type GetAdminIngressStatusOptions, type GetAdminSyncStatusOptions, type GetOperationsOptions, type GetSyncDeadLettersOptions, type GetSyncIngressStatusOptions, type GetSyncStatusOptions, type ListTreeOptions, type OperationFeedResponse, type OperationStatusResponse, type QueuedResponse, type QueryFilesOptions, type SyncIngressStatusResponse, type SyncStatusResponse, type TreeResponse, type WriteFileInput, type WriteQueuedResponse } from "./types.js";
1
+ import { type AdminIngressStatusResponse, type AdminSyncStatusResponse, type BulkWriteInput, type BulkWriteResponse, type BackendStatusResponse, type AckResponse, type DeleteFileInput, type DeadLetterItem, type DeadLetterFeedResponse, type EventFeedResponse, type ExportJsonResponse, type ExportOptions, type FileQueryResponse, type FileReadResponse, type FilesystemEvent, type GetEventsOptions, type GetAdminIngressStatusOptions, type GetAdminSyncStatusOptions, type GetOperationsOptions, type GetSyncDeadLettersOptions, type GetSyncIngressStatusOptions, type GetSyncStatusOptions, type ListTreeOptions, type OperationFeedResponse, type OperationStatusResponse, type QueuedResponse, type QueryFilesOptions, type SyncIngressStatusResponse, type SyncStatusResponse, type TreeResponse, type WriteFileInput, type WriteQueuedResponse, type IngestWebhookInput, type WritebackItem, type AckWritebackInput, type AckWritebackResponse } from "./types.js";
2
2
  export type AccessTokenProvider = string | (() => string | Promise<string>);
3
3
  export interface RelayFileRetryOptions {
4
4
  maxRetries?: number;
@@ -59,6 +59,9 @@ export declare class RelayFileClient {
59
59
  replaySyncDeadLetter(workspaceId: string, envelopeId: string, correlationId?: string, signal?: AbortSignal): Promise<QueuedResponse>;
60
60
  ackSyncDeadLetter(workspaceId: string, envelopeId: string, correlationId?: string, signal?: AbortSignal): Promise<AckResponse>;
61
61
  triggerSyncRefresh(workspaceId: string, provider: string, reason?: string, correlationId?: string, signal?: AbortSignal): Promise<QueuedResponse>;
62
+ ingestWebhook(input: IngestWebhookInput): Promise<QueuedResponse>;
63
+ listPendingWritebacks(workspaceId: string, correlationId?: string, signal?: AbortSignal): Promise<WritebackItem[]>;
64
+ ackWriteback(input: AckWritebackInput): Promise<AckWritebackResponse>;
62
65
  private request;
63
66
  private performRequest;
64
67
  private shouldRetryStatus;
@@ -70,4 +73,3 @@ export declare class RelayFileClient {
70
73
  private throwForError;
71
74
  }
72
75
  export {};
73
- //# sourceMappingURL=client.d.ts.map
package/dist/client.js CHANGED
@@ -57,6 +57,15 @@ function createBlobFromResponse(response) {
57
57
  }
58
58
  return response.arrayBuffer().then((buffer) => new Blob([buffer], { type: response.headers.get("content-type") ?? undefined }));
59
59
  }
60
+ function normalizeExportJsonResponse(payload) {
61
+ if (Array.isArray(payload)) {
62
+ return { files: payload };
63
+ }
64
+ const data = (payload ?? {});
65
+ return {
66
+ files: Array.isArray(data.files) ? data.files : []
67
+ };
68
+ }
60
69
  class RelayFileWebSocketConnection {
61
70
  socket;
62
71
  handlers = {
@@ -92,7 +101,14 @@ class RelayFileWebSocketConnection {
92
101
  }
93
102
  let parsed;
94
103
  try {
95
- parsed = JSON.parse(event.data);
104
+ const raw = JSON.parse(event.data);
105
+ if (typeof raw !== "object" || raw === null || typeof raw.type !== "string") {
106
+ throw new Error("Invalid WebSocket event: missing required 'type' field.");
107
+ }
108
+ if (raw.path !== undefined && typeof raw.path !== "string") {
109
+ throw new Error("Invalid WebSocket event: 'path' must be a string.");
110
+ }
111
+ parsed = raw;
96
112
  }
97
113
  catch (error) {
98
114
  const parseError = error instanceof Error ? error : new Error("Failed to parse WebSocket event payload.");
@@ -202,7 +218,7 @@ export class RelayFileClient {
202
218
  });
203
219
  }
204
220
  async bulkWrite(input) {
205
- return this.request({
221
+ const response = await this.performRequest({
206
222
  method: "POST",
207
223
  path: `/v1/workspaces/${encodeURIComponent(input.workspaceId)}/fs/bulk`,
208
224
  correlationId: input.correlationId,
@@ -211,6 +227,7 @@ export class RelayFileClient {
211
227
  },
212
228
  signal: input.signal
213
229
  });
230
+ return this.readPayload(response);
214
231
  }
215
232
  async deleteFile(input) {
216
233
  const query = buildQuery({ path: input.path });
@@ -249,7 +266,7 @@ export class RelayFileClient {
249
266
  accept: format === "json" ? "application/json" : "*/*"
250
267
  });
251
268
  if (format === "json") {
252
- return this.readPayload(response);
269
+ return normalizeExportJsonResponse(await this.readPayload(response));
253
270
  }
254
271
  return createBlobFromResponse(response);
255
272
  }
@@ -436,9 +453,47 @@ export class RelayFileClient {
436
453
  signal
437
454
  });
438
455
  }
456
+ async ingestWebhook(input) {
457
+ return this.request({
458
+ method: "POST",
459
+ path: `/v1/workspaces/${encodeURIComponent(input.workspaceId)}/webhooks/ingest`,
460
+ correlationId: input.correlationId,
461
+ body: {
462
+ provider: input.provider,
463
+ event_type: input.event_type,
464
+ path: input.path,
465
+ data: input.data,
466
+ delivery_id: input.delivery_id,
467
+ timestamp: input.timestamp,
468
+ headers: input.headers
469
+ },
470
+ signal: input.signal
471
+ });
472
+ }
473
+ async listPendingWritebacks(workspaceId, correlationId, signal) {
474
+ return this.request({
475
+ method: "GET",
476
+ path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/writeback/pending`,
477
+ correlationId,
478
+ signal
479
+ });
480
+ }
481
+ async ackWriteback(input) {
482
+ return this.request({
483
+ method: "POST",
484
+ path: `/v1/workspaces/${encodeURIComponent(input.workspaceId)}/writeback/${encodeURIComponent(input.itemId)}/ack`,
485
+ correlationId: input.correlationId,
486
+ body: {
487
+ success: input.success,
488
+ error: input.error
489
+ },
490
+ signal: input.signal
491
+ });
492
+ }
439
493
  async request(params) {
440
494
  const response = await this.performRequest(params);
441
- return this.readPayload(response);
495
+ const payload = await this.readPayload(response);
496
+ return payload;
442
497
  }
443
498
  async performRequest(params) {
444
499
  const correlationId = params.correlationId ?? generateCorrelationId();
@@ -628,4 +683,3 @@ export class RelayFileClient {
628
683
  });
629
684
  }
630
685
  }
631
- //# sourceMappingURL=client.js.map
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Composio integration bridge for Relayfile.
3
+ *
4
+ * Maps Composio trigger webhook events → Relayfile filesystem paths + semantics.
5
+ *
6
+ * Composio webhook payload format (V3):
7
+ * {
8
+ * "type": "composio.trigger.message",
9
+ * "metadata": {
10
+ * "trigger_slug": "GITHUB_COMMIT_EVENT",
11
+ * "trigger_id": "trig_abc123",
12
+ * "connected_account_id": "ca_xyz789",
13
+ * "user_id": "user_123",
14
+ * "toolkit": "github"
15
+ * },
16
+ * "data": {
17
+ * // trigger-specific payload (e.g., commit author, message, url)
18
+ * }
19
+ * }
20
+ *
21
+ * @see https://docs.composio.dev/docs/triggers
22
+ * @see https://docs.composio.dev/docs/setting-up-triggers/subscribing-to-events
23
+ */
24
+ import type { QueuedResponse } from "./types.js";
25
+ import { IntegrationProvider, type WebhookInput } from "./provider.js";
26
+ /** Raw webhook payload from Composio (V3 format) */
27
+ export interface ComposioWebhookPayload {
28
+ type: "composio.trigger.message" | "composio.connected_account.expired";
29
+ metadata: {
30
+ trigger_slug: string;
31
+ trigger_id: string;
32
+ connected_account_id: string;
33
+ user_id?: string;
34
+ toolkit: string;
35
+ };
36
+ data: Record<string, unknown>;
37
+ }
38
+ /** Options for creating Composio trigger subscriptions */
39
+ export interface ComposioTriggerOptions {
40
+ /** Composio API key */
41
+ apiKey: string;
42
+ /** Webhook URL to receive events */
43
+ webhookUrl: string;
44
+ /** Base URL for Composio API (default: https://backend.composio.dev) */
45
+ baseUrl?: string;
46
+ }
47
+ export declare class ComposioHelpers extends IntegrationProvider {
48
+ readonly name = "composio";
49
+ /**
50
+ * Ingest a Composio webhook payload into Relayfile.
51
+ *
52
+ * @param workspaceId - Relayfile workspace ID
53
+ * @param rawInput - Raw Composio webhook payload (ComposioWebhookPayload)
54
+ * @param signal - Optional abort signal
55
+ */
56
+ ingestWebhook(workspaceId: string, rawInput: unknown, signal?: AbortSignal): Promise<QueuedResponse>;
57
+ /**
58
+ * Normalize a Composio webhook payload to the generic WebhookInput format.
59
+ * Useful for custom processing pipelines.
60
+ */
61
+ normalize(input: ComposioWebhookPayload): WebhookInput;
62
+ private buildSemanticProperties;
63
+ }
@@ -0,0 +1,233 @@
1
+ /**
2
+ * Composio integration bridge for Relayfile.
3
+ *
4
+ * Maps Composio trigger webhook events → Relayfile filesystem paths + semantics.
5
+ *
6
+ * Composio webhook payload format (V3):
7
+ * {
8
+ * "type": "composio.trigger.message",
9
+ * "metadata": {
10
+ * "trigger_slug": "GITHUB_COMMIT_EVENT",
11
+ * "trigger_id": "trig_abc123",
12
+ * "connected_account_id": "ca_xyz789",
13
+ * "user_id": "user_123",
14
+ * "toolkit": "github"
15
+ * },
16
+ * "data": {
17
+ * // trigger-specific payload (e.g., commit author, message, url)
18
+ * }
19
+ * }
20
+ *
21
+ * @see https://docs.composio.dev/docs/triggers
22
+ * @see https://docs.composio.dev/docs/setting-up-triggers/subscribing-to-events
23
+ */
24
+ import { IntegrationProvider, computeCanonicalPath, } from "./provider.js";
25
+ // ---------------------------------------------------------------------------
26
+ // Trigger slug → Relayfile object type mapping
27
+ // ---------------------------------------------------------------------------
28
+ /**
29
+ * Maps Composio trigger slugs to Relayfile object types.
30
+ * The trigger slug format is usually: {TOOLKIT}_{EVENT_NAME}
31
+ * e.g., GITHUB_COMMIT_EVENT → "commits", SLACK_NEW_MESSAGE → "messages"
32
+ */
33
+ const TRIGGER_OBJECT_TYPE = {
34
+ // GitHub
35
+ GITHUB_COMMIT_EVENT: "commits",
36
+ GITHUB_PULL_REQUEST_EVENT: "pull_requests",
37
+ GITHUB_ISSUE_EVENT: "issues",
38
+ GITHUB_STAR_EVENT: "stars",
39
+ GITHUB_PUSH_EVENT: "pushes",
40
+ // Slack
41
+ SLACK_NEW_MESSAGE: "messages",
42
+ SLACK_CHANNEL_CREATED: "channels",
43
+ SLACK_REACTION_ADDED: "reactions",
44
+ // Gmail
45
+ GMAIL_NEW_EMAIL: "emails",
46
+ // Zendesk
47
+ ZENDESK_NEW_TICKET: "tickets",
48
+ ZENDESK_TICKET_UPDATED: "tickets",
49
+ // Shopify
50
+ SHOPIFY_NEW_ORDER: "orders",
51
+ SHOPIFY_ORDER_UPDATED: "orders",
52
+ // Stripe
53
+ STRIPE_PAYMENT_RECEIVED: "payments",
54
+ STRIPE_INVOICE_CREATED: "invoices",
55
+ // Jira
56
+ JIRA_ISSUE_CREATED: "issues",
57
+ JIRA_ISSUE_UPDATED: "issues",
58
+ // HubSpot
59
+ HUBSPOT_CONTACT_CREATED: "contacts",
60
+ HUBSPOT_DEAL_CREATED: "deals",
61
+ // Notion
62
+ NOTION_PAGE_UPDATED: "pages",
63
+ // Linear
64
+ LINEAR_ISSUE_CREATED: "issues",
65
+ LINEAR_ISSUE_UPDATED: "issues",
66
+ // Intercom
67
+ INTERCOM_NEW_CONVERSATION: "conversations",
68
+ // Freshdesk
69
+ FRESHDESK_TICKET_CREATED: "tickets",
70
+ FRESHDESK_TICKET_UPDATED: "tickets",
71
+ };
72
+ /**
73
+ * Extract event type (created/updated/deleted) from trigger slug.
74
+ */
75
+ function extractEventType(triggerSlug) {
76
+ const slug = triggerSlug.toUpperCase();
77
+ if (slug.includes("CREATED") || slug.includes("NEW"))
78
+ return "created";
79
+ if (slug.includes("UPDATED") || slug.includes("CHANGED"))
80
+ return "updated";
81
+ if (slug.includes("DELETED") || slug.includes("REMOVED"))
82
+ return "deleted";
83
+ return "event";
84
+ }
85
+ /**
86
+ * Extract a stable object ID from Composio event data.
87
+ * Different triggers have different ID fields.
88
+ */
89
+ function extractObjectId(data) {
90
+ // Common ID fields across various providers
91
+ const idFields = ["id", "objectId", "object_id", "ticketId", "issueId", "messageId", "orderId", "commitId"];
92
+ for (const field of idFields) {
93
+ const val = data[field];
94
+ if (typeof val === "string" || typeof val === "number") {
95
+ return String(val);
96
+ }
97
+ }
98
+ // Nested ID patterns
99
+ if (typeof data.issue === "object" && data.issue !== null && "id" in data.issue) {
100
+ return String(data.issue.id);
101
+ }
102
+ if (typeof data.pull_request === "object" && data.pull_request !== null && "id" in data.pull_request) {
103
+ return String(data.pull_request.id);
104
+ }
105
+ // Fallback: hash from trigger_id + timestamp
106
+ return `auto-${Date.now().toString(36)}`;
107
+ }
108
+ /**
109
+ * Infer the object type from trigger slug when not in the mapping table.
110
+ * Format: TOOLKIT_OBJECT_EVENT → "objects" (pluralized)
111
+ */
112
+ function inferObjectType(triggerSlug) {
113
+ // Remove toolkit prefix and event suffix
114
+ const parts = triggerSlug.toLowerCase().split("_");
115
+ if (parts.length >= 3) {
116
+ // e.g., GITHUB_COMMIT_EVENT → "commit" → "commits"
117
+ const objectPart = parts.slice(1, -1).join("_");
118
+ return objectPart.endsWith("s") ? objectPart : `${objectPart}s`;
119
+ }
120
+ return "events";
121
+ }
122
+ // ---------------------------------------------------------------------------
123
+ // Composio provider implementation
124
+ // ---------------------------------------------------------------------------
125
+ export class ComposioHelpers extends IntegrationProvider {
126
+ name = "composio";
127
+ /**
128
+ * Ingest a Composio webhook payload into Relayfile.
129
+ *
130
+ * @param workspaceId - Relayfile workspace ID
131
+ * @param rawInput - Raw Composio webhook payload (ComposioWebhookPayload)
132
+ * @param signal - Optional abort signal
133
+ */
134
+ async ingestWebhook(workspaceId, rawInput, signal) {
135
+ const input = rawInput;
136
+ if (input.type === "composio.connected_account.expired") {
137
+ // Handle account expiry as a system event
138
+ return this.client.ingestWebhook({
139
+ workspaceId,
140
+ provider: input.metadata.toolkit || "composio",
141
+ event_type: "account_expired",
142
+ path: `/.system/composio/expired/${input.metadata.connected_account_id}.json`,
143
+ data: {
144
+ connected_account_id: input.metadata.connected_account_id,
145
+ user_id: input.metadata.user_id,
146
+ toolkit: input.metadata.toolkit,
147
+ expired_at: new Date().toISOString(),
148
+ },
149
+ headers: {},
150
+ signal,
151
+ });
152
+ }
153
+ const toolkit = input.metadata.toolkit;
154
+ const triggerSlug = input.metadata.trigger_slug;
155
+ const objectType = TRIGGER_OBJECT_TYPE[triggerSlug] ?? inferObjectType(triggerSlug);
156
+ const objectId = extractObjectId(input.data);
157
+ const eventType = extractEventType(triggerSlug);
158
+ const path = computeCanonicalPath(toolkit, objectType, objectId);
159
+ const properties = this.buildSemanticProperties(input);
160
+ const semantics = {
161
+ properties,
162
+ relations: [],
163
+ };
164
+ return this.client.ingestWebhook({
165
+ workspaceId,
166
+ provider: toolkit,
167
+ event_type: eventType,
168
+ path,
169
+ data: {
170
+ ...input.data,
171
+ semantics,
172
+ },
173
+ headers: {
174
+ "X-Composio-Trigger-Id": input.metadata.trigger_id,
175
+ "X-Composio-Trigger-Slug": triggerSlug,
176
+ "X-Composio-Connected-Account": input.metadata.connected_account_id,
177
+ ...(input.metadata.user_id
178
+ ? { "X-Composio-User-Id": input.metadata.user_id }
179
+ : {}),
180
+ },
181
+ signal,
182
+ });
183
+ }
184
+ /**
185
+ * Normalize a Composio webhook payload to the generic WebhookInput format.
186
+ * Useful for custom processing pipelines.
187
+ */
188
+ normalize(input) {
189
+ const toolkit = input.metadata.toolkit;
190
+ const triggerSlug = input.metadata.trigger_slug;
191
+ return {
192
+ provider: toolkit,
193
+ objectType: TRIGGER_OBJECT_TYPE[triggerSlug] ?? inferObjectType(triggerSlug),
194
+ objectId: extractObjectId(input.data),
195
+ eventType: extractEventType(triggerSlug),
196
+ payload: input.data,
197
+ metadata: {
198
+ "composio.trigger_id": input.metadata.trigger_id,
199
+ "composio.trigger_slug": triggerSlug,
200
+ "composio.connected_account_id": input.metadata.connected_account_id,
201
+ ...(input.metadata.user_id
202
+ ? { "composio.user_id": input.metadata.user_id }
203
+ : {}),
204
+ },
205
+ };
206
+ }
207
+ buildSemanticProperties(input) {
208
+ const properties = {
209
+ "composio.trigger_id": input.metadata.trigger_id,
210
+ "composio.trigger_slug": input.metadata.trigger_slug,
211
+ "composio.connected_account_id": input.metadata.connected_account_id,
212
+ provider: input.metadata.toolkit,
213
+ "provider.object_type": TRIGGER_OBJECT_TYPE[input.metadata.trigger_slug] ??
214
+ inferObjectType(input.metadata.trigger_slug),
215
+ "provider.object_id": extractObjectId(input.data),
216
+ };
217
+ if (input.metadata.user_id) {
218
+ properties["composio.user_id"] = input.metadata.user_id;
219
+ }
220
+ // Extract common fields from data
221
+ const data = input.data;
222
+ if (typeof data.status === "string") {
223
+ properties["provider.status"] = data.status;
224
+ }
225
+ if (typeof data.updated_at === "string") {
226
+ properties["provider.updated_at"] = data.updated_at;
227
+ }
228
+ if (typeof data.created_at === "string") {
229
+ properties["provider.created_at"] = data.created_at;
230
+ }
231
+ return properties;
232
+ }
233
+ }
package/dist/errors.d.ts CHANGED
@@ -22,4 +22,3 @@ export declare class InvalidStateError extends RelayFileApiError {
22
22
  export declare class PayloadTooLargeError extends RelayFileApiError {
23
23
  constructor(status: number, payload?: Partial<ErrorResponse>);
24
24
  }
25
- //# sourceMappingURL=errors.d.ts.map
package/dist/errors.js CHANGED
@@ -44,4 +44,3 @@ export class PayloadTooLargeError extends RelayFileApiError {
44
44
  this.name = "PayloadTooLargeError";
45
45
  }
46
46
  }
47
- //# sourceMappingURL=errors.js.map
package/dist/index.d.ts CHANGED
@@ -1,4 +1,10 @@
1
1
  export { RelayFileClient, type ConnectWebSocketOptions, type RelayFileRetryOptions, type WebSocketConnection } from "./client.js";
2
+ export { RelayFileSync, type RelayFileSyncOptions, type RelayFileSyncPong, type RelayFileSyncReconnectOptions, type RelayFileSyncSocket, type RelayFileSyncState } from "./sync.js";
2
3
  export { InvalidStateError, PayloadTooLargeError, QueueFullError, RelayFileApiError, RevisionConflictError } from "./errors.js";
3
- export type { AckResponse, AdminIngressAlert, AdminIngressAlertProfile, AdminIngressEffectiveAlertProfile, AdminIngressAlertSeverity, AdminIngressAlertThresholds, AdminIngressAlertTotals, AdminIngressAlertType, AdminIngressStatusResponse, AdminSyncAlert, AdminSyncAlertSeverity, AdminSyncAlertThresholds, AdminSyncAlertTotals, AdminSyncAlertType, AdminSyncStatusResponse, BackendStatusResponse, BulkWriteFile, BulkWriteInput, BulkWriteResponse, ConflictErrorResponse, DeleteFileInput, DeadLetterFeedResponse, DeadLetterItem, ErrorResponse, EventFeedResponse, ExportFormat, ExportJsonResponse, ExportOptions, FileQueryItem, FileQueryResponse, FileReadResponse, FileSemantics, FileWriteRequest, FilesystemEvent, GetEventsOptions, GetAdminSyncStatusOptions, GetAdminIngressStatusOptions, GetOperationsOptions, GetSyncDeadLettersOptions, GetSyncIngressStatusOptions, GetSyncStatusOptions, ListTreeOptions, OperationFeedResponse, OperationStatusResponse, QueuedResponse, QueryFilesOptions, SyncIngressStatusResponse, SyncRefreshRequest, SyncStatusResponse, TreeEntry, TreeResponse, WritebackActionType, WriteFileInput, WriteQueuedResponse } from "./types.js";
4
- //# sourceMappingURL=index.d.ts.map
4
+ export { IntegrationProvider, computeCanonicalPath } from "./provider.js";
5
+ export type { WebhookInput, ListProviderFilesOptions, WatchProviderEventsOptions } from "./provider.js";
6
+ export { NangoHelpers } from "./nango.js";
7
+ export type { NangoWebhookInput } from "./nango.js";
8
+ export { ComposioHelpers } from "./composio.js";
9
+ export type { ComposioWebhookPayload, ComposioTriggerOptions } from "./composio.js";
10
+ export type { AckResponse, AckWritebackInput, AckWritebackResponse, AdminIngressAlert, AdminIngressAlertProfile, AdminIngressEffectiveAlertProfile, AdminIngressAlertSeverity, AdminIngressAlertThresholds, AdminIngressAlertTotals, AdminIngressAlertType, AdminIngressStatusResponse, AdminSyncAlert, AdminSyncAlertSeverity, AdminSyncAlertThresholds, AdminSyncAlertTotals, AdminSyncAlertType, AdminSyncStatusResponse, BackendStatusResponse, BulkWriteFile, BulkWriteInput, BulkWriteResponse, ConflictErrorResponse, DeleteFileInput, DeadLetterFeedResponse, DeadLetterItem, ErrorResponse, EventFeedResponse, ExportFormat, ExportJsonResponse, ExportOptions, FileQueryItem, FileQueryResponse, FileReadResponse, FileSemantics, FileWriteRequest, FilesystemEvent, FilesystemEventType, EventOrigin, GetEventsOptions, GetAdminSyncStatusOptions, GetAdminIngressStatusOptions, GetOperationsOptions, GetSyncDeadLettersOptions, GetSyncIngressStatusOptions, GetSyncStatusOptions, IngestWebhookInput, ListTreeOptions, OperationFeedResponse, OperationStatus, OperationStatusResponse, QueuedResponse, QueryFilesOptions, SyncIngressStatusResponse, SyncProviderStatus, SyncProviderStatusState, SyncRefreshRequest, SyncStatusResponse, TreeEntry, TreeResponse, WritebackActionType, WritebackState, WritebackItem, WriteFileInput, WriteQueuedResponse } from "./types.js";
package/dist/index.js CHANGED
@@ -1,3 +1,9 @@
1
1
  export { RelayFileClient } from "./client.js";
2
+ export { RelayFileSync } from "./sync.js";
2
3
  export { InvalidStateError, PayloadTooLargeError, QueueFullError, RelayFileApiError, RevisionConflictError } from "./errors.js";
3
- //# sourceMappingURL=index.js.map
4
+ // Integration providers
5
+ export { IntegrationProvider, computeCanonicalPath } from "./provider.js";
6
+ // Nango bridge
7
+ export { NangoHelpers } from "./nango.js";
8
+ // Composio bridge
9
+ export { ComposioHelpers } from "./composio.js";
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Nango integration bridge for Relayfile.
3
+ *
4
+ * Maps Nango sync webhook events → Relayfile filesystem paths + semantics.
5
+ *
6
+ * @see https://docs.nango.dev/integrate/guides/receive-webhooks-from-nango
7
+ */
8
+ import type { QueuedResponse } from "./types.js";
9
+ import { IntegrationProvider, type WebhookInput } from "./provider.js";
10
+ export interface NangoWebhookInput {
11
+ connectionId: string;
12
+ integrationId: string;
13
+ providerConfigKey?: string;
14
+ model: string;
15
+ objectId: string;
16
+ eventType: string;
17
+ payload: Record<string, unknown>;
18
+ relations?: string[];
19
+ }
20
+ export interface GetProviderFilesOptions {
21
+ provider: string;
22
+ objectType?: string;
23
+ status?: string;
24
+ limit?: number;
25
+ signal?: AbortSignal;
26
+ }
27
+ export interface WatchProviderEventsOptions {
28
+ provider: string;
29
+ pollIntervalMs?: number;
30
+ cursor?: string;
31
+ signal?: AbortSignal;
32
+ }
33
+ export declare class NangoHelpers extends IntegrationProvider {
34
+ readonly name = "nango";
35
+ /**
36
+ * Ingest a Nango webhook event into Relayfile.
37
+ *
38
+ * @param workspaceId - Relayfile workspace ID
39
+ * @param rawInput - NangoWebhookInput
40
+ * @param signal - Optional abort signal
41
+ */
42
+ ingestWebhook(workspaceId: string, rawInput: unknown, signal?: AbortSignal): Promise<QueuedResponse>;
43
+ /**
44
+ * Normalize a Nango webhook input to the generic WebhookInput format.
45
+ */
46
+ normalize(input: NangoWebhookInput): WebhookInput;
47
+ }
package/dist/nango.js ADDED
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Nango integration bridge for Relayfile.
3
+ *
4
+ * Maps Nango sync webhook events → Relayfile filesystem paths + semantics.
5
+ *
6
+ * @see https://docs.nango.dev/integrate/guides/receive-webhooks-from-nango
7
+ */
8
+ import { IntegrationProvider, computeCanonicalPath, } from "./provider.js";
9
+ // ---------------------------------------------------------------------------
10
+ // Nango provider implementation
11
+ // ---------------------------------------------------------------------------
12
+ function buildSemanticProperties(provider, input, payload) {
13
+ const properties = {
14
+ "nango.connection_id": input.connectionId,
15
+ "nango.integration_id": input.integrationId,
16
+ "provider": provider,
17
+ "provider.object_type": input.model,
18
+ "provider.object_id": input.objectId
19
+ };
20
+ if (input.providerConfigKey) {
21
+ properties["nango.provider_config_key"] = input.providerConfigKey;
22
+ }
23
+ if (typeof payload.status === "string") {
24
+ properties["provider.status"] = payload.status;
25
+ }
26
+ if (typeof payload.updated_at === "string") {
27
+ properties["provider.updated_at"] = payload.updated_at;
28
+ }
29
+ if (typeof payload.created_at === "string") {
30
+ properties["provider.created_at"] = payload.created_at;
31
+ }
32
+ return properties;
33
+ }
34
+ export class NangoHelpers extends IntegrationProvider {
35
+ name = "nango";
36
+ /**
37
+ * Ingest a Nango webhook event into Relayfile.
38
+ *
39
+ * @param workspaceId - Relayfile workspace ID
40
+ * @param rawInput - NangoWebhookInput
41
+ * @param signal - Optional abort signal
42
+ */
43
+ async ingestWebhook(workspaceId, rawInput, signal) {
44
+ const input = rawInput;
45
+ const provider = input.integrationId.split("-")[0] ?? input.integrationId;
46
+ const path = computeCanonicalPath(provider, input.model, input.objectId);
47
+ const properties = buildSemanticProperties(provider, input, input.payload);
48
+ return this.client.ingestWebhook({
49
+ workspaceId,
50
+ provider: provider,
51
+ event_type: input.eventType,
52
+ path,
53
+ data: {
54
+ ...input.payload,
55
+ semantics: {
56
+ properties,
57
+ relations: input.relations ?? []
58
+ }
59
+ },
60
+ headers: {
61
+ "X-Nango-Connection-Id": input.connectionId,
62
+ "X-Nango-Integration-Id": input.integrationId,
63
+ ...(input.providerConfigKey
64
+ ? { "X-Nango-Provider-Config-Key": input.providerConfigKey }
65
+ : {})
66
+ },
67
+ signal
68
+ });
69
+ }
70
+ /**
71
+ * Normalize a Nango webhook input to the generic WebhookInput format.
72
+ */
73
+ normalize(input) {
74
+ const provider = input.integrationId.split("-")[0] ?? input.integrationId;
75
+ return {
76
+ provider,
77
+ objectType: input.model,
78
+ objectId: input.objectId,
79
+ eventType: input.eventType,
80
+ payload: input.payload,
81
+ relations: input.relations,
82
+ metadata: {
83
+ "nango.connection_id": input.connectionId,
84
+ "nango.integration_id": input.integrationId,
85
+ ...(input.providerConfigKey
86
+ ? { "nango.provider_config_key": input.providerConfigKey }
87
+ : {}),
88
+ },
89
+ };
90
+ }
91
+ }