@syncular/server-hono 0.0.3-8 → 0.0.4-26

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syncular/server-hono",
3
- "version": "0.0.3-8",
3
+ "version": "0.0.4-26",
4
4
  "description": "Hono adapter for the Syncular server with OpenAPI support",
5
5
  "license": "MIT",
6
6
  "author": "Benjamin Kniffler",
@@ -48,16 +48,17 @@
48
48
  "@hono/standard-validator": "^0.2.2",
49
49
  "@standard-community/standard-json": "^0.3.5",
50
50
  "@standard-community/standard-openapi": "^0.2.9",
51
- "@syncular/core": "0.0.3-8",
52
- "@syncular/server": "0.0.3-8",
51
+ "@syncular/console": "0.0.4-26",
52
+ "@syncular/core": "0.0.4-26",
53
+ "@syncular/server": "0.0.4-26",
53
54
  "@types/json-schema": "^7.0.15",
54
55
  "hono-openapi": "^1.2.0",
55
56
  "openapi-types": "^12.1.3"
56
57
  },
57
58
  "devDependencies": {
58
59
  "@syncular/config": "0.0.0",
59
- "@syncular/dialect-pglite": "0.0.3-8",
60
- "@syncular/server-dialect-postgres": "0.0.3-8",
60
+ "@syncular/dialect-pglite": "0.0.4-26",
61
+ "@syncular/server-dialect-postgres": "0.0.4-26",
61
62
  "kysely": "*",
62
63
  "zod": "*"
63
64
  },
@@ -1081,7 +1081,15 @@ export function createConsoleGatewayRoutes(
1081
1081
  cors({
1082
1082
  origin: corsOrigins === '*' ? '*' : corsOrigins,
1083
1083
  allowMethods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
1084
- allowHeaders: ['Content-Type', 'Authorization'],
1084
+ allowHeaders: [
1085
+ 'Content-Type',
1086
+ 'Authorization',
1087
+ 'X-Syncular-Transport-Path',
1088
+ 'Baggage',
1089
+ 'Sentry-Trace',
1090
+ 'Traceparent',
1091
+ 'Tracestate',
1092
+ ],
1085
1093
  credentials: true,
1086
1094
  })
1087
1095
  );
@@ -7,3 +7,4 @@
7
7
  export * from './gateway';
8
8
  export * from './routes';
9
9
  export * from './schemas';
10
+ export * from './ui';
@@ -586,7 +586,15 @@ export function createConsoleRoutes<DB extends SyncCoreDb>(
586
586
  cors({
587
587
  origin: corsOrigins === '*' ? '*' : corsOrigins,
588
588
  allowMethods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
589
- allowHeaders: ['Content-Type', 'Authorization'],
589
+ allowHeaders: [
590
+ 'Content-Type',
591
+ 'Authorization',
592
+ 'X-Syncular-Transport-Path',
593
+ 'Baggage',
594
+ 'Sentry-Trace',
595
+ 'Traceparent',
596
+ 'Tracestate',
597
+ ],
590
598
  exposeHeaders: ['X-Total-Count'],
591
599
  credentials: true,
592
600
  })
@@ -0,0 +1,100 @@
1
+ import {
2
+ type ConsoleStaticResponder,
3
+ type ConsoleUiPrefill,
4
+ type CreateConsoleStaticResponderOptions,
5
+ createConsoleStaticResponder,
6
+ type ServeConsoleStaticRequestOptions,
7
+ } from '@syncular/console/server';
8
+ import type { Context, Hono } from 'hono';
9
+
10
+ type MaybePromise<T> = T | Promise<T>;
11
+
12
+ export interface MountConsoleUiOptions {
13
+ /**
14
+ * Browser mount path for the console UI. Defaults to `/console`.
15
+ */
16
+ mountPath?: string;
17
+ /**
18
+ * API base path used to prefill the console server URL.
19
+ * Defaults to `/api`.
20
+ */
21
+ apiBasePath?: string;
22
+ /**
23
+ * Resolve prefill values per request.
24
+ * Return `null`/`undefined` to keep defaults.
25
+ */
26
+ resolvePrefill?: (
27
+ c: Context
28
+ ) => MaybePromise<ConsoleUiPrefill | null | undefined>;
29
+ /**
30
+ * Convenience callback for prefilled token.
31
+ */
32
+ resolveToken?: (c: Context) => MaybePromise<string | undefined>;
33
+ /**
34
+ * Override distributable directory.
35
+ */
36
+ staticDir?: string;
37
+ /**
38
+ * Cache-Control header for index responses.
39
+ */
40
+ indexCacheControl?: string;
41
+ /**
42
+ * Cache-Control header for static asset responses.
43
+ */
44
+ assetCacheControl?: string;
45
+ }
46
+
47
+ type StaticResponderConfig = Pick<
48
+ CreateConsoleStaticResponderOptions,
49
+ 'mountPath' | 'staticDir' | 'indexCacheControl' | 'assetCacheControl'
50
+ >;
51
+
52
+ function normalizePath(pathname: string | undefined, fallback: string): string {
53
+ const value = pathname?.trim() ?? '';
54
+ if (!value) return fallback;
55
+ if (value === '/') return '/';
56
+ const withLeadingSlash = value.startsWith('/') ? value : `/${value}`;
57
+ return withLeadingSlash.replace(/\/+$/g, '') || '/';
58
+ }
59
+
60
+ export function mountConsoleUi(
61
+ app: Hono,
62
+ options: MountConsoleUiOptions = {}
63
+ ): void {
64
+ const mountPath = normalizePath(options.mountPath, '/console');
65
+ const apiBasePath = normalizePath(options.apiBasePath, '/api');
66
+
67
+ const staticResponderConfig: StaticResponderConfig = {
68
+ mountPath,
69
+ staticDir: options.staticDir,
70
+ indexCacheControl: options.indexCacheControl,
71
+ assetCacheControl: options.assetCacheControl,
72
+ };
73
+ const serveConsoleStatic: ConsoleStaticResponder =
74
+ createConsoleStaticResponder(staticResponderConfig);
75
+
76
+ const handler = async (c: Context) => {
77
+ const prefillFromResolver = await options.resolvePrefill?.(c);
78
+ const token = await options.resolveToken?.(c);
79
+ const origin = new URL(c.req.url).origin;
80
+
81
+ const prefill: ConsoleUiPrefill = {
82
+ basePath: mountPath,
83
+ serverUrl: `${origin}${apiBasePath}`,
84
+ ...prefillFromResolver,
85
+ };
86
+
87
+ if (token !== undefined) {
88
+ prefill.token = token;
89
+ }
90
+
91
+ const requestOptions: ServeConsoleStaticRequestOptions = { prefill };
92
+ const response = await serveConsoleStatic(c.req.raw, requestOptions);
93
+ if (!response) return c.notFound();
94
+ return response;
95
+ };
96
+
97
+ const wildcardPath = mountPath === '/' ? '/*' : `${mountPath}/*`;
98
+ app.get(mountPath, handler);
99
+ app.get(wildcardPath, handler);
100
+ }
package/src/routes.ts CHANGED
@@ -420,13 +420,13 @@ function emitConsoleLiveEvent(
420
420
  }
421
421
  | undefined,
422
422
  type: 'push' | 'pull' | 'commit' | 'client_update',
423
- data: Record<string, unknown>
423
+ data: Record<string, unknown> | (() => Record<string, unknown>)
424
424
  ): void {
425
425
  if (!emitter) return;
426
426
  emitter.emit({
427
427
  type,
428
428
  timestamp: new Date().toISOString(),
429
- data,
429
+ data: typeof data === 'function' ? data() : data,
430
430
  });
431
431
  }
432
432
 
@@ -453,6 +453,8 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
453
453
  const maxPullMaxSnapshotPages = config.maxPullMaxSnapshotPages ?? 10;
454
454
  const maxOperationsPerPush = config.maxOperationsPerPush ?? 200;
455
455
  const consoleLiveEmitter = options.consoleLiveEmitter;
456
+ const shouldEmitConsoleLiveEvents = consoleLiveEmitter !== undefined;
457
+ const shouldRecordRequestEvents = shouldEmitConsoleLiveEvents;
456
458
 
457
459
  // -------------------------------------------------------------------------
458
460
  // Optional WebSocket manager (scope-key based wake-ups)
@@ -611,13 +613,19 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
611
613
  `.execute(options.db);
612
614
  };
613
615
 
614
- const recordRequestEventInBackground = (event: RequestEvent): void => {
615
- void recordRequestEvent(event).catch((error) => {
616
+ const recordRequestEventInBackground = (
617
+ event: RequestEvent | (() => RequestEvent)
618
+ ): void => {
619
+ if (!shouldRecordRequestEvents) return;
620
+
621
+ const resolvedEvent = typeof event === 'function' ? event() : event;
622
+
623
+ void recordRequestEvent(resolvedEvent).catch((error) => {
616
624
  logAsyncFailureOnce('sync.request_event_record_failed', {
617
625
  event: 'sync.request_event_record_failed',
618
- userId: event.actorId,
619
- clientId: event.clientId,
620
- requestEventType: event.eventType,
626
+ userId: resolvedEvent.actorId,
627
+ clientId: resolvedEvent.clientId,
628
+ requestEventType: resolvedEvent.eventType,
621
629
  error: error instanceof Error ? error.message : String(error),
622
630
  });
623
631
  });
@@ -761,7 +769,8 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
761
769
 
762
770
  // --- Push phase ---
763
771
  if (body.push) {
764
- const pushOps = body.push.operations ?? [];
772
+ const pushBody = body.push;
773
+ const pushOps = pushBody.operations ?? [];
765
774
  if (pushOps.length > maxOperationsPerPush) {
766
775
  return c.json(
767
776
  {
@@ -782,9 +791,9 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
782
791
  partitionId,
783
792
  request: {
784
793
  clientId,
785
- clientCommitId: body.push.clientCommitId,
786
- operations: body.push.operations,
787
- schemaVersion: body.push.schemaVersion,
794
+ clientCommitId: pushBody.clientCommitId,
795
+ operations: pushBody.operations,
796
+ schemaVersion: pushBody.schemaVersion,
788
797
  },
789
798
  });
790
799
 
@@ -799,7 +808,7 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
799
808
  commitSeq: pushed.response.commitSeq,
800
809
  });
801
810
 
802
- recordRequestEventInBackground({
811
+ recordRequestEventInBackground(() => ({
803
812
  partitionId,
804
813
  requestId,
805
814
  traceId: traceContext.traceId,
@@ -820,14 +829,14 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
820
829
  payloadSnapshot: {
821
830
  request: {
822
831
  clientId,
823
- clientCommitId: body.push.clientCommitId,
824
- schemaVersion: body.push.schemaVersion,
825
- operations: body.push.operations,
832
+ clientCommitId: pushBody.clientCommitId,
833
+ schemaVersion: pushBody.schemaVersion,
834
+ operations: pushBody.operations,
826
835
  },
827
836
  response: pushed.response,
828
837
  },
829
- });
830
- emitConsoleLiveEvent(consoleLiveEmitter, 'push', {
838
+ }));
839
+ emitConsoleLiveEvent(consoleLiveEmitter, 'push', () => ({
831
840
  partitionId,
832
841
  requestId,
833
842
  traceId: traceContext.traceId,
@@ -842,7 +851,7 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
842
851
  commitSeq: pushed.response.commitSeq ?? null,
843
852
  operationCount: pushOps.length,
844
853
  tables: pushed.affectedTables,
845
- });
854
+ }));
846
855
 
847
856
  // WS notifications
848
857
  if (
@@ -895,13 +904,13 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
895
904
  pushed.response.status === 'applied' &&
896
905
  typeof pushed.response.commitSeq === 'number'
897
906
  ) {
898
- emitConsoleLiveEvent(consoleLiveEmitter, 'commit', {
907
+ emitConsoleLiveEvent(consoleLiveEmitter, 'commit', () => ({
899
908
  partitionId,
900
909
  commitSeq: pushed.response.commitSeq,
901
910
  actorId: auth.actorId,
902
911
  clientId,
903
912
  affectedTables: pushed.affectedTables,
904
- });
913
+ }));
905
914
  }
906
915
 
907
916
  pushResponse = pushed.response;
@@ -947,7 +956,7 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
947
956
  maxPullLimitSnapshotRows
948
957
  ),
949
958
  maxSnapshotPages: clampInt(
950
- body.pull.maxSnapshotPages ?? 1,
959
+ body.pull.maxSnapshotPages ?? 4,
951
960
  1,
952
961
  maxPullMaxSnapshotPages
953
962
  ),
@@ -994,13 +1003,13 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
994
1003
  effectiveScopes: pullResult.effectiveScopes,
995
1004
  })
996
1005
  .then(() => {
997
- emitConsoleLiveEvent(consoleLiveEmitter, 'client_update', {
1006
+ emitConsoleLiveEvent(consoleLiveEmitter, 'client_update', () => ({
998
1007
  action: 'cursor_recorded',
999
1008
  partitionId,
1000
1009
  actorId: auth.actorId,
1001
1010
  clientId,
1002
1011
  cursor: pullResult.clientCursor,
1003
- });
1012
+ }));
1004
1013
  })
1005
1014
  .catch((error) => {
1006
1015
  logAsyncFailureOnce('sync.client_cursor_record_failed', {
@@ -1029,56 +1038,73 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1029
1038
  clientCursor: pullResult.clientCursor,
1030
1039
  });
1031
1040
 
1032
- recordRequestEventInBackground({
1033
- partitionId,
1034
- requestId,
1035
- traceId: traceContext.traceId,
1036
- spanId: traceContext.spanId,
1037
- eventType: 'pull',
1038
- syncPath: 'http-combined',
1039
- actorId: auth.actorId,
1040
- clientId,
1041
- transportPath: readTransportPath(c),
1042
- statusCode: 200,
1043
- outcome: 'applied',
1044
- responseStatus: normalizeResponseStatus(200, 'applied'),
1045
- durationMs: pullDurationMs,
1046
- rowCount: countPullRows(pullResult.response),
1047
- subscriptionCount: request.subscriptions.length,
1048
- scopesSummary: summarizeScopeValues(pullResult.effectiveScopes),
1049
- payloadSnapshot: {
1050
- request: {
1051
- clientId,
1052
- limitCommits: request.limitCommits,
1053
- limitSnapshotRows: request.limitSnapshotRows,
1054
- maxSnapshotPages: request.maxSnapshotPages,
1055
- dedupeRows: request.dedupeRows,
1056
- subscriptions: request.subscriptions.map((subscription) => ({
1057
- id: subscription.id,
1058
- table: subscription.table,
1059
- scopes: subscription.scopes,
1060
- cursor: subscription.cursor,
1061
- bootstrapState: subscription.bootstrapState,
1062
- })),
1063
- },
1064
- response: summarizePullResponse(pullResult.response),
1065
- },
1041
+ recordRequestEventInBackground(() => {
1042
+ const pullRowCount = shouldRecordRequestEvents
1043
+ ? countPullRows(pullResult.response)
1044
+ : null;
1045
+ const scopesSummary = shouldRecordRequestEvents
1046
+ ? summarizeScopeValues(pullResult.effectiveScopes)
1047
+ : null;
1048
+ const payloadSnapshot = shouldRecordRequestEvents
1049
+ ? {
1050
+ request: {
1051
+ clientId,
1052
+ limitCommits: request.limitCommits,
1053
+ limitSnapshotRows: request.limitSnapshotRows,
1054
+ maxSnapshotPages: request.maxSnapshotPages,
1055
+ dedupeRows: request.dedupeRows,
1056
+ subscriptions: request.subscriptions.map((subscription) => ({
1057
+ id: subscription.id,
1058
+ table: subscription.table,
1059
+ scopes: subscription.scopes,
1060
+ cursor: subscription.cursor,
1061
+ bootstrapState: subscription.bootstrapState,
1062
+ })),
1063
+ },
1064
+ response: summarizePullResponse(pullResult.response),
1065
+ }
1066
+ : null;
1067
+
1068
+ return {
1069
+ partitionId,
1070
+ requestId,
1071
+ traceId: traceContext.traceId,
1072
+ spanId: traceContext.spanId,
1073
+ eventType: 'pull',
1074
+ syncPath: 'http-combined',
1075
+ actorId: auth.actorId,
1076
+ clientId,
1077
+ transportPath: readTransportPath(c),
1078
+ statusCode: 200,
1079
+ outcome: 'applied',
1080
+ responseStatus: normalizeResponseStatus(200, 'applied'),
1081
+ durationMs: pullDurationMs,
1082
+ rowCount: pullRowCount,
1083
+ subscriptionCount: request.subscriptions.length,
1084
+ scopesSummary,
1085
+ payloadSnapshot,
1086
+ };
1066
1087
  });
1067
- emitConsoleLiveEvent(consoleLiveEmitter, 'pull', {
1068
- partitionId,
1069
- requestId,
1070
- traceId: traceContext.traceId,
1071
- spanId: traceContext.spanId,
1072
- actorId: auth.actorId,
1073
- clientId,
1074
- transportPath: readTransportPath(c),
1075
- syncPath: 'http-combined',
1076
- outcome: 'applied',
1077
- statusCode: 200,
1078
- durationMs: pullDurationMs,
1079
- rowCount: countPullRows(pullResult.response),
1080
- subscriptionCount: request.subscriptions.length,
1081
- clientCursor: pullResult.clientCursor,
1088
+ emitConsoleLiveEvent(consoleLiveEmitter, 'pull', () => {
1089
+ const pullRowCount = shouldEmitConsoleLiveEvents
1090
+ ? countPullRows(pullResult.response)
1091
+ : null;
1092
+ return {
1093
+ partitionId,
1094
+ requestId,
1095
+ traceId: traceContext.traceId,
1096
+ spanId: traceContext.spanId,
1097
+ actorId: auth.actorId,
1098
+ clientId,
1099
+ transportPath: readTransportPath(c),
1100
+ syncPath: 'http-combined',
1101
+ outcome: 'applied',
1102
+ statusCode: 200,
1103
+ durationMs: pullDurationMs,
1104
+ rowCount: pullRowCount,
1105
+ subscriptionCount: request.subscriptions.length,
1106
+ clientCursor: pullResult.clientCursor,
1107
+ };
1082
1108
  });
1083
1109
 
1084
1110
  pullResponse = pullResult.response;
@@ -1309,14 +1335,14 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1309
1335
 
1310
1336
  unregister = wsConnectionManager.register(conn, initialScopeKeys);
1311
1337
  conn.sendHeartbeat();
1312
- emitConsoleLiveEvent(consoleLiveEmitter, 'client_update', {
1338
+ emitConsoleLiveEvent(consoleLiveEmitter, 'client_update', () => ({
1313
1339
  action: 'realtime_connected',
1314
1340
  actorId: auth.actorId,
1315
1341
  clientId,
1316
1342
  partitionId,
1317
1343
  transportPath: realtimeTransportPath,
1318
1344
  scopeCount: initialScopeKeys.length,
1319
- });
1345
+ }));
1320
1346
  },
1321
1347
  onClose(_evt, _ws) {
1322
1348
  unregister?.();
@@ -1326,12 +1352,12 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1326
1352
  event: 'sync.realtime.disconnect',
1327
1353
  userId: auth.actorId,
1328
1354
  });
1329
- emitConsoleLiveEvent(consoleLiveEmitter, 'client_update', {
1355
+ emitConsoleLiveEvent(consoleLiveEmitter, 'client_update', () => ({
1330
1356
  action: 'realtime_disconnected',
1331
1357
  actorId: auth.actorId,
1332
1358
  clientId,
1333
1359
  partitionId,
1334
- });
1360
+ }));
1335
1361
  },
1336
1362
  onError(_evt, _ws) {
1337
1363
  unregister?.();
@@ -1341,12 +1367,12 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1341
1367
  event: 'sync.realtime.disconnect',
1342
1368
  userId: auth.actorId,
1343
1369
  });
1344
- emitConsoleLiveEvent(consoleLiveEmitter, 'client_update', {
1370
+ emitConsoleLiveEvent(consoleLiveEmitter, 'client_update', () => ({
1345
1371
  action: 'realtime_error',
1346
1372
  actorId: auth.actorId,
1347
1373
  clientId,
1348
1374
  partitionId,
1349
- });
1375
+ }));
1350
1376
  },
1351
1377
  onMessage(evt, _ws) {
1352
1378
  if (!connRef) return;
@@ -1479,7 +1505,7 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1479
1505
  { opIndex: 0, status: 'error', error: 'Invalid push payload' },
1480
1506
  ],
1481
1507
  });
1482
- recordRequestEventInBackground({
1508
+ recordRequestEventInBackground(() => ({
1483
1509
  partitionId,
1484
1510
  requestId,
1485
1511
  traceId: traceContext.traceId,
@@ -1503,8 +1529,8 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1503
1529
  reason: 'invalid_push_payload',
1504
1530
  },
1505
1531
  },
1506
- });
1507
- emitConsoleLiveEvent(consoleLiveEmitter, 'push', {
1532
+ }));
1533
+ emitConsoleLiveEvent(consoleLiveEmitter, 'push', () => ({
1508
1534
  partitionId,
1509
1535
  requestId,
1510
1536
  traceId: traceContext.traceId,
@@ -1517,7 +1543,7 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1517
1543
  statusCode: 400,
1518
1544
  durationMs: invalidDurationMs,
1519
1545
  errorCode: 'INVALID_PUSH_PAYLOAD',
1520
- });
1546
+ }));
1521
1547
  return;
1522
1548
  }
1523
1549
 
@@ -1536,7 +1562,7 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1536
1562
  },
1537
1563
  ],
1538
1564
  });
1539
- recordRequestEventInBackground({
1565
+ recordRequestEventInBackground(() => ({
1540
1566
  partitionId,
1541
1567
  requestId,
1542
1568
  traceId: traceContext.traceId,
@@ -1566,8 +1592,8 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1566
1592
  reason: 'max_operations_exceeded',
1567
1593
  },
1568
1594
  },
1569
- });
1570
- emitConsoleLiveEvent(consoleLiveEmitter, 'push', {
1595
+ }));
1596
+ emitConsoleLiveEvent(consoleLiveEmitter, 'push', () => ({
1571
1597
  partitionId,
1572
1598
  requestId,
1573
1599
  traceId: traceContext.traceId,
@@ -1581,7 +1607,7 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1581
1607
  durationMs: rejectedDurationMs,
1582
1608
  operationCount: pushOps.length,
1583
1609
  errorCode: 'MAX_OPERATIONS_EXCEEDED',
1584
- });
1610
+ }));
1585
1611
  return;
1586
1612
  }
1587
1613
 
@@ -1610,7 +1636,7 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1610
1636
  commitSeq: pushed.response.commitSeq,
1611
1637
  });
1612
1638
 
1613
- recordRequestEventInBackground({
1639
+ recordRequestEventInBackground(() => ({
1614
1640
  partitionId,
1615
1641
  requestId,
1616
1642
  traceId: traceContext.traceId,
@@ -1637,8 +1663,8 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1637
1663
  },
1638
1664
  response: pushed.response,
1639
1665
  },
1640
- });
1641
- emitConsoleLiveEvent(consoleLiveEmitter, 'push', {
1666
+ }));
1667
+ emitConsoleLiveEvent(consoleLiveEmitter, 'push', () => ({
1642
1668
  partitionId,
1643
1669
  requestId,
1644
1670
  traceId: traceContext.traceId,
@@ -1653,7 +1679,7 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1653
1679
  commitSeq: pushed.response.commitSeq ?? null,
1654
1680
  operationCount: pushOps.length,
1655
1681
  tables: pushed.affectedTables,
1656
- });
1682
+ }));
1657
1683
 
1658
1684
  // WS notifications to other clients
1659
1685
  if (
@@ -1702,13 +1728,13 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1702
1728
  pushed.response.status === 'applied' &&
1703
1729
  typeof pushed.response.commitSeq === 'number'
1704
1730
  ) {
1705
- emitConsoleLiveEvent(consoleLiveEmitter, 'commit', {
1731
+ emitConsoleLiveEvent(consoleLiveEmitter, 'commit', () => ({
1706
1732
  partitionId,
1707
1733
  commitSeq: pushed.response.commitSeq,
1708
1734
  actorId,
1709
1735
  clientId,
1710
1736
  affectedTables: pushed.affectedTables,
1711
- });
1737
+ }));
1712
1738
  }
1713
1739
 
1714
1740
  conn.sendPushResponse({
@@ -1729,7 +1755,7 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1729
1755
  });
1730
1756
  const message =
1731
1757
  err instanceof Error ? err.message : 'Internal server error';
1732
- recordRequestEventInBackground({
1758
+ recordRequestEventInBackground(() => ({
1733
1759
  partitionId,
1734
1760
  requestId,
1735
1761
  traceId: traceContext.traceId,
@@ -1754,8 +1780,8 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1754
1780
  message,
1755
1781
  },
1756
1782
  },
1757
- });
1758
- emitConsoleLiveEvent(consoleLiveEmitter, 'push', {
1783
+ }));
1784
+ emitConsoleLiveEvent(consoleLiveEmitter, 'push', () => ({
1759
1785
  partitionId,
1760
1786
  requestId,
1761
1787
  traceId: traceContext.traceId,
@@ -1768,7 +1794,7 @@ export function createSyncRoutes<DB extends SyncCoreDb = SyncCoreDb>(
1768
1794
  statusCode: 500,
1769
1795
  durationMs: failedDurationMs,
1770
1796
  errorCode: 'INTERNAL_SERVER_ERROR',
1771
- });
1797
+ }));
1772
1798
  conn.sendPushResponse({
1773
1799
  requestId,
1774
1800
  ok: false,