@stratasync/transport-graphql 0.2.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/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # @stratasync/transport-graphql
2
+
3
+ GraphQL transport adapter for sync communication and mutations in the Done.
4
+
5
+ ## Overview
6
+
7
+ sync-transport-graphql handles communication between the sync client and server:
8
+
9
+ - **GraphQL client initialization** for sync endpoints
10
+ - **Delta subscriptions** via GraphQL subscriptions over WebSocket
11
+ - **Mutation document generation** from model metadata
12
+ - **Message serialization** for sync payloads including Yjs binary deltas
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @stratasync/transport-graphql
18
+ ```
19
+
20
+ Dependencies: `@stratasync/core`, `@stratasync/yjs`
21
+
22
+ ## Usage
23
+
24
+ ```typescript
25
+ import { createGraphQLTransport } from "@stratasync/transport-graphql";
26
+
27
+ const transport = createGraphQLTransport({
28
+ endpoint: "https://api.example.com/graphql",
29
+ wsEndpoint: "wss://api.example.com/graphql",
30
+ });
31
+
32
+ // Pass to SyncClient configuration
33
+ const client = new SyncClient({
34
+ transport,
35
+ });
36
+ ```
37
+
38
+ ## How It Works
39
+
40
+ 1. **Bootstrap** — fetches initial state via GraphQL query
41
+ 2. **Subscribe** — opens a WebSocket subscription for real-time deltas
42
+ 3. **Mutate** — sends client mutations as GraphQL mutations
43
+ 4. **Reconnect** — handles connection drops with automatic retry and resubscription
44
+
45
+ Yjs collaborative editing deltas are encoded as binary (Uint8Array) within GraphQL payloads.
@@ -0,0 +1,31 @@
1
+ import type { TransportAdapter } from "@stratasync/client";
2
+ import type { BatchLoadOptions, BootstrapMetadata, BootstrapOptions, ConnectionState, DeltaPacket, DeltaSubscription, ModelRow, MutateResult, SubscribeOptions, SyncId, TransactionBatch } from "@stratasync/core";
3
+ import type { TransportOptions } from "./types.js";
4
+ import { YjsTransportAdapter } from "./yjs-transport.js";
5
+ /**
6
+ * GraphQL transport adapter implementation
7
+ */
8
+ export declare class GraphQLTransportAdapter implements TransportAdapter {
9
+ private readonly options;
10
+ private readonly wsManager;
11
+ private connectionState;
12
+ private readonly stateListeners;
13
+ private readonly retryConfig;
14
+ private readonly syncEndpoint;
15
+ private yjsTransport;
16
+ constructor(options: TransportOptions);
17
+ bootstrap(options: BootstrapOptions): AsyncGenerator<ModelRow, BootstrapMetadata, unknown>;
18
+ batchLoad(options: BatchLoadOptions): AsyncIterable<ModelRow>;
19
+ mutate(batch: TransactionBatch): Promise<MutateResult>;
20
+ subscribe(options: SubscribeOptions): DeltaSubscription;
21
+ getYjsTransport(): YjsTransportAdapter;
22
+ fetchDeltas(after: SyncId, limit?: number, groups?: string[]): Promise<DeltaPacket>;
23
+ getConnectionState(): ConnectionState;
24
+ onConnectionStateChange(callback: (state: ConnectionState) => void): () => void;
25
+ close(): Promise<void>;
26
+ private setConnectionState;
27
+ private getYjsConnectionState;
28
+ private syncYjsConnectionState;
29
+ private static resolveYjsConnectionState;
30
+ }
31
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,MAAM,EACN,gBAAgB,EACjB,MAAM,kBAAkB,CAAC;AAW1B,OAAO,KAAK,EAAe,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGhE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;GAEG;AACH,qBAAa,uBAAwB,YAAW,gBAAgB;IAC9D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;IAC7C,OAAO,CAAC,eAAe,CAAmC;IAC1D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+C;IAC9E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,YAAY,CAAoC;gBAE5C,OAAO,EAAE,gBAAgB;IAyBrC,SAAS,CACP,OAAO,EAAE,gBAAgB,GACxB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAO,CAAC;IAWvD,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa,CAAC,QAAQ,CAAC;IAW7D,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;IAyBtD,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,iBAAiB;IAIvD,eAAe,IAAI,mBAAmB;IAwBtC,WAAW,CACT,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,WAAW,CAAC;IAavB,kBAAkB,IAAI,eAAe;IAIrC,uBAAuB,CAErB,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,GACzC,MAAM,IAAI;IAOP,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,qBAAqB;IAO7B,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,MAAM,CAAC,yBAAyB;CASzC"}
@@ -0,0 +1,151 @@
1
+ import { isLiveEditingErrorMessage, isSessionStateMessage, isYjsSyncStep2Message, isYjsUpdateMessage, } from "@stratasync/yjs";
2
+ import { createBatchLoadStream, createBootstrapStream } from "./bootstrap.js";
3
+ import { fetchDeltas } from "./deltas.js";
4
+ import { sendMutations, sendRestMutations } from "./mutations.js";
5
+ import { DEFAULT_RETRY_CONFIG } from "./types.js";
6
+ import { WebSocketManager } from "./websocket.js";
7
+ import { YjsTransportAdapter } from "./yjs-transport.js";
8
+ /**
9
+ * GraphQL transport adapter implementation
10
+ */
11
+ export class GraphQLTransportAdapter {
12
+ options;
13
+ wsManager;
14
+ connectionState = "disconnected";
15
+ stateListeners = new Set();
16
+ retryConfig;
17
+ syncEndpoint;
18
+ yjsTransport = null;
19
+ constructor(options) {
20
+ this.options = options;
21
+ this.retryConfig = options.retry ?? DEFAULT_RETRY_CONFIG;
22
+ if (!options.syncEndpoint) {
23
+ throw new Error("syncEndpoint is required");
24
+ }
25
+ this.syncEndpoint = options.syncEndpoint;
26
+ this.wsManager = new WebSocketManager(options.wsEndpoint, options.auth, this.retryConfig, options.webSocketFactory);
27
+ // Forward WebSocket connection state changes
28
+ this.wsManager.onConnectionStateChange((state) => {
29
+ this.setConnectionState(state);
30
+ this.syncYjsConnectionState(state, this.wsManager.isSubscribedReady());
31
+ });
32
+ this.wsManager.onSubscribeStateChange((ready) => {
33
+ this.syncYjsConnectionState(this.wsManager.getConnectionState(), ready);
34
+ });
35
+ }
36
+ bootstrap(options) {
37
+ return createBootstrapStream({
38
+ auth: this.options.auth,
39
+ bootstrapOptions: options,
40
+ headers: this.options.headers,
41
+ retryConfig: this.retryConfig,
42
+ syncEndpoint: this.syncEndpoint,
43
+ timeoutMs: this.options.timeout,
44
+ });
45
+ }
46
+ batchLoad(options) {
47
+ return createBatchLoadStream({
48
+ auth: this.options.auth,
49
+ batchLoadOptions: options,
50
+ headers: this.options.headers,
51
+ retryConfig: this.retryConfig,
52
+ syncEndpoint: this.syncEndpoint,
53
+ timeoutMs: this.options.timeout,
54
+ });
55
+ }
56
+ mutate(batch) {
57
+ // Use REST endpoint when no GraphQL mutation builder is configured
58
+ if (!this.options.mutationBuilder) {
59
+ return sendRestMutations({
60
+ auth: this.options.auth,
61
+ batch,
62
+ endpoint: `${this.syncEndpoint}/mutate`,
63
+ headers: this.options.headers,
64
+ retryConfig: this.retryConfig,
65
+ timeoutMs: this.options.timeout,
66
+ });
67
+ }
68
+ // Otherwise use GraphQL
69
+ return sendMutations({
70
+ auth: this.options.auth,
71
+ batch,
72
+ endpoint: this.options.endpoint,
73
+ headers: this.options.headers,
74
+ mutationBuilder: this.options.mutationBuilder,
75
+ retryConfig: this.retryConfig,
76
+ timeoutMs: this.options.timeout,
77
+ });
78
+ }
79
+ subscribe(options) {
80
+ return this.wsManager.subscribe(options);
81
+ }
82
+ getYjsTransport() {
83
+ if (this.yjsTransport) {
84
+ return this.yjsTransport;
85
+ }
86
+ const adapter = new YjsTransportAdapter((message) => {
87
+ this.wsManager.sendRaw(JSON.stringify(message));
88
+ }, this.getYjsConnectionState());
89
+ this.wsManager.onYjsMessage((message) => {
90
+ if (isYjsSyncStep2Message(message) ||
91
+ isYjsUpdateMessage(message) ||
92
+ isSessionStateMessage(message) ||
93
+ isLiveEditingErrorMessage(message)) {
94
+ adapter.handleIncoming(message);
95
+ }
96
+ });
97
+ this.yjsTransport = adapter;
98
+ return adapter;
99
+ }
100
+ fetchDeltas(after, limit, groups) {
101
+ return fetchDeltas({
102
+ afterSyncId: after,
103
+ auth: this.options.auth,
104
+ groups,
105
+ headers: this.options.headers,
106
+ limit,
107
+ retryConfig: this.retryConfig,
108
+ syncEndpoint: this.syncEndpoint,
109
+ timeoutMs: this.options.timeout,
110
+ });
111
+ }
112
+ getConnectionState() {
113
+ return this.connectionState;
114
+ }
115
+ onConnectionStateChange(
116
+ // oxlint-disable-next-line prefer-await-to-callbacks -- event listener registration
117
+ callback) {
118
+ this.stateListeners.add(callback);
119
+ return () => {
120
+ this.stateListeners.delete(callback);
121
+ };
122
+ }
123
+ async close() {
124
+ await this.wsManager.close();
125
+ this.setConnectionState("disconnected");
126
+ }
127
+ setConnectionState(state) {
128
+ if (this.connectionState !== state) {
129
+ this.connectionState = state;
130
+ for (const listener of this.stateListeners) {
131
+ listener(state);
132
+ }
133
+ }
134
+ }
135
+ getYjsConnectionState() {
136
+ return GraphQLTransportAdapter.resolveYjsConnectionState(this.wsManager.getConnectionState(), this.wsManager.isSubscribedReady());
137
+ }
138
+ syncYjsConnectionState(wsState, subscribeReady) {
139
+ if (!this.yjsTransport) {
140
+ return;
141
+ }
142
+ this.yjsTransport.handleConnectionStateChange(GraphQLTransportAdapter.resolveYjsConnectionState(wsState, subscribeReady));
143
+ }
144
+ static resolveYjsConnectionState(wsState, subscribeReady) {
145
+ if (wsState !== "connected") {
146
+ return wsState;
147
+ }
148
+ return subscribeReady ? "connected" : "connecting";
149
+ }
150
+ }
151
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAElE,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;GAEG;AACH,MAAM,OAAO,uBAAuB;IACjB,OAAO,CAAmB;IAC1B,SAAS,CAAmB;IACrC,eAAe,GAAoB,cAAc,CAAC;IACzC,cAAc,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC7D,WAAW,CAAc;IACzB,YAAY,CAAS;IAC9B,YAAY,GAA+B,IAAI,CAAC;IAExD,YAAY,OAAyB;QACnC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,KAAK,IAAI,oBAAoB,CAAC;QACzD,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,SAAS,GAAG,IAAI,gBAAgB,CACnC,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,IAAI,EACZ,IAAI,CAAC,WAAW,EAChB,OAAO,CAAC,gBAAgB,CACzB,CAAC;QAEF,6CAA6C;QAC7C,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC,KAAK,EAAE,EAAE;YAC/C,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;YAC/B,IAAI,CAAC,sBAAsB,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,EAAE;YAC9C,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC,kBAAkB,EAAE,EAAE,KAAK,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;IACL,CAAC;IAED,SAAS,CACP,OAAyB;QAEzB,OAAO,qBAAqB,CAAC;YAC3B,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;YACvB,gBAAgB,EAAE,OAAO;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;YAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;SAChC,CAAC,CAAC;IACL,CAAC;IAED,SAAS,CAAC,OAAyB;QACjC,OAAO,qBAAqB,CAAC;YAC3B,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;YACvB,gBAAgB,EAAE,OAAO;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;YAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;SAChC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,KAAuB;QAC5B,mEAAmE;QACnE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;YAClC,OAAO,iBAAiB,CAAC;gBACvB,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;gBACvB,KAAK;gBACL,QAAQ,EAAE,GAAG,IAAI,CAAC,YAAY,SAAS;gBACvC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;gBAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;aAChC,CAAC,CAAC;QACL,CAAC;QAED,wBAAwB;QACxB,OAAO,aAAa,CAAC;YACnB,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;YACvB,KAAK;YACL,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;YAC/B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;YAC7B,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,eAAe;YAC7C,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;SAChC,CAAC,CAAC;IACL,CAAC;IAED,SAAS,CAAC,OAAyB;QACjC,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,eAAe;QACb,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC,YAAY,CAAC;QAC3B,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,mBAAmB,CAAC,CAAC,OAAO,EAAE,EAAE;YAClD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QAClD,CAAC,EAAE,IAAI,CAAC,qBAAqB,EAAE,CAAC,CAAC;QAEjC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,EAAE;YACtC,IACE,qBAAqB,CAAC,OAAO,CAAC;gBAC9B,kBAAkB,CAAC,OAAO,CAAC;gBAC3B,qBAAqB,CAAC,OAAO,CAAC;gBAC9B,yBAAyB,CAAC,OAAO,CAAC,EAClC,CAAC;gBACD,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YAClC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;QAC5B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,WAAW,CACT,KAAa,EACb,KAAc,EACd,MAAiB;QAEjB,OAAO,WAAW,CAAC;YACjB,WAAW,EAAE,KAAK;YAClB,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;YACvB,MAAM;YACN,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;YAC7B,KAAK;YACL,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;SAChC,CAAC,CAAC;IACL,CAAC;IAED,kBAAkB;QAChB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED,uBAAuB;IACrB,oFAAoF;IACpF,QAA0C;QAE1C,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;IAEO,kBAAkB,CAAC,KAAsB;QAC/C,IAAI,IAAI,CAAC,eAAe,KAAK,KAAK,EAAE,CAAC;YACnC,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;YAC7B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;gBAC3C,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAEO,qBAAqB;QAC3B,OAAO,uBAAuB,CAAC,yBAAyB,CACtD,IAAI,CAAC,SAAS,CAAC,kBAAkB,EAAE,EACnC,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,CACnC,CAAC;IACJ,CAAC;IAEO,sBAAsB,CAC5B,OAAwB,EACxB,cAAuB;QAEvB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,2BAA2B,CAC3C,uBAAuB,CAAC,yBAAyB,CAAC,OAAO,EAAE,cAAc,CAAC,CAC3E,CAAC;IACJ,CAAC;IAEO,MAAM,CAAC,yBAAyB,CACtC,OAAwB,EACxB,cAAuB;QAEvB,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;YAC5B,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC;IACrD,CAAC;CACF"}
@@ -0,0 +1,27 @@
1
+ import type { BatchLoadOptions, BootstrapMetadata, BootstrapOptions, ModelRow } from "@stratasync/core";
2
+ import type { AuthProvider, RetryConfig } from "./types.js";
3
+ export interface BootstrapStreamOptions {
4
+ syncEndpoint: string;
5
+ bootstrapOptions: BootstrapOptions;
6
+ auth: AuthProvider;
7
+ headers?: Record<string, string>;
8
+ retryConfig?: RetryConfig;
9
+ timeoutMs?: number;
10
+ }
11
+ /**
12
+ * Creates a bootstrap stream that yields model rows
13
+ */
14
+ export declare function createBootstrapStream(opts: BootstrapStreamOptions): AsyncGenerator<ModelRow, BootstrapMetadata, unknown>;
15
+ export interface BatchLoadStreamOptions {
16
+ syncEndpoint: string;
17
+ batchLoadOptions: BatchLoadOptions;
18
+ auth: AuthProvider;
19
+ headers?: Record<string, string>;
20
+ retryConfig?: RetryConfig;
21
+ timeoutMs?: number;
22
+ }
23
+ /**
24
+ * Batch loads specific model instances via REST
25
+ */
26
+ export declare function createBatchLoadStream(opts: BatchLoadStreamOptions): AsyncGenerator<ModelRow, void, unknown>;
27
+ //# sourceMappingURL=bootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAEhB,iBAAiB,EACjB,gBAAgB,EAChB,QAAQ,EACT,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAU5D,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AAKH,wBAAuB,qBAAqB,CAC1C,IAAI,EAAE,sBAAsB,GAC3B,cAAc,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAO,CAAC,CAuCtD;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AAEH,wBAAuB,qBAAqB,CAC1C,IAAI,EAAE,sBAAsB,GAC3B,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAyCzC"}
@@ -0,0 +1,223 @@
1
+ import { joinSyncUrl, normalizeSyncEndpoint } from "./protocol.js";
2
+ import { buildRequestHeaders, fetchChecked, isRetryableError, parseSyncId, resolveAuthToken, retryWithBackoff, } from "./utils.js";
3
+ /**
4
+ * Creates a bootstrap stream that yields model rows
5
+ */
6
+ // oxlint-disable-next-line func-style -- generators require function declaration
7
+ // oxlint-disable-next-line require-yields
8
+ // oxlint-disable-next-line func-style
9
+ // oxlint-disable-next-line func-style, require-yields -- generators require function declaration
10
+ export async function* createBootstrapStream(opts) {
11
+ const url = buildBootstrapUrl(opts.syncEndpoint, opts.bootstrapOptions);
12
+ const response = await retryWithBackoff(async () => {
13
+ const token = await resolveAuthToken(opts.auth);
14
+ const requestHeaders = buildRequestHeaders({
15
+ accept: "application/x-ndjson",
16
+ headers: opts.headers,
17
+ token,
18
+ });
19
+ return fetchChecked(url, { headers: requestHeaders, method: "GET" }, opts.timeoutMs, "Bootstrap failed");
20
+ }, opts.retryConfig, isRetryableError);
21
+ if (!response.body) {
22
+ throw new Error("Bootstrap response has no body");
23
+ }
24
+ let metadata = null;
25
+ for await (const line of readNdjsonLines(response.body)) {
26
+ const parsed = parseBootstrapLine(line);
27
+ if (parsed?.type === "meta") {
28
+ ({ metadata } = parsed);
29
+ }
30
+ else if (parsed?.type === "row") {
31
+ yield parsed.row;
32
+ }
33
+ }
34
+ return finalizeBootstrapMetadata(metadata, opts.bootstrapOptions);
35
+ }
36
+ /**
37
+ * Batch loads specific model instances via REST
38
+ */
39
+ // oxlint-disable-next-line func-style, require-yields -- generators require function declaration
40
+ export async function* createBatchLoadStream(opts) {
41
+ const body = JSON.stringify({
42
+ firstSyncId: parseSyncId(opts.batchLoadOptions.firstSyncId, "Batch load firstSyncId"),
43
+ requests: opts.batchLoadOptions.requests.map(serializeBatchRequest),
44
+ });
45
+ const syncBase = normalizeSyncEndpoint(opts.syncEndpoint);
46
+ const url = joinSyncUrl(syncBase, "/batch");
47
+ const response = await retryWithBackoff(async () => {
48
+ const token = await resolveAuthToken(opts.auth);
49
+ const requestHeaders = buildRequestHeaders({
50
+ accept: "application/x-ndjson",
51
+ contentType: "application/json",
52
+ headers: opts.headers,
53
+ token,
54
+ });
55
+ return fetchChecked(url, { body, headers: requestHeaders, method: "POST" }, opts.timeoutMs, "Batch load failed");
56
+ }, opts.retryConfig, isRetryableError);
57
+ if (!response.body) {
58
+ throw new Error("Batch load response has no body");
59
+ }
60
+ for await (const line of readNdjsonLines(response.body)) {
61
+ const parsed = parseBootstrapLine(line);
62
+ if (parsed?.type === "row") {
63
+ yield parsed.row;
64
+ }
65
+ }
66
+ }
67
+ const buildBootstrapUrl = (syncEndpoint, options) => {
68
+ const params = new URLSearchParams();
69
+ params.set("type", options.type ?? "full");
70
+ if (options.onlyModels?.length) {
71
+ params.set("onlyModels", options.onlyModels.join(","));
72
+ }
73
+ if (options.schemaHash) {
74
+ params.set("schemaHash", options.schemaHash);
75
+ }
76
+ if (options.firstSyncId !== undefined) {
77
+ params.set("firstSyncId", parseSyncId(options.firstSyncId, "Bootstrap options firstSyncId"));
78
+ }
79
+ if (options.syncGroups?.length) {
80
+ params.set("syncGroups", options.syncGroups.join(","));
81
+ }
82
+ if (options.noSyncPackets) {
83
+ params.set("noSyncPackets", "true");
84
+ }
85
+ if (options.useCFCaching) {
86
+ params.set("useCFCaching", "true");
87
+ }
88
+ if (options.noCache) {
89
+ params.set("noCache", "true");
90
+ }
91
+ if (options.modelsHash) {
92
+ params.set("modelsHash", options.modelsHash);
93
+ }
94
+ const syncBase = normalizeSyncEndpoint(syncEndpoint);
95
+ return `${joinSyncUrl(syncBase, "/bootstrap")}?${params.toString()}`;
96
+ };
97
+ // oxlint-disable-next-line func-style -- generators require function declaration
98
+ async function* readNdjsonLines(body) {
99
+ const reader = body.getReader();
100
+ const decoder = new TextDecoder();
101
+ let buffer = "";
102
+ try {
103
+ while (true) {
104
+ const { done, value } = await reader.read();
105
+ if (done) {
106
+ break;
107
+ }
108
+ buffer += decoder.decode(value, { stream: true });
109
+ const lines = buffer.split("\n");
110
+ buffer = lines.pop() ?? "";
111
+ for (const line of lines) {
112
+ const trimmed = line.trim();
113
+ if (trimmed) {
114
+ yield trimmed;
115
+ }
116
+ }
117
+ }
118
+ if (buffer.trim()) {
119
+ yield buffer.trim();
120
+ }
121
+ }
122
+ finally {
123
+ reader.releaseLock();
124
+ }
125
+ }
126
+ const finalizeBootstrapMetadata = (metadata, options) => {
127
+ if (!metadata) {
128
+ if (options.type === "partial") {
129
+ return { subscribedSyncGroups: [] };
130
+ }
131
+ throw new Error("Bootstrap did not receive metadata");
132
+ }
133
+ if (options.type !== "partial" && metadata.lastSyncId === undefined) {
134
+ throw new Error("Bootstrap metadata is missing lastSyncId");
135
+ }
136
+ return metadata;
137
+ };
138
+ const parseBootstrapLine = (line) => {
139
+ const trimmed = line.trim();
140
+ if (!trimmed) {
141
+ return null;
142
+ }
143
+ if (trimmed.startsWith("_metadata_=")) {
144
+ const raw = JSON.parse(trimmed.slice("_metadata_=".length));
145
+ return { metadata: normalizeBootstrapMetadata(raw), type: "meta" };
146
+ }
147
+ const parsed = JSON.parse(trimmed);
148
+ if (typeof parsed._metadata_ === "object" && parsed._metadata_ !== null) {
149
+ return {
150
+ metadata: normalizeBootstrapMetadata(parsed._metadata_),
151
+ type: "meta",
152
+ };
153
+ }
154
+ if (isBootstrapMetadata(parsed)) {
155
+ return { metadata: normalizeBootstrapMetadata(parsed), type: "meta" };
156
+ }
157
+ if (parsed.type === "error") {
158
+ const message = typeof parsed.message === "string"
159
+ ? parsed.message
160
+ : "Unknown server error";
161
+ throw new Error(`Bootstrap server error: ${message}`);
162
+ }
163
+ if (parsed.type === "end") {
164
+ return null;
165
+ }
166
+ const modelName = resolveModelName(parsed);
167
+ if (!modelName) {
168
+ throw new Error("Bootstrap row is missing __class");
169
+ }
170
+ const { __class, ...data } = parsed;
171
+ return {
172
+ row: { data, modelName },
173
+ type: "row",
174
+ };
175
+ };
176
+ const isBootstrapMetadata = (parsed) => "lastSyncId" in parsed ||
177
+ "subscribedSyncGroups" in parsed ||
178
+ "returnedModelsCount" in parsed;
179
+ const normalizeBootstrapMetadata = (parsed) => {
180
+ const lastSyncIdRaw = parsed.lastSyncId;
181
+ const subscribedSyncGroupsRaw = parsed.subscribedSyncGroups;
182
+ const subscribedSyncGroups = Array.isArray(subscribedSyncGroupsRaw)
183
+ ? subscribedSyncGroupsRaw.filter((group) => typeof group === "string")
184
+ : [];
185
+ const result = {
186
+ subscribedSyncGroups,
187
+ };
188
+ if (lastSyncIdRaw !== undefined) {
189
+ result.lastSyncId = parseSyncId(lastSyncIdRaw, "Bootstrap metadata lastSyncId");
190
+ }
191
+ if (parsed.returnedModelsCount &&
192
+ typeof parsed.returnedModelsCount === "object") {
193
+ result.returnedModelsCount = parsed.returnedModelsCount;
194
+ }
195
+ if (typeof parsed.schemaHash === "string") {
196
+ result.schemaHash = parsed.schemaHash;
197
+ }
198
+ if (typeof parsed.databaseVersion === "number") {
199
+ result.databaseVersion = parsed.databaseVersion;
200
+ }
201
+ result.raw = parsed;
202
+ return result;
203
+ };
204
+ const resolveModelName = (parsed) => {
205
+ if (typeof parsed.__class === "string") {
206
+ return parsed.__class;
207
+ }
208
+ return null;
209
+ };
210
+ const serializeBatchRequest = (request) => {
211
+ if ("indexedKey" in request && typeof request.indexedKey === "string") {
212
+ return {
213
+ indexedKey: request.indexedKey,
214
+ keyValue: request.keyValue,
215
+ modelName: request.modelName,
216
+ };
217
+ }
218
+ return {
219
+ groupId: request.groupId,
220
+ modelName: request.modelName,
221
+ };
222
+ };
223
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEnE,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAWpB;;GAEG;AACH,iFAAiF;AACjF,0CAA0C;AAC1C,sCAAsC;AACtC,iGAAiG;AACjG,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,qBAAqB,CAC1C,IAA4B;IAE5B,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAExE,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CACrC,KAAK,IAAI,EAAE;QACT,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,cAAc,GAAG,mBAAmB,CAAC;YACzC,MAAM,EAAE,sBAAsB;YAC9B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK;SACN,CAAC,CAAC;QACH,OAAO,YAAY,CACjB,GAAG,EACH,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,EAC1C,IAAI,CAAC,SAAS,EACd,kBAAkB,CACnB,CAAC;IACJ,CAAC,EACD,IAAI,CAAC,WAAW,EAChB,gBAAgB,CACjB,CAAC;IAEF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,QAAQ,GAA6B,IAAI,CAAC;IAE9C,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAExC,IAAI,MAAM,EAAE,IAAI,KAAK,MAAM,EAAE,CAAC;YAC5B,CAAC,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,MAAM,EAAE,IAAI,KAAK,KAAK,EAAE,CAAC;YAClC,MAAM,MAAM,CAAC,GAAG,CAAC;QACnB,CAAC;IACH,CAAC;IAED,OAAO,yBAAyB,CAAC,QAAQ,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;AACpE,CAAC;AAWD;;GAEG;AACH,iGAAiG;AACjG,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,qBAAqB,CAC1C,IAA4B;IAE5B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;QAC1B,WAAW,EAAE,WAAW,CACtB,IAAI,CAAC,gBAAgB,CAAC,WAAW,EACjC,wBAAwB,CACzB;QACD,QAAQ,EAAE,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,qBAAqB,CAAC;KACpE,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CACrC,KAAK,IAAI,EAAE;QACT,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,cAAc,GAAG,mBAAmB,CAAC;YACzC,MAAM,EAAE,sBAAsB;YAC9B,WAAW,EAAE,kBAAkB;YAC/B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK;SACN,CAAC,CAAC;QACH,OAAO,YAAY,CACjB,GAAG,EACH,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,EACjD,IAAI,CAAC,SAAS,EACd,mBAAmB,CACpB,CAAC;IACJ,CAAC,EACD,IAAI,CAAC,WAAW,EAChB,gBAAgB,CACjB,CAAC;IAEF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,MAAM,EAAE,IAAI,KAAK,KAAK,EAAE,CAAC;YAC3B,MAAM,MAAM,CAAC,GAAG,CAAC;QACnB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,iBAAiB,GAAG,CACxB,YAAoB,EACpB,OAAyB,EACjB,EAAE;IACV,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC;IAC3C,IAAI,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,CACR,aAAa,EACb,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,+BAA+B,CAAC,CAClE,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAChC,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,QAAQ,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;IACrD,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AACvE,CAAC,CAAC;AAEF,iFAAiF;AACjF,KAAK,SAAS,CAAC,CAAC,eAAe,CAC7B,IAAgC;IAEhC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAE5C,IAAI,IAAI,EAAE,CAAC;gBACT,MAAM;YACR,CAAC;YAED,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAElD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC5B,IAAI,OAAO,EAAE,CAAC;oBACZ,MAAM,OAAO,CAAC;gBAChB,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YAClB,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC;AACH,CAAC;AAED,MAAM,yBAAyB,GAAG,CAChC,QAAkC,EAClC,OAAyB,EACN,EAAE;IACrB,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,EAAE,oBAAoB,EAAE,EAAE,EAAE,CAAC;QACtC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAMF,MAAM,kBAAkB,GAAG,CAAC,IAAY,EAA8B,EAAE;IACtE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAGzD,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,0BAA0B,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACrE,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;IAE9D,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QACxE,OAAO;YACL,QAAQ,EAAE,0BAA0B,CAClC,MAAM,CAAC,UAAqC,CAC7C;YACD,IAAI,EAAE,MAAM;SACb,CAAC;IACJ,CAAC;IAED,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,QAAQ,EAAE,0BAA0B,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACxE,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,GACX,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ;YAChC,CAAC,CAAC,MAAM,CAAC,OAAO;YAChB,CAAC,CAAC,sBAAsB,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,2BAA2B,OAAO,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,SAAS,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;IACpC,OAAO;QACL,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QACxB,IAAI,EAAE,KAAK;KACZ,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,MAA+B,EAAW,EAAE,CACvE,YAAY,IAAI,MAAM;IACtB,sBAAsB,IAAI,MAAM;IAChC,qBAAqB,IAAI,MAAM,CAAC;AAElC,MAAM,0BAA0B,GAAG,CACjC,MAA+B,EACZ,EAAE;IACrB,MAAM,aAAa,GAAG,MAAM,CAAC,UAAU,CAAC;IACxC,MAAM,uBAAuB,GAAG,MAAM,CAAC,oBAAoB,CAAC;IAE5D,MAAM,oBAAoB,GAAG,KAAK,CAAC,OAAO,CAAC,uBAAuB,CAAC;QACjE,CAAC,CAAC,uBAAuB,CAAC,MAAM,CAC5B,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CACtD;QACH,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,MAAM,GAAsB;QAChC,oBAAoB;KACrB,CAAC;IAEF,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,CAAC,UAAU,GAAG,WAAW,CAC7B,aAAa,EACb,+BAA+B,CAChC,CAAC;IACJ,CAAC;IAED,IACE,MAAM,CAAC,mBAAmB;QAC1B,OAAO,MAAM,CAAC,mBAAmB,KAAK,QAAQ,EAC9C,CAAC;QACD,MAAM,CAAC,mBAAmB,GAAG,MAAM,CAAC,mBAGnC,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC1C,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IACxC,CAAC;IACD,IAAI,OAAO,MAAM,CAAC,eAAe,KAAK,QAAQ,EAAE,CAAC;QAC/C,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;IAClD,CAAC;IACD,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC;IAEpB,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,MAA+B,EAAiB,EAAE;IAC1E,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACvC,OAAO,MAAM,CAAC,OAAO,CAAC;IACxB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAC5B,OAAqB,EACI,EAAE;IAC3B,IAAI,YAAY,IAAI,OAAO,IAAI,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QACtE,OAAO;YACL,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { DeltaPacket, SyncAction, SyncId } from "@stratasync/core";
2
+ import type { AuthProvider, RetryConfig } from "./types.js";
3
+ export interface FetchDeltasOptions {
4
+ syncEndpoint: string;
5
+ afterSyncId: SyncId;
6
+ auth: AuthProvider;
7
+ headers?: Record<string, string>;
8
+ limit?: number;
9
+ groups?: string[];
10
+ retryConfig?: RetryConfig;
11
+ timeoutMs?: number;
12
+ }
13
+ /**
14
+ * Fetches deltas from the server via REST
15
+ */
16
+ export declare const fetchDeltas: (opts: FetchDeltasOptions) => Promise<DeltaPacket>;
17
+ export interface FetchAllDeltasOptions {
18
+ syncEndpoint: string;
19
+ afterSyncId: SyncId;
20
+ auth: AuthProvider;
21
+ headers?: Record<string, string>;
22
+ batchSize?: number;
23
+ groups?: string[];
24
+ retryConfig?: RetryConfig;
25
+ timeoutMs?: number;
26
+ }
27
+ /**
28
+ * Fetches all deltas since a sync ID, handling pagination
29
+ */
30
+ export declare function fetchAllDeltas(opts: FetchAllDeltasOptions): AsyncGenerator<SyncAction, SyncId, unknown>;
31
+ //# sourceMappingURL=deltas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deltas.d.ts","sourceRoot":"","sources":["../src/deltas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQxE,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAU5D,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,MAAM,kBAAkB,KACvB,OAAO,CAAC,WAAW,CA2CrB,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AAOH,wBAAuB,cAAc,CACnC,IAAI,EAAE,qBAAqB,GAC1B,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CA8B7C"}
package/dist/deltas.js ADDED
@@ -0,0 +1,69 @@
1
+ import { maxSyncId } from "@stratasync/core";
2
+ import { joinSyncUrl, normalizeSyncEndpoint, parseDeltaPacket, } from "./protocol.js";
3
+ import { buildRequestHeaders, fetchChecked, isRetryableError, parseSyncId, resolveAuthToken, retryWithBackoff, } from "./utils.js";
4
+ /**
5
+ * Fetches deltas from the server via REST
6
+ */
7
+ export const fetchDeltas = async (opts) => {
8
+ const response = await retryWithBackoff(async () => {
9
+ const token = await resolveAuthToken(opts.auth);
10
+ const requestHeaders = buildRequestHeaders({
11
+ accept: "application/json",
12
+ headers: opts.headers,
13
+ token,
14
+ });
15
+ const params = new URLSearchParams();
16
+ params.set("after", parseSyncId(opts.afterSyncId, "Fetch deltas afterSyncId"));
17
+ if (opts.limit !== undefined) {
18
+ params.set("limit", String(opts.limit));
19
+ }
20
+ if (opts.groups && opts.groups.length > 0) {
21
+ params.set("syncGroups", opts.groups.join(","));
22
+ }
23
+ const syncBase = normalizeSyncEndpoint(opts.syncEndpoint);
24
+ const url = `${joinSyncUrl(syncBase, "/deltas")}?${params.toString()}`;
25
+ const res = await fetchChecked(url, { headers: requestHeaders, method: "GET" }, opts.timeoutMs, "Fetch deltas failed");
26
+ return res.json();
27
+ }, opts.retryConfig, isRetryableError);
28
+ const packet = parseDeltaPacket(response);
29
+ if (!packet) {
30
+ throw new Error("Delta response is not in a supported format");
31
+ }
32
+ return packet;
33
+ };
34
+ /**
35
+ * Fetches all deltas since a sync ID, handling pagination
36
+ */
37
+ // oxlint-disable-next-line func-style -- generators require function declaration
38
+ // oxlint-disable-next-line require-yields, func-style
39
+ // oxlint-disable-next-line func-style
40
+ // oxlint-disable-next-line require-yields, func-style
41
+ // oxlint-disable-next-line func-style
42
+ // oxlint-disable-next-line require-yields, func-style
43
+ export async function* fetchAllDeltas(opts) {
44
+ const batchSize = opts.batchSize ?? 1000;
45
+ let currentSyncId = opts.afterSyncId;
46
+ let lastSyncId = opts.afterSyncId;
47
+ while (true) {
48
+ const packet = await fetchDeltas({
49
+ afterSyncId: currentSyncId,
50
+ auth: opts.auth,
51
+ groups: opts.groups,
52
+ headers: opts.headers,
53
+ limit: batchSize,
54
+ retryConfig: opts.retryConfig,
55
+ syncEndpoint: opts.syncEndpoint,
56
+ timeoutMs: opts.timeoutMs,
57
+ });
58
+ for (const action of packet.actions) {
59
+ yield action;
60
+ lastSyncId = maxSyncId(lastSyncId, action.id);
61
+ }
62
+ if (!packet.hasMore || packet.actions.length === 0) {
63
+ break;
64
+ }
65
+ currentSyncId = packet.lastSyncId;
66
+ }
67
+ return lastSyncId;
68
+ }
69
+ //# sourceMappingURL=deltas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deltas.js","sourceRoot":"","sources":["../src/deltas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { GraphQLTransportAdapter } from "./adapter.js";
2
+ export type { AuthProvider, TransportOptions } from "./types.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ // biome-ignore-all lint/performance/noBarrelFile: package entry point
2
+ export { GraphQLTransportAdapter } from "./adapter.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC"}