@syncular/relay 0.0.1 → 0.0.2-127

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +41 -0
  2. package/dist/client-role/forward-engine.d.ts.map +1 -1
  3. package/dist/client-role/forward-engine.js +11 -11
  4. package/dist/client-role/forward-engine.js.map +1 -1
  5. package/dist/client-role/index.js +3 -3
  6. package/dist/client-role/pull-engine.d.ts +2 -2
  7. package/dist/client-role/pull-engine.d.ts.map +1 -1
  8. package/dist/client-role/pull-engine.js +38 -18
  9. package/dist/client-role/pull-engine.js.map +1 -1
  10. package/dist/index.d.ts +2 -2
  11. package/dist/index.js +9 -9
  12. package/dist/mode-manager.js +1 -1
  13. package/dist/mode-manager.js.map +1 -1
  14. package/dist/relay.d.ts +7 -6
  15. package/dist/relay.d.ts.map +1 -1
  16. package/dist/relay.js +37 -31
  17. package/dist/relay.js.map +1 -1
  18. package/dist/server-role/index.d.ts +1 -1
  19. package/dist/server-role/index.d.ts.map +1 -1
  20. package/dist/server-role/index.js +9 -12
  21. package/dist/server-role/index.js.map +1 -1
  22. package/dist/server-role/pull.d.ts +1 -1
  23. package/dist/server-role/pull.d.ts.map +1 -1
  24. package/dist/server-role/pull.js +2 -2
  25. package/dist/server-role/pull.js.map +1 -1
  26. package/dist/server-role/push.d.ts +1 -1
  27. package/dist/server-role/push.d.ts.map +1 -1
  28. package/dist/server-role/push.js +23 -27
  29. package/dist/server-role/push.js.map +1 -1
  30. package/package.json +28 -6
  31. package/src/__tests__/relay.test.ts +317 -0
  32. package/src/client-role/forward-engine.ts +11 -14
  33. package/src/client-role/pull-engine.ts +47 -21
  34. package/src/index.ts +2 -2
  35. package/src/mode-manager.ts +1 -1
  36. package/src/relay.ts +35 -30
  37. package/src/server-role/index.ts +8 -11
  38. package/src/server-role/pull.ts +3 -3
  39. package/src/server-role/push.ts +27 -34
@@ -7,6 +7,7 @@
7
7
  import type { SyncPullRequest, SyncPushRequest } from '@syncular/core';
8
8
  import {
9
9
  createSyncTimer,
10
+ isRecord,
10
11
  logSyncEvent,
11
12
  ScopeValuesSchema,
12
13
  SyncBootstrapStateSchema,
@@ -31,7 +32,7 @@ export interface CreateRelayRoutesOptions<
31
32
  > {
32
33
  db: Kysely<DB>;
33
34
  dialect: ServerSyncDialect;
34
- shapes: TableRegistry<DB>;
35
+ handlers: TableRegistry<DB>;
35
36
  realtime: RelayRealtime;
36
37
  /**
37
38
  * Called after a commit is successfully applied locally.
@@ -64,10 +65,6 @@ function clampInt(value: number, min: number, max: number): number {
64
65
  return Math.max(min, Math.min(max, value));
65
66
  }
66
67
 
67
- function isRecord(value: unknown): value is Record<string, unknown> {
68
- return typeof value === 'object' && value !== null && !Array.isArray(value);
69
- }
70
-
71
68
  /**
72
69
  * Create Hono routes for relay server-role endpoints.
73
70
  *
@@ -139,12 +136,12 @@ export function createRelayRoutes<DB extends RelayDatabase = RelayDatabase>(
139
136
  }
140
137
 
141
138
  const id = typeof subValue.id === 'string' ? subValue.id : null;
142
- const shape = typeof subValue.shape === 'string' ? subValue.shape : null;
143
- if (!id || !shape) {
139
+ const table = typeof subValue.table === 'string' ? subValue.table : null;
140
+ if (!id || !table) {
144
141
  return c.json(
145
142
  {
146
143
  error: 'INVALID_REQUEST',
147
- message: 'Subscription id/shape required',
144
+ message: 'Subscription id/table required',
148
145
  },
149
146
  400
150
147
  );
@@ -198,7 +195,7 @@ export function createRelayRoutes<DB extends RelayDatabase = RelayDatabase>(
198
195
 
199
196
  subscriptions.push({
200
197
  id,
201
- shape,
198
+ table,
202
199
  scopes: scopesParsed.data,
203
200
  params: rawParams,
204
201
  cursor,
@@ -250,7 +247,7 @@ export function createRelayRoutes<DB extends RelayDatabase = RelayDatabase>(
250
247
  const pullResult = await relayPull({
251
248
  db: options.db,
252
249
  dialect: options.dialect,
253
- shapes: options.shapes,
250
+ handlers: options.handlers,
254
251
  actorId: auth.actorId,
255
252
  request: validatedRequest.data,
256
253
  });
@@ -308,7 +305,7 @@ export function createRelayRoutes<DB extends RelayDatabase = RelayDatabase>(
308
305
  const pushed = await relayPushCommit({
309
306
  db: options.db,
310
307
  dialect: options.dialect,
311
- shapes: options.shapes,
308
+ handlers: options.handlers,
312
309
  actorId: auth.actorId,
313
310
  request: body,
314
311
  });
@@ -22,15 +22,15 @@ export async function relayPull<
22
22
  >(args: {
23
23
  db: Kysely<DB>;
24
24
  dialect: ServerSyncDialect;
25
- shapes: TableRegistry<DB>;
25
+ handlers: TableRegistry<DB>;
26
26
  actorId: string;
27
27
  request: SyncPullRequest;
28
28
  }): Promise<PullResult> {
29
- // Use the standard pull - scope authorization is handled by shapes
29
+ // Use the standard pull - scope authorization is handled by handlers
30
30
  return pull({
31
31
  db: args.db,
32
32
  dialect: args.dialect,
33
- shapes: args.shapes,
33
+ handlers: args.handlers,
34
34
  actorId: args.actorId,
35
35
  request: args.request,
36
36
  });
@@ -6,21 +6,12 @@
6
6
  */
7
7
 
8
8
  import type { SyncPushRequest } from '@syncular/core';
9
+ import { randomId } from '@syncular/core';
9
10
  import type { ServerSyncDialect, TableRegistry } from '@syncular/server';
10
11
  import { type PushCommitResult, pushCommit } from '@syncular/server';
11
12
  import { type Kysely, sql } from 'kysely';
12
13
  import type { RelayDatabase } from '../schema';
13
14
 
14
- function randomId(): string {
15
- if (
16
- typeof crypto !== 'undefined' &&
17
- typeof crypto.randomUUID === 'function'
18
- ) {
19
- return crypto.randomUUID();
20
- }
21
- return `${Date.now()}-${Math.random().toString(16).slice(2)}`;
22
- }
23
-
24
15
  /**
25
16
  * Push a commit from a local client to the relay.
26
17
  *
@@ -34,37 +25,39 @@ export async function relayPushCommit<
34
25
  >(args: {
35
26
  db: Kysely<DB>;
36
27
  dialect: ServerSyncDialect;
37
- shapes: TableRegistry<DB>;
28
+ handlers: TableRegistry<DB>;
38
29
  actorId: string;
39
30
  request: SyncPushRequest;
40
31
  }): Promise<PushCommitResult> {
41
32
  const { request } = args;
42
33
 
43
- // Use the standard pushCommit - scope authorization is handled by shapes
44
- const result = await pushCommit({
45
- db: args.db,
46
- dialect: args.dialect,
47
- shapes: args.shapes,
48
- actorId: args.actorId,
49
- request,
50
- });
51
-
52
- // If the commit was applied, enqueue it for forwarding to main server
53
- if (
54
- result.response.ok === true &&
55
- result.response.status === 'applied' &&
56
- typeof result.response.commitSeq === 'number'
57
- ) {
58
- await enqueueForForwarding(args.db, {
59
- localCommitSeq: result.response.commitSeq,
60
- clientId: request.clientId,
61
- clientCommitId: request.clientCommitId,
62
- operations: request.operations,
63
- schemaVersion: request.schemaVersion,
34
+ return args.db.transaction().execute(async (trx) => {
35
+ // Use the standard pushCommit - scope authorization is handled by handlers
36
+ const result = await pushCommit({
37
+ db: trx,
38
+ dialect: args.dialect,
39
+ handlers: args.handlers,
40
+ actorId: args.actorId,
41
+ request,
64
42
  });
65
- }
66
43
 
67
- return result;
44
+ // If the commit was applied, enqueue it for forwarding to main server
45
+ if (
46
+ result.response.ok === true &&
47
+ result.response.status === 'applied' &&
48
+ typeof result.response.commitSeq === 'number'
49
+ ) {
50
+ await enqueueForForwarding(trx, {
51
+ localCommitSeq: result.response.commitSeq,
52
+ clientId: request.clientId,
53
+ clientCommitId: request.clientCommitId,
54
+ operations: request.operations,
55
+ schemaVersion: request.schemaVersion,
56
+ });
57
+ }
58
+
59
+ return result;
60
+ });
68
61
  }
69
62
 
70
63
  /**