@relayfile/sdk 0.10.2 → 0.10.3

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/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type AdminIngressStatusResponse, type AdminSyncStatusResponse, type BulkWriteInput, type BulkWriteResponse, type BackendStatusResponse, type AckResponse, type CommitForkInput, type CommitForkResponse, type CreateForkInput, type DeleteFileInput, type DeadLetterItem, type DeadLetterFeedResponse, type DeleteWebhookOptions, type DiscardForkInput, 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 GetWebhookDeadLettersOptions, type ListWebhooksOptions, type ListTreeOptions, type OperationFeedResponse, type OperationStatusResponse, type QueuedResponse, type ResourceAtEventResult, type ReadFileInput, type QueryFilesOptions, type RegisterWebhookInput, type RegisterWebhookResponse, type RelayFileReadCacheOptions, type Subscription, type SyncIngressStatusResponse, type SyncStatusResponse, type TreeResponse, type WriteFileInput, type WriteQueuedResponse, type IngestWebhookInput, type WritebackItem, type WebhookDeliveryDeadLetterFeedResponse, type WebhookSubscription, type AckWritebackInput, type AckWritebackResponse, type SweepWritebackDraftsInput, type SweepWritebackDraftsResponse, type ChangeEvent, type ChangeLogQueryResult, type ChangeStreamConnection, type ChangeStreamConnectionOptions, type SubscribeOptions } from "./types.js";
1
+ import { type AdminIngressStatusResponse, type AdminSyncStatusResponse, type BulkWriteInput, type BulkWriteResponse, type BackendStatusResponse, type AckResponse, type CommitForkInput, type CommitForkResponse, type CreateForkInput, type DeleteFileInput, type DeadLetterItem, type DeadLetterFeedResponse, type DeleteWebhookOptions, type DiscardForkInput, 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 GetWebhookDeadLettersOptions, type ListWebhooksOptions, type ListTreeOptions, type OperationFeedResponse, type OperationStatusResponse, type QueuedResponse, type ResourceAtEventResult, type ReadFileInput, type QueryFilesOptions, type RegisterWebhookInput, type RegisterWebhookResponse, type RelayFileReadCacheOptions, type Subscription, type SyncIngressStatusResponse, type SyncProviderStatus, type SyncStatusResponse, type TreeResponse, type WriteFileInput, type WriteQueuedResponse, type IngestWebhookInput, type WritebackItem, type WebhookDeliveryDeadLetterFeedResponse, type WebhookSubscription, type AckWritebackInput, type AckWritebackResponse, type SweepWritebackDraftsInput, type SweepWritebackDraftsResponse, type ChangeEvent, type ChangeLogQueryResult, type ChangeStreamConnection, type ChangeStreamConnectionOptions, type SubscribeOptions, type WaitForDataOptions } from "./types.js";
2
2
  import type { ForkHandle } from "@relayfile/core";
3
3
  /**
4
4
  * Bearer token or token factory used for Relayfile API requests.
@@ -124,6 +124,18 @@ export declare class RelayFileClient {
124
124
  getAdminIngressStatus(optionsOrCorrelationId?: GetAdminIngressStatusOptions | string, signal?: AbortSignal): Promise<AdminIngressStatusResponse>;
125
125
  getAdminSyncStatus(optionsOrCorrelationId?: GetAdminSyncStatusOptions | string, signal?: AbortSignal): Promise<AdminSyncStatusResponse>;
126
126
  getSyncStatus(workspaceId: string, options?: GetSyncStatusOptions): Promise<SyncStatusResponse>;
127
+ /**
128
+ * Wait until a provider is safe to read from the data plane.
129
+ *
130
+ * Cloud-managed syncs report first-sync completion through `ready: true` or
131
+ * `status: "ready"`. OSS self-host `/sync/status` uses `healthy` for provider
132
+ * health, including empty freshly filtered provider rows, so this method only
133
+ * treats OSS `healthy` as data-ready after processed-ingest progress appears
134
+ * on the status row (`cursor` or `watermarkTs`). For custom OSS ingest flows,
135
+ * gate on your own ingest completion when you need stronger domain-specific
136
+ * proof than provider progress.
137
+ */
138
+ waitForData(workspaceId: string, provider: string, options?: WaitForDataOptions): Promise<SyncProviderStatus>;
127
139
  getSyncIngressStatus(workspaceId: string, options?: GetSyncIngressStatusOptions): Promise<SyncIngressStatusResponse>;
128
140
  getSyncDeadLetters(workspaceId: string, options?: GetSyncDeadLettersOptions): Promise<DeadLetterFeedResponse>;
129
141
  getSyncDeadLetter(workspaceId: string, envelopeId: string, correlationId?: string, signal?: AbortSignal): Promise<DeadLetterItem>;
package/dist/client.js CHANGED
@@ -186,6 +186,32 @@ function normalizeErrorDetails(data, explicitDetails) {
186
186
  }
187
187
  return Object.keys(details).length > 0 ? details : undefined;
188
188
  }
189
+ function normalizeProviderId(value) {
190
+ const normalized = value.trim().toLowerCase();
191
+ if (!normalized) {
192
+ throw new Error("provider is required.");
193
+ }
194
+ return normalized;
195
+ }
196
+ function normalizeProviderIdOrNull(value) {
197
+ const normalized = value.trim().toLowerCase();
198
+ return normalized || null;
199
+ }
200
+ function normalizePositiveInteger(value, field) {
201
+ const normalized = Math.floor(value);
202
+ if (!Number.isFinite(normalized) || normalized <= 0) {
203
+ throw new Error(`${field} must be a positive integer.`);
204
+ }
205
+ return normalized;
206
+ }
207
+ function providerDataReady(status) {
208
+ return (status.ready === true ||
209
+ status.status === "ready" ||
210
+ (status.status === "healthy" && providerHasProgress(status)));
211
+ }
212
+ function providerHasProgress(status) {
213
+ return Boolean(status.cursor || status.watermarkTs);
214
+ }
189
215
  class RelayFileWebSocketConnection {
190
216
  socket;
191
217
  handlers = {
@@ -1585,6 +1611,44 @@ export class RelayFileClient {
1585
1611
  signal: options.signal
1586
1612
  });
1587
1613
  }
1614
+ /**
1615
+ * Wait until a provider is safe to read from the data plane.
1616
+ *
1617
+ * Cloud-managed syncs report first-sync completion through `ready: true` or
1618
+ * `status: "ready"`. OSS self-host `/sync/status` uses `healthy` for provider
1619
+ * health, including empty freshly filtered provider rows, so this method only
1620
+ * treats OSS `healthy` as data-ready after processed-ingest progress appears
1621
+ * on the status row (`cursor` or `watermarkTs`). For custom OSS ingest flows,
1622
+ * gate on your own ingest completion when you need stronger domain-specific
1623
+ * proof than provider progress.
1624
+ */
1625
+ async waitForData(workspaceId, provider, options = {}) {
1626
+ const providerKey = normalizeProviderId(provider);
1627
+ const pollIntervalMs = normalizePositiveInteger(options.pollIntervalMs ?? 1_000, "pollIntervalMs");
1628
+ const timeoutMs = normalizePositiveInteger(options.timeoutMs ?? 5 * 60_000, "timeoutMs");
1629
+ const startedAt = Date.now();
1630
+ for (;;) {
1631
+ if (options.signal?.aborted) {
1632
+ throw createAbortError();
1633
+ }
1634
+ const elapsedMs = Date.now() - startedAt;
1635
+ if (elapsedMs >= timeoutMs) {
1636
+ throw new Error(`Timed out waiting for ${providerKey} data after ${elapsedMs}ms.`);
1637
+ }
1638
+ const status = await this.getSyncStatus(workspaceId, {
1639
+ provider: providerKey,
1640
+ correlationId: options.correlationId,
1641
+ signal: options.signal
1642
+ });
1643
+ const providerStatus = status.providers.find((entry) => normalizeProviderIdOrNull(entry.provider) === providerKey);
1644
+ options.onPoll?.(elapsedMs, providerStatus);
1645
+ if (providerStatus && providerDataReady(providerStatus)) {
1646
+ return providerStatus;
1647
+ }
1648
+ const remainingMs = Math.max(0, timeoutMs - (Date.now() - startedAt));
1649
+ await this.sleep(Math.min(pollIntervalMs, remainingMs), options.signal);
1650
+ }
1651
+ }
1588
1652
  async getSyncIngressStatus(workspaceId, options = {}) {
1589
1653
  const query = buildQuery({
1590
1654
  provider: options.provider
@@ -41,3 +41,39 @@ export interface ConnectionProvider {
41
41
  getConnection?(connectionId: string): Promise<Record<string, unknown>>;
42
42
  listConnections?(): Promise<Array<Record<string, unknown>>>;
43
43
  }
44
+ /**
45
+ * Maps a relayfile provider slug (e.g. "github", "linear") to the provider
46
+ * config key it is registered under in your credential backend (e.g. the Nango
47
+ * `providerConfigKey`). The relayfile slug is NOT guaranteed to equal the
48
+ * upstream config key, so self-host callers supply this mapping explicitly.
49
+ */
50
+ export type ProviderConfigKeyMap = Record<string, string>;
51
+ export interface CreateConnectSessionInput {
52
+ relayfileProvider: string;
53
+ providerConfigKey: string;
54
+ endUserId: string;
55
+ connectionId?: string;
56
+ metadata?: Record<string, unknown>;
57
+ }
58
+ export interface ConnectSession {
59
+ connectLink: string | null;
60
+ sessionToken: string | null;
61
+ expiresAt: string | null;
62
+ connectionId: string;
63
+ }
64
+ export interface GetConnectConnectionStatusInput {
65
+ relayfileProvider: string;
66
+ providerConfigKey: string;
67
+ connectionId: string;
68
+ }
69
+ export interface ConnectConnectionStatus {
70
+ connectionId: string;
71
+ state: string;
72
+ ready?: boolean;
73
+ raw?: unknown;
74
+ }
75
+ export interface ConnectCapableProvider extends ConnectionProvider {
76
+ createConnectSession(input: CreateConnectSessionInput): Promise<ConnectSession>;
77
+ getConnectionStatus(input: GetConnectConnectionStatusInput): Promise<ConnectConnectionStatus>;
78
+ }
79
+ export declare function supportsConnect(provider: ConnectionProvider): provider is ConnectCapableProvider;
@@ -3,4 +3,8 @@
3
3
  *
4
4
  * These types are the contract every provider package must implement.
5
5
  */
6
- export {};
6
+ export function supportsConnect(provider) {
7
+ const candidate = provider;
8
+ return (typeof candidate.createConnectSession === "function" &&
9
+ typeof candidate.getConnectionStatus === "function");
10
+ }
package/dist/index.d.ts CHANGED
@@ -9,8 +9,11 @@ export { onWrite, pathMatches, type OnWriteClient, type OnWriteHandler, type OnW
9
9
  export { InvalidStateError, PayloadTooLargeError, QueueFullError, RelayFileApiError, RevisionConflictError } from "./errors.js";
10
10
  export { IntegrationProvider, computeCanonicalPath } from "./provider.js";
11
11
  export type { WebhookInput, ListProviderFilesOptions, WatchProviderEventsOptions } from "./provider.js";
12
- export type { ConnectionProvider, NormalizedWebhook, ProxyHeaders, ProxyMethod, ProxyQuery, ProxyRequest, ProxyResponse, } from "./connection.js";
13
- export type { AckResponse, AckWritebackInput, AckWritebackDraftDisposition, AckWritebackResponse, AdminIngressAlert, AdminIngressAlertProfile, AdminIngressEffectiveAlertProfile, AdminIngressAlertSeverity, AdminIngressAlertThresholds, AdminIngressAlertTotals, AdminIngressAlertType, AdminIngressStatusResponse, AdminSyncAlert, AdminSyncAlertSeverity, AdminSyncAlertThresholds, AdminSyncAlertTotals, AdminSyncAlertType, AdminSyncStatusResponse, BackendStatusResponse, BulkWriteFile, BulkWriteInput, BulkWriteResponse, ChangeLogQueryResult, ChangeEvent, ChangeEventActor, ChangeEventResource, ChangeEventSummary, ChangeStreamConnection, ChangeStreamConnectionOptions, CommitForkInput, CommitForkResponse, ConflictErrorResponse, CreateForkInput, ContentIdentity, DeleteFileInput, DeleteWebhookOptions, DeadLetterFeedResponse, DeadLetterItem, DigestBullet, DigestContext, DigestHandler, DigestSection, DigestWindow, DiscardForkInput, ErrorResponse, EventSummary, EventFeedResponse, ExportFormat, ExportJsonResponse, ExportOptions, FileQueryItem, FileQueryResponse, FileReadResponse, FileSemantics, FileWriteRequest, FilesystemEvent, FilesystemEventType, EventOrigin, Expansion, ExpansionLevel, GetEventsOptions, GetAdminSyncStatusOptions, GetAdminIngressStatusOptions, GetOperationsOptions, GetSyncDeadLettersOptions, GetSyncIngressStatusOptions, GetSyncStatusOptions, GetWebhookDeadLettersOptions, IngestWebhookInput, LayoutManifest, LayoutManifestAlias, LayoutManifestResource, ListWebhooksOptions, ListTreeOptions, OperationFeedResponse, OperationStatus, OperationStatusResponse, QueuedResponse, QueryFilesOptions, ReadFileInput, RegisterWebhookInput, RegisterWebhookResponse, ReplayOptions, ResourceAtEventResult, SummaryExpansion, FullExpansion, DiffExpansion, ThreadExpansion, RelayFileJwtClaims, SubscribeOptions, Subscription, SyncIngressStatusResponse, SyncProviderStatus, SyncProviderStatusState, SyncRefreshRequest, SyncStatusResponse, SweepWritebackDraftsInput, SweepWritebackDraftsResponse, TreeEntry, TreeResponse, WebhookDeliveryDeadLetterFeedResponse, WebhookDeliveryDeadLetterItem, WebhookSubscription, WebhookSubscriptionHealth, WritebackActionType, WritebackDeadLetterError, WritebackDeadLetterErrorCode, WritebackListState, WritebackState, WritebackItem, WritebackItemDetail, WritebackSchemaRef, WriteFileInput, WriteQueuedResponse } from "./types.js";
12
+ export type { ConnectCapableProvider, ConnectConnectionStatus, ConnectSession, ConnectionProvider, CreateConnectSessionInput, GetConnectConnectionStatusInput, NormalizedWebhook, ProviderConfigKeyMap, ProxyHeaders, ProxyMethod, ProxyQuery, ProxyRequest, ProxyResponse, } from "./connection.js";
13
+ export { supportsConnect } from "./connection.js";
14
+ export { SelfHostConnect } from "./self-host-connect.js";
15
+ export type { SelfHostConnectOptions, SelfHostConnectResult, StartSelfHostConnectOptions, WaitForSelfHostConnectionOptions } from "./self-host-connect.js";
16
+ export type { AckResponse, AckWritebackInput, AckWritebackDraftDisposition, AckWritebackResponse, AdminIngressAlert, AdminIngressAlertProfile, AdminIngressEffectiveAlertProfile, AdminIngressAlertSeverity, AdminIngressAlertThresholds, AdminIngressAlertTotals, AdminIngressAlertType, AdminIngressStatusResponse, AdminSyncAlert, AdminSyncAlertSeverity, AdminSyncAlertThresholds, AdminSyncAlertTotals, AdminSyncAlertType, AdminSyncStatusResponse, BackendStatusResponse, BulkWriteFile, BulkWriteInput, BulkWriteResponse, ChangeLogQueryResult, ChangeEvent, ChangeEventActor, ChangeEventResource, ChangeEventSummary, ChangeStreamConnection, ChangeStreamConnectionOptions, CommitForkInput, CommitForkResponse, ConflictErrorResponse, CreateForkInput, ContentIdentity, DeleteFileInput, DeleteWebhookOptions, DeadLetterFeedResponse, DeadLetterItem, DigestBullet, DigestContext, DigestHandler, DigestSection, DigestWindow, DiscardForkInput, ErrorResponse, EventSummary, EventFeedResponse, ExportFormat, ExportJsonResponse, ExportOptions, FileQueryItem, FileQueryResponse, FileReadResponse, FileSemantics, FileWriteRequest, FilesystemEvent, FilesystemEventType, EventOrigin, Expansion, ExpansionLevel, GetEventsOptions, GetAdminSyncStatusOptions, GetAdminIngressStatusOptions, GetOperationsOptions, GetSyncDeadLettersOptions, GetSyncIngressStatusOptions, GetSyncStatusOptions, WaitForDataOptions, GetWebhookDeadLettersOptions, IngestWebhookInput, LayoutManifest, LayoutManifestAlias, LayoutManifestResource, ListWebhooksOptions, ListTreeOptions, OperationFeedResponse, OperationStatus, OperationStatusResponse, QueuedResponse, QueryFilesOptions, ReadFileInput, RegisterWebhookInput, RegisterWebhookResponse, ReplayOptions, ResourceAtEventResult, SummaryExpansion, FullExpansion, DiffExpansion, ThreadExpansion, RelayFileJwtClaims, SubscribeOptions, Subscription, SyncIngressStatusResponse, SyncProviderStatus, SyncProviderStatusState, SyncRefreshRequest, SyncStatusResponse, SweepWritebackDraftsInput, SweepWritebackDraftsResponse, TreeEntry, TreeResponse, WebhookDeliveryDeadLetterFeedResponse, WebhookDeliveryDeadLetterItem, WebhookSubscription, WebhookSubscriptionHealth, WritebackActionType, WritebackDeadLetterError, WritebackDeadLetterErrorCode, WritebackListState, WritebackState, WritebackItem, WritebackItemDetail, WritebackSchemaRef, WriteFileInput, WriteQueuedResponse } from "./types.js";
14
17
  export type { ForkHandle, ForkOptions } from "@relayfile/core";
15
18
  export type { WriteEvent, WriteEventActor, WriteEventOperation, WriteEventSource } from "@relayfile/core";
16
19
  export { WritebackConsumer } from "./writeback-consumer.js";
package/dist/index.js CHANGED
@@ -7,6 +7,8 @@ export { onWrite, pathMatches } from "./onWrite.js";
7
7
  export { InvalidStateError, PayloadTooLargeError, QueueFullError, RelayFileApiError, RevisionConflictError } from "./errors.js";
8
8
  // Integration providers
9
9
  export { IntegrationProvider, computeCanonicalPath } from "./provider.js";
10
+ export { supportsConnect } from "./connection.js";
11
+ export { SelfHostConnect } from "./self-host-connect.js";
10
12
  export { WritebackConsumer } from "./writeback-consumer.js";
11
13
  export * from "./integration-adapter.js";
12
14
  // Agent workspace provisioning helpers (`seedWorkspace`, `seedAclRules`,
@@ -0,0 +1,38 @@
1
+ import type { ConnectConnectionStatus, ConnectionProvider, ProviderConfigKeyMap } from "./connection.js";
2
+ export interface SelfHostConnectOptions {
3
+ provider: ConnectionProvider;
4
+ providerConfigKeys: ProviderConfigKeyMap;
5
+ defaultPollIntervalMs?: number;
6
+ defaultTimeoutMs?: number;
7
+ }
8
+ export interface StartSelfHostConnectOptions {
9
+ endUserId: string;
10
+ connectionId?: string;
11
+ metadata?: Record<string, unknown>;
12
+ }
13
+ export interface SelfHostConnectResult {
14
+ relayfileProvider: string;
15
+ providerConfigKey: string;
16
+ connectLink: string | null;
17
+ sessionToken: string | null;
18
+ expiresAt: string | null;
19
+ connectionId: string;
20
+ }
21
+ export interface WaitForSelfHostConnectionOptions {
22
+ connectionId: string;
23
+ pollIntervalMs?: number;
24
+ timeoutMs?: number;
25
+ signal?: AbortSignal;
26
+ onPoll?: (elapsedMs: number, status?: ConnectConnectionStatus) => void;
27
+ }
28
+ export declare class SelfHostConnect {
29
+ private readonly provider;
30
+ private readonly providerConfigKeys;
31
+ private readonly defaultPollIntervalMs;
32
+ private readonly defaultTimeoutMs;
33
+ constructor(options: SelfHostConnectOptions);
34
+ startConnect(relayfileProvider: string, options: StartSelfHostConnectOptions): Promise<SelfHostConnectResult>;
35
+ waitForConnection(relayfileProvider: string, options: WaitForSelfHostConnectionOptions): Promise<ConnectConnectionStatus>;
36
+ private resolveProviderConfigKey;
37
+ private requireConnectProvider;
38
+ }
@@ -0,0 +1,141 @@
1
+ import { supportsConnect } from "./connection.js";
2
+ const DEFAULT_WAIT_INTERVAL_MS = 2_000;
3
+ const DEFAULT_WAIT_TIMEOUT_MS = 5 * 60_000;
4
+ const AUTH_READY_STATE = "oauth_connected";
5
+ export class SelfHostConnect {
6
+ provider;
7
+ providerConfigKeys;
8
+ defaultPollIntervalMs;
9
+ defaultTimeoutMs;
10
+ constructor(options) {
11
+ this.provider = options.provider;
12
+ this.providerConfigKeys = { ...options.providerConfigKeys };
13
+ this.defaultPollIntervalMs = normalizePositiveInteger(options.defaultPollIntervalMs, DEFAULT_WAIT_INTERVAL_MS);
14
+ this.defaultTimeoutMs = normalizePositiveInteger(options.defaultTimeoutMs, DEFAULT_WAIT_TIMEOUT_MS);
15
+ }
16
+ async startConnect(relayfileProvider, options) {
17
+ const normalizedProvider = normalizeRelayfileProvider(relayfileProvider);
18
+ const providerConfigKey = this.resolveProviderConfigKey(normalizedProvider);
19
+ const connectProvider = this.requireConnectProvider();
20
+ const endUserId = options.endUserId?.trim();
21
+ if (!endUserId) {
22
+ throw new Error("endUserId is required to start a self-host connect session");
23
+ }
24
+ const input = {
25
+ relayfileProvider: normalizedProvider,
26
+ providerConfigKey,
27
+ endUserId
28
+ };
29
+ const connectionId = options.connectionId?.trim();
30
+ if (connectionId) {
31
+ input.connectionId = connectionId;
32
+ }
33
+ if (options.metadata) {
34
+ input.metadata = { ...options.metadata };
35
+ }
36
+ const session = await connectProvider.createConnectSession(input);
37
+ return {
38
+ relayfileProvider: normalizedProvider,
39
+ providerConfigKey,
40
+ connectLink: session.connectLink,
41
+ sessionToken: session.sessionToken,
42
+ expiresAt: session.expiresAt,
43
+ connectionId: session.connectionId
44
+ };
45
+ }
46
+ async waitForConnection(relayfileProvider, options) {
47
+ const normalizedProvider = normalizeRelayfileProvider(relayfileProvider);
48
+ const providerConfigKey = this.resolveProviderConfigKey(normalizedProvider);
49
+ const connectProvider = this.requireConnectProvider();
50
+ const connectionId = options.connectionId?.trim();
51
+ if (!connectionId) {
52
+ throw new Error("connectionId is required to wait for a self-host connection");
53
+ }
54
+ const pollIntervalMs = normalizeNonNegativeInteger(options.pollIntervalMs, this.defaultPollIntervalMs);
55
+ const timeoutMs = normalizePositiveInteger(options.timeoutMs, this.defaultTimeoutMs);
56
+ const startedAt = Date.now();
57
+ for (;;) {
58
+ throwIfAborted(options.signal);
59
+ const elapsedMs = Date.now() - startedAt;
60
+ if (elapsedMs >= timeoutMs) {
61
+ throw new Error(`Timed out waiting for ${normalizedProvider} connection "${connectionId}" after ${elapsedMs}ms.`);
62
+ }
63
+ const status = await connectProvider.getConnectionStatus({
64
+ relayfileProvider: normalizedProvider,
65
+ providerConfigKey,
66
+ connectionId
67
+ });
68
+ options.onPoll?.(Date.now() - startedAt, status);
69
+ if (isAuthReady(status)) {
70
+ return status;
71
+ }
72
+ const sleepMs = Math.min(pollIntervalMs, Math.max(0, timeoutMs - (Date.now() - startedAt)));
73
+ await sleep(sleepMs, options.signal);
74
+ }
75
+ }
76
+ resolveProviderConfigKey(relayfileProvider) {
77
+ const providerConfigKey = this.providerConfigKeys[relayfileProvider]?.trim();
78
+ if (!providerConfigKey) {
79
+ throw new Error(`No providerConfigKey mapping configured for relayfile provider "${relayfileProvider}".`);
80
+ }
81
+ return providerConfigKey;
82
+ }
83
+ requireConnectProvider() {
84
+ if (!supportsConnect(this.provider)) {
85
+ throw new Error(`Provider "${this.provider.name}" does not support self-host Connect.`);
86
+ }
87
+ return this.provider;
88
+ }
89
+ }
90
+ function isAuthReady(status) {
91
+ return status.state === AUTH_READY_STATE || status.ready === true;
92
+ }
93
+ function normalizeRelayfileProvider(provider) {
94
+ const normalized = provider?.trim();
95
+ if (!normalized) {
96
+ throw new Error("relayfileProvider is required");
97
+ }
98
+ return normalized;
99
+ }
100
+ function normalizePositiveInteger(value, fallback) {
101
+ if (value === undefined) {
102
+ return fallback;
103
+ }
104
+ return Math.max(1, Math.floor(value));
105
+ }
106
+ function normalizeNonNegativeInteger(value, fallback) {
107
+ if (value === undefined) {
108
+ return fallback;
109
+ }
110
+ return Math.max(0, Math.floor(value));
111
+ }
112
+ function throwIfAborted(signal) {
113
+ if (signal?.aborted) {
114
+ throw createAbortError();
115
+ }
116
+ }
117
+ function sleep(ms, signal) {
118
+ if (ms <= 0) {
119
+ return Promise.resolve();
120
+ }
121
+ if (signal?.aborted) {
122
+ return Promise.reject(createAbortError());
123
+ }
124
+ return new Promise((resolve, reject) => {
125
+ const onAbort = () => {
126
+ clearTimeout(timeout);
127
+ signal?.removeEventListener("abort", onAbort);
128
+ reject(createAbortError());
129
+ };
130
+ const timeout = setTimeout(() => {
131
+ signal?.removeEventListener("abort", onAbort);
132
+ resolve();
133
+ }, ms);
134
+ signal?.addEventListener("abort", onAbort, { once: true });
135
+ });
136
+ }
137
+ function createAbortError() {
138
+ const error = new Error("Aborted while waiting for self-host connection.");
139
+ error.name = "AbortError";
140
+ return error;
141
+ }
package/dist/types.d.ts CHANGED
@@ -357,10 +357,11 @@ export interface SyncRefreshRequest {
357
357
  provider: string;
358
358
  reason?: string;
359
359
  }
360
- export type SyncProviderStatusState = "healthy" | "lagging" | "error" | "paused";
360
+ export type SyncProviderStatusState = "connected" | "oauth_connected" | "sync_queued" | "syncing" | "ready" | "healthy" | "lagging" | "error" | "paused";
361
361
  export interface SyncProviderStatus {
362
362
  provider: string;
363
363
  status: SyncProviderStatusState;
364
+ ready?: boolean;
364
365
  cursor?: string | null;
365
366
  watermarkTs?: string | null;
366
367
  lagSeconds?: number;
@@ -534,6 +535,11 @@ export interface GetSyncStatusOptions {
534
535
  correlationId?: string;
535
536
  signal?: AbortSignal;
536
537
  }
538
+ export interface WaitForDataOptions extends GetSyncStatusOptions {
539
+ pollIntervalMs?: number;
540
+ timeoutMs?: number;
541
+ onPoll?: (elapsedMs: number, status?: SyncProviderStatus) => void;
542
+ }
537
543
  export interface GetSyncIngressStatusOptions {
538
544
  provider?: string;
539
545
  correlationId?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relayfile/sdk",
3
- "version": "0.10.2",
3
+ "version": "0.10.3",
4
4
  "description": "TypeScript SDK for relayfile — real-time filesystem for humans and agents",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -59,15 +59,15 @@
59
59
  "prepublishOnly": "npm run build"
60
60
  },
61
61
  "dependencies": {
62
- "@relayfile/core": "0.10.2",
62
+ "@relayfile/core": "0.10.3",
63
63
  "ignore": "^7.0.5",
64
64
  "tar": "^7.5.10"
65
65
  },
66
66
  "optionalDependencies": {
67
- "@relayfile/mount-darwin-arm64": "0.10.2",
68
- "@relayfile/mount-darwin-x64": "0.10.2",
69
- "@relayfile/mount-linux-arm64": "0.10.2",
70
- "@relayfile/mount-linux-x64": "0.10.2"
67
+ "@relayfile/mount-darwin-arm64": "0.10.3",
68
+ "@relayfile/mount-darwin-x64": "0.10.3",
69
+ "@relayfile/mount-linux-arm64": "0.10.3",
70
+ "@relayfile/mount-linux-x64": "0.10.3"
71
71
  },
72
72
  "devDependencies": {
73
73
  "typescript": "^5.7.3",