@syncular/server-hono 0.0.4-26 → 0.0.6-101
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/console/gateway.d.ts +3 -1
- package/dist/console/gateway.d.ts.map +1 -1
- package/dist/console/gateway.js +218 -41
- package/dist/console/gateway.js.map +1 -1
- package/dist/console/index.d.ts +1 -0
- package/dist/console/index.d.ts.map +1 -1
- package/dist/console/index.js +1 -0
- package/dist/console/index.js.map +1 -1
- package/dist/console/routes.d.ts +3 -97
- package/dist/console/routes.d.ts.map +1 -1
- package/dist/console/routes.js +507 -80
- package/dist/console/routes.js.map +1 -1
- package/dist/console/schemas.d.ts +29 -0
- package/dist/console/schemas.d.ts.map +1 -1
- package/dist/console/schemas.js +22 -0
- package/dist/console/schemas.js.map +1 -1
- package/dist/console/types.d.ts +175 -0
- package/dist/console/types.d.ts.map +1 -0
- package/dist/console/types.js +2 -0
- package/dist/console/types.js.map +1 -0
- package/dist/create-server.d.ts +17 -34
- package/dist/create-server.d.ts.map +1 -1
- package/dist/create-server.js +26 -26
- package/dist/create-server.js.map +1 -1
- package/dist/proxy/connection-manager.d.ts +3 -3
- package/dist/proxy/connection-manager.d.ts.map +1 -1
- package/dist/proxy/routes.d.ts +4 -4
- package/dist/proxy/routes.d.ts.map +1 -1
- package/dist/proxy/routes.js +1 -1
- package/dist/routes.d.ts +33 -9
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +153 -70
- package/dist/routes.js.map +1 -1
- package/package.json +21 -7
- package/src/__tests__/blob-routes.test.ts +424 -0
- package/src/__tests__/console-gateway-live-routes.test.ts +54 -3
- package/src/__tests__/console-routes.test.ts +161 -7
- package/src/__tests__/console-ui.test.ts +114 -0
- package/src/__tests__/create-server.test.ts +233 -10
- package/src/__tests__/pull-chunk-storage.test.ts +6 -2
- package/src/__tests__/realtime-bridge.test.ts +6 -2
- package/src/__tests__/sync-rate-limit-routing.test.ts +6 -2
- package/src/console/gateway.ts +277 -53
- package/src/console/index.ts +1 -0
- package/src/console/routes.ts +654 -198
- package/src/console/schemas.ts +29 -0
- package/src/console/types.ts +185 -0
- package/src/create-server.ts +56 -53
- package/src/proxy/connection-manager.ts +3 -3
- package/src/proxy/routes.ts +4 -4
- package/src/routes.ts +225 -96
package/src/console/schemas.ts
CHANGED
|
@@ -403,3 +403,32 @@ export const LiveEventSchema = z.object({
|
|
|
403
403
|
});
|
|
404
404
|
|
|
405
405
|
export type LiveEvent = z.infer<typeof LiveEventSchema>;
|
|
406
|
+
|
|
407
|
+
// ---------------------------------------------------------------------------
|
|
408
|
+
// Blob storage
|
|
409
|
+
// ---------------------------------------------------------------------------
|
|
410
|
+
|
|
411
|
+
export const ConsoleBlobSchema = z.object({
|
|
412
|
+
key: z.string(),
|
|
413
|
+
size: z.number().int(),
|
|
414
|
+
uploaded: z.string(),
|
|
415
|
+
httpMetadata: z.object({ contentType: z.string().optional() }).optional(),
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
export type ConsoleBlob = z.infer<typeof ConsoleBlobSchema>;
|
|
419
|
+
|
|
420
|
+
export const ConsoleBlobListQuerySchema = z.object({
|
|
421
|
+
prefix: z.string().optional(),
|
|
422
|
+
cursor: z.string().optional(),
|
|
423
|
+
limit: z.coerce.number().int().min(1).max(1000).default(100),
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
export const ConsoleBlobListResponseSchema = z.object({
|
|
427
|
+
items: z.array(ConsoleBlobSchema),
|
|
428
|
+
truncated: z.boolean(),
|
|
429
|
+
cursor: z.string().nullable(),
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
export const ConsoleBlobDeleteResponseSchema = z.object({
|
|
433
|
+
deleted: z.boolean(),
|
|
434
|
+
});
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ServerSyncDialect,
|
|
3
|
+
ServerTableHandler,
|
|
4
|
+
SqlFamily,
|
|
5
|
+
SyncCoreDb,
|
|
6
|
+
SyncServerAuth,
|
|
7
|
+
} from '@syncular/server';
|
|
8
|
+
import type { Context } from 'hono';
|
|
9
|
+
import type { UpgradeWebSocket } from 'hono/ws';
|
|
10
|
+
import type { Kysely } from 'kysely';
|
|
11
|
+
import type { WebSocketConnectionManager } from '../ws';
|
|
12
|
+
import type { LiveEvent } from './schemas';
|
|
13
|
+
|
|
14
|
+
export interface ConsoleAuthResult {
|
|
15
|
+
/** Identifier for the console user (for audit logging). */
|
|
16
|
+
consoleUserId?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Listener for console live events (SSE streaming).
|
|
21
|
+
*/
|
|
22
|
+
export type ConsoleEventListener = (event: LiveEvent) => void;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Console event emitter for broadcasting live events.
|
|
26
|
+
*/
|
|
27
|
+
export interface ConsoleEventEmitter {
|
|
28
|
+
/** Add a listener for live events */
|
|
29
|
+
addListener(listener: ConsoleEventListener): void;
|
|
30
|
+
/** Remove a listener */
|
|
31
|
+
removeListener(listener: ConsoleEventListener): void;
|
|
32
|
+
/** Emit an event to all listeners */
|
|
33
|
+
emit(event: LiveEvent): void;
|
|
34
|
+
/**
|
|
35
|
+
* Replay recent events, optionally constrained by timestamp, partition, and max count.
|
|
36
|
+
*/
|
|
37
|
+
replay(options?: {
|
|
38
|
+
since?: string;
|
|
39
|
+
limit?: number;
|
|
40
|
+
partitionId?: string;
|
|
41
|
+
}): LiveEvent[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface ConsoleMetricsOptions {
|
|
45
|
+
/**
|
|
46
|
+
* Metrics query strategy for timeseries/latency endpoints.
|
|
47
|
+
* - raw: in-memory processing from raw event rows
|
|
48
|
+
* - aggregated: DB-level aggregation where supported (raw fallback for unsupported paths)
|
|
49
|
+
* - auto: use raw for small windows, aggregated for larger windows
|
|
50
|
+
*/
|
|
51
|
+
aggregationMode?: 'auto' | 'raw' | 'aggregated';
|
|
52
|
+
/** Max events for using raw mode when aggregationMode is 'auto'. */
|
|
53
|
+
rawFallbackMaxEvents?: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface ConsoleMaintenanceOptions {
|
|
57
|
+
/**
|
|
58
|
+
* Minimum interval between automatic event-prune runs.
|
|
59
|
+
* Set to 0 to disable automatic pruning.
|
|
60
|
+
* Default: 5 minutes.
|
|
61
|
+
*/
|
|
62
|
+
autoPruneIntervalMs?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Max age for request events before pruning.
|
|
65
|
+
* Set to 0 to disable age-based pruning.
|
|
66
|
+
* Default: 7 days.
|
|
67
|
+
*/
|
|
68
|
+
requestEventsMaxAgeMs?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Max number of request events to retain.
|
|
71
|
+
* Set to 0 to disable count-based pruning.
|
|
72
|
+
* Default: 10000.
|
|
73
|
+
*/
|
|
74
|
+
requestEventsMaxRows?: number;
|
|
75
|
+
/**
|
|
76
|
+
* Max age for operation audit events before pruning.
|
|
77
|
+
* Set to 0 to disable age-based pruning.
|
|
78
|
+
* Default: 30 days.
|
|
79
|
+
*/
|
|
80
|
+
operationEventsMaxAgeMs?: number;
|
|
81
|
+
/**
|
|
82
|
+
* Max number of operation audit events to retain.
|
|
83
|
+
* Set to 0 to disable count-based pruning.
|
|
84
|
+
* Default: 5000.
|
|
85
|
+
*/
|
|
86
|
+
operationEventsMaxRows?: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface ConsoleBlobObject {
|
|
90
|
+
key: string;
|
|
91
|
+
size: number;
|
|
92
|
+
uploaded: Date;
|
|
93
|
+
httpMetadata?: { contentType?: string };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface ConsoleBlobGetResult {
|
|
97
|
+
body: ReadableStream;
|
|
98
|
+
size: number;
|
|
99
|
+
httpMetadata?: { contentType?: string };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface ConsoleBlobHeadResult {
|
|
103
|
+
size: number;
|
|
104
|
+
httpMetadata?: { contentType?: string };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface ConsoleBlobBucket {
|
|
108
|
+
list(options: { prefix?: string; cursor?: string; limit?: number }): Promise<{
|
|
109
|
+
objects: ConsoleBlobObject[];
|
|
110
|
+
truncated: boolean;
|
|
111
|
+
cursor?: string;
|
|
112
|
+
}>;
|
|
113
|
+
get(key: string): Promise<ConsoleBlobGetResult | null>;
|
|
114
|
+
delete(key: string | string[]): Promise<void>;
|
|
115
|
+
head(key: string): Promise<ConsoleBlobHeadResult | null>;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface ConsoleSharedOptions {
|
|
119
|
+
/**
|
|
120
|
+
* CORS origins to allow. Defaults to ['http://localhost:5173', 'https://console.sync.dev'].
|
|
121
|
+
* Set to '*' to allow all origins (not recommended for production).
|
|
122
|
+
*/
|
|
123
|
+
corsOrigins?: string[] | '*';
|
|
124
|
+
metrics?: ConsoleMetricsOptions;
|
|
125
|
+
maintenance?: ConsoleMaintenanceOptions;
|
|
126
|
+
blobBucket?: ConsoleBlobBucket;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface CreateConsoleRoutesOptions<
|
|
130
|
+
DB extends SyncCoreDb = SyncCoreDb,
|
|
131
|
+
Auth extends SyncServerAuth = SyncServerAuth,
|
|
132
|
+
F extends SqlFamily = SqlFamily,
|
|
133
|
+
> extends ConsoleSharedOptions {
|
|
134
|
+
db: Kysely<DB>;
|
|
135
|
+
dialect: ServerSyncDialect<F>;
|
|
136
|
+
handlers: ServerTableHandler<DB, Auth>[];
|
|
137
|
+
/**
|
|
138
|
+
* Authentication function for console requests.
|
|
139
|
+
* Return null to reject the request.
|
|
140
|
+
*/
|
|
141
|
+
authenticate: (c: Context) => Promise<ConsoleAuthResult | null>;
|
|
142
|
+
/**
|
|
143
|
+
* Compaction options (required for /compact endpoint).
|
|
144
|
+
*/
|
|
145
|
+
compact?: {
|
|
146
|
+
fullHistoryHours?: number;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Pruning options.
|
|
150
|
+
*/
|
|
151
|
+
prune?: {
|
|
152
|
+
activeWindowMs?: number;
|
|
153
|
+
fallbackMaxAgeMs?: number;
|
|
154
|
+
keepNewestCommits?: number;
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* Event emitter for live console events.
|
|
158
|
+
* If provided along with websocket config, enables the /events/live WebSocket endpoint.
|
|
159
|
+
*/
|
|
160
|
+
eventEmitter?: ConsoleEventEmitter;
|
|
161
|
+
/**
|
|
162
|
+
* Shared sync WebSocket connection manager.
|
|
163
|
+
* When provided, `/clients` includes realtime connection state per client.
|
|
164
|
+
*/
|
|
165
|
+
wsConnectionManager?: WebSocketConnectionManager;
|
|
166
|
+
/**
|
|
167
|
+
* WebSocket configuration for live events streaming.
|
|
168
|
+
*/
|
|
169
|
+
websocket?: {
|
|
170
|
+
enabled?: boolean;
|
|
171
|
+
/**
|
|
172
|
+
* Runtime-provided WebSocket upgrader (e.g. from `hono/bun`'s `createBunWebSocket()`).
|
|
173
|
+
*/
|
|
174
|
+
upgradeWebSocket?: UpgradeWebSocket;
|
|
175
|
+
/**
|
|
176
|
+
* Heartbeat interval in milliseconds. Default: 30000
|
|
177
|
+
*/
|
|
178
|
+
heartbeatIntervalMs?: number;
|
|
179
|
+
};
|
|
180
|
+
/**
|
|
181
|
+
* Optional console schema readiness promise.
|
|
182
|
+
* When provided, routes wait for this promise before querying console tables.
|
|
183
|
+
*/
|
|
184
|
+
consoleSchemaReady?: Promise<void>;
|
|
185
|
+
}
|
package/src/create-server.ts
CHANGED
|
@@ -2,25 +2,29 @@
|
|
|
2
2
|
* Simplified server factory for Hono
|
|
3
3
|
*
|
|
4
4
|
* Breaking changes from legacy createSyncRoutes:
|
|
5
|
-
* -
|
|
5
|
+
* - sync contract instead of top-level handlers/authenticate
|
|
6
6
|
* - Combined sync + console routes in one call
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type {
|
|
10
|
+
ScopeCacheBackend,
|
|
11
|
+
ServerSyncConfig,
|
|
10
12
|
ServerSyncDialect,
|
|
11
|
-
ServerTableHandler,
|
|
12
13
|
SnapshotChunkStorage,
|
|
14
|
+
SqlFamily,
|
|
13
15
|
SyncCoreDb,
|
|
14
16
|
} from '@syncular/server';
|
|
15
|
-
import type { Context } from 'hono';
|
|
16
17
|
import type { UpgradeWebSocket } from 'hono/ws';
|
|
17
18
|
import type { Kysely } from 'kysely';
|
|
18
19
|
import {
|
|
19
|
-
type ConsoleEventEmitter,
|
|
20
20
|
createConsoleEventEmitter,
|
|
21
21
|
createConsoleRoutes,
|
|
22
22
|
createTokenAuthenticator,
|
|
23
|
-
} from './console';
|
|
23
|
+
} from './console/routes';
|
|
24
|
+
import type {
|
|
25
|
+
ConsoleEventEmitter,
|
|
26
|
+
ConsoleSharedOptions,
|
|
27
|
+
} from './console/types';
|
|
24
28
|
import {
|
|
25
29
|
createSyncRoutes,
|
|
26
30
|
getSyncWebSocketConnectionManager,
|
|
@@ -28,26 +32,28 @@ import {
|
|
|
28
32
|
type SyncRoutesConfigWithRateLimit,
|
|
29
33
|
} from './routes';
|
|
30
34
|
|
|
31
|
-
export interface SyncServerOptions<
|
|
35
|
+
export interface SyncServerOptions<
|
|
36
|
+
DB extends SyncCoreDb = SyncCoreDb,
|
|
37
|
+
Auth extends SyncAuthResult = SyncAuthResult,
|
|
38
|
+
F extends SqlFamily = SqlFamily,
|
|
39
|
+
> {
|
|
32
40
|
/** Kysely database instance */
|
|
33
41
|
db: Kysely<DB>;
|
|
34
42
|
|
|
35
43
|
/** Server sync dialect */
|
|
36
|
-
dialect: ServerSyncDialect
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Table handlers for sync operations.
|
|
40
|
-
*/
|
|
41
|
-
handlers: ServerTableHandler<DB>[];
|
|
44
|
+
dialect: ServerSyncDialect<F>;
|
|
42
45
|
|
|
43
|
-
/**
|
|
44
|
-
|
|
46
|
+
/** Sync contract with auth + table handlers */
|
|
47
|
+
sync: ServerSyncConfig<DB, Auth>;
|
|
45
48
|
|
|
46
49
|
/** Snapshot chunk storage (external body storage, e.g. R2/S3) */
|
|
47
50
|
chunkStorage?: SnapshotChunkStorage;
|
|
48
51
|
|
|
52
|
+
/** Scope cache backend for resolveScopes() results */
|
|
53
|
+
scopeCache?: ScopeCacheBackend;
|
|
54
|
+
|
|
49
55
|
/** Sync route configuration */
|
|
50
|
-
|
|
56
|
+
routes?: SyncRoutesConfigWithRateLimit;
|
|
51
57
|
|
|
52
58
|
/** WebSocket upgrader for realtime */
|
|
53
59
|
upgradeWebSocket?: UpgradeWebSocket;
|
|
@@ -58,17 +64,10 @@ export interface SyncServerOptions<DB extends SyncCoreDb = SyncCoreDb> {
|
|
|
58
64
|
*/
|
|
59
65
|
console?:
|
|
60
66
|
| false
|
|
61
|
-
| {
|
|
67
|
+
| ({
|
|
62
68
|
/** Console bearer token for authentication (required unless SYNC_CONSOLE_TOKEN is set) */
|
|
63
69
|
token?: string;
|
|
64
|
-
|
|
65
|
-
corsOrigins?: '*' | string[];
|
|
66
|
-
/** Metrics aggregation strategy for console stats endpoints */
|
|
67
|
-
metrics?: {
|
|
68
|
-
aggregationMode?: 'auto' | 'raw' | 'aggregated';
|
|
69
|
-
rawFallbackMaxEvents?: number;
|
|
70
|
-
};
|
|
71
|
-
};
|
|
70
|
+
} & ConsoleSharedOptions);
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
export interface SyncServerResult {
|
|
@@ -85,45 +84,39 @@ export interface SyncServerResult {
|
|
|
85
84
|
*
|
|
86
85
|
* @example
|
|
87
86
|
* ```typescript
|
|
88
|
-
* // With
|
|
87
|
+
* // With sync contract
|
|
89
88
|
* const { syncRoutes } = createSyncServer({
|
|
90
89
|
* db,
|
|
91
90
|
* dialect,
|
|
92
|
-
*
|
|
93
|
-
* authenticate: async (c) => {
|
|
94
|
-
* const userId = c.req.header('x-user-id');
|
|
95
|
-
* return userId ? { actorId: userId } : null;
|
|
96
|
-
* },
|
|
91
|
+
* sync,
|
|
97
92
|
* });
|
|
98
93
|
*
|
|
99
94
|
* // With custom handlers
|
|
100
95
|
* const { syncRoutes, consoleRoutes } = createSyncServer({
|
|
101
96
|
* db,
|
|
102
97
|
* dialect,
|
|
103
|
-
*
|
|
104
|
-
* authenticate: async (c) => {
|
|
105
|
-
* const userId = c.req.header('x-user-id');
|
|
106
|
-
* return userId ? { actorId: userId } : null;
|
|
107
|
-
* },
|
|
98
|
+
* sync,
|
|
108
99
|
* console: { token: process.env.CONSOLE_TOKEN },
|
|
109
100
|
* });
|
|
110
101
|
* ```
|
|
111
102
|
*/
|
|
112
|
-
export function createSyncServer<
|
|
113
|
-
|
|
114
|
-
|
|
103
|
+
export function createSyncServer<
|
|
104
|
+
DB extends SyncCoreDb = SyncCoreDb,
|
|
105
|
+
Auth extends SyncAuthResult = SyncAuthResult,
|
|
106
|
+
F extends SqlFamily = SqlFamily,
|
|
107
|
+
>(options: SyncServerOptions<DB, Auth, F>): SyncServerResult {
|
|
115
108
|
const {
|
|
116
109
|
db,
|
|
117
110
|
dialect,
|
|
118
|
-
handlers,
|
|
119
|
-
authenticate,
|
|
120
|
-
chunkStorage,
|
|
121
111
|
sync,
|
|
112
|
+
chunkStorage,
|
|
113
|
+
scopeCache,
|
|
114
|
+
routes,
|
|
122
115
|
upgradeWebSocket,
|
|
123
116
|
console: consoleConfig,
|
|
124
117
|
} = options;
|
|
125
118
|
|
|
126
|
-
if (handlers.length === 0) {
|
|
119
|
+
if (sync.handlers.length === 0) {
|
|
127
120
|
throw new Error('At least one handler must be provided');
|
|
128
121
|
}
|
|
129
122
|
|
|
@@ -145,29 +138,36 @@ export function createSyncServer<DB extends SyncCoreDb = SyncCoreDb>(
|
|
|
145
138
|
const consoleEventEmitter = isConsoleEnabled
|
|
146
139
|
? createConsoleEventEmitter()
|
|
147
140
|
: undefined;
|
|
141
|
+
const consoleSchemaReady =
|
|
142
|
+
isConsoleEnabled && dialect.ensureConsoleSchema
|
|
143
|
+
? dialect.ensureConsoleSchema(db)
|
|
144
|
+
: undefined;
|
|
148
145
|
|
|
149
146
|
// Create sync routes
|
|
150
147
|
const syncRoutes = createSyncRoutes({
|
|
151
148
|
db,
|
|
152
149
|
dialect,
|
|
153
|
-
handlers,
|
|
154
|
-
authenticate
|
|
150
|
+
handlers: sync.handlers,
|
|
151
|
+
authenticate: async (context): Promise<Auth | null> =>
|
|
152
|
+
sync.authenticate(context.req.raw),
|
|
155
153
|
chunkStorage,
|
|
154
|
+
scopeCache,
|
|
156
155
|
consoleLiveEmitter: consoleEventEmitter,
|
|
156
|
+
consoleSchemaReady,
|
|
157
157
|
sync: {
|
|
158
|
-
...
|
|
158
|
+
...routes,
|
|
159
159
|
websocket: upgradeWebSocket
|
|
160
160
|
? {
|
|
161
161
|
enabled: true,
|
|
162
162
|
upgradeWebSocket,
|
|
163
|
-
...(
|
|
164
|
-
heartbeatIntervalMs:
|
|
163
|
+
...(routes?.websocket?.heartbeatIntervalMs !== undefined && {
|
|
164
|
+
heartbeatIntervalMs: routes.websocket.heartbeatIntervalMs,
|
|
165
165
|
}),
|
|
166
|
-
...(
|
|
167
|
-
maxConnectionsTotal:
|
|
166
|
+
...(routes?.websocket?.maxConnectionsTotal !== undefined && {
|
|
167
|
+
maxConnectionsTotal: routes.websocket.maxConnectionsTotal,
|
|
168
168
|
}),
|
|
169
|
-
...(
|
|
170
|
-
maxConnectionsPerClient:
|
|
169
|
+
...(routes?.websocket?.maxConnectionsPerClient !== undefined && {
|
|
170
|
+
maxConnectionsPerClient: routes.websocket.maxConnectionsPerClient,
|
|
171
171
|
}),
|
|
172
172
|
}
|
|
173
173
|
: { enabled: false },
|
|
@@ -182,12 +182,15 @@ export function createSyncServer<DB extends SyncCoreDb = SyncCoreDb>(
|
|
|
182
182
|
const consoleRoutes = createConsoleRoutes({
|
|
183
183
|
db,
|
|
184
184
|
dialect,
|
|
185
|
-
handlers,
|
|
185
|
+
handlers: sync.handlers,
|
|
186
186
|
authenticate: createTokenAuthenticator(consoleToken),
|
|
187
|
-
corsOrigins: resolvedConsoleConfig.corsOrigins
|
|
187
|
+
corsOrigins: resolvedConsoleConfig.corsOrigins,
|
|
188
188
|
eventEmitter: consoleEventEmitter,
|
|
189
|
+
consoleSchemaReady,
|
|
189
190
|
wsConnectionManager: getSyncWebSocketConnectionManager(syncRoutes),
|
|
190
191
|
metrics: resolvedConsoleConfig.metrics,
|
|
192
|
+
maintenance: resolvedConsoleConfig.maintenance,
|
|
193
|
+
blobBucket: resolvedConsoleConfig.blobBucket,
|
|
191
194
|
...(upgradeWebSocket && {
|
|
192
195
|
websocket: {
|
|
193
196
|
enabled: true,
|
|
@@ -11,7 +11,7 @@ import type {
|
|
|
11
11
|
} from '@syncular/core';
|
|
12
12
|
import type {
|
|
13
13
|
ExecuteProxyQueryResult,
|
|
14
|
-
|
|
14
|
+
ProxyHandlerCollection,
|
|
15
15
|
ServerSyncDialect,
|
|
16
16
|
SyncCoreDb,
|
|
17
17
|
} from '@syncular/server';
|
|
@@ -26,8 +26,8 @@ export interface ProxyConnectionManagerConfig<
|
|
|
26
26
|
db: Kysely<DB>;
|
|
27
27
|
/** Server sync dialect */
|
|
28
28
|
dialect: ServerSyncDialect;
|
|
29
|
-
/** Proxy table
|
|
30
|
-
handlers:
|
|
29
|
+
/** Proxy table handlers for oplog generation */
|
|
30
|
+
handlers: ProxyHandlerCollection;
|
|
31
31
|
/** Maximum concurrent connections (default: 100) */
|
|
32
32
|
maxConnections?: number;
|
|
33
33
|
/** Idle connection timeout in ms (default: 30000) */
|
package/src/proxy/routes.ts
CHANGED
|
@@ -12,7 +12,7 @@ import type {
|
|
|
12
12
|
} from '@syncular/core';
|
|
13
13
|
import { logSyncEvent } from '@syncular/core';
|
|
14
14
|
import type {
|
|
15
|
-
|
|
15
|
+
ProxyHandlerCollection,
|
|
16
16
|
ServerSyncDialect,
|
|
17
17
|
SyncCoreDb,
|
|
18
18
|
} from '@syncular/server';
|
|
@@ -48,8 +48,8 @@ interface CreateProxyRoutesConfig<DB extends SyncCoreDb = SyncCoreDb> {
|
|
|
48
48
|
db: Kysely<DB>;
|
|
49
49
|
/** Server sync dialect */
|
|
50
50
|
dialect: ServerSyncDialect;
|
|
51
|
-
/** Proxy table
|
|
52
|
-
handlers:
|
|
51
|
+
/** Proxy table handlers for oplog generation */
|
|
52
|
+
handlers: ProxyHandlerCollection;
|
|
53
53
|
/** Authenticate the request and return actor info */
|
|
54
54
|
authenticate: (c: Context) => Promise<ProxyAuthResult | null>;
|
|
55
55
|
/** WebSocket upgrade function from Hono */
|
|
@@ -75,7 +75,7 @@ interface CreateProxyRoutesConfig<DB extends SyncCoreDb = SyncCoreDb> {
|
|
|
75
75
|
*
|
|
76
76
|
* app.route('/proxy', createProxyRoutes({
|
|
77
77
|
* db,
|
|
78
|
-
* handlers:
|
|
78
|
+
* handlers: proxyHandlers,
|
|
79
79
|
* authenticate: async (c) => {
|
|
80
80
|
* // Verify admin auth
|
|
81
81
|
* return { actorId: 'admin:123' };
|