@syncular/server-dialect-postgres 0.0.1-100

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.
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @syncular/server-dialect-postgres - PostgreSQL Server Sync Dialect
3
+ *
4
+ * Driver-agnostic PostgreSQL dialect for sync. Works with any Postgres-compatible
5
+ * Kysely dialect (pg, pglite, neon, etc.).
6
+ *
7
+ * Tables:
8
+ * - sync_commits: commit log (idempotency + ordering)
9
+ * - sync_table_commits: commit routing index (fast pull by table)
10
+ * - sync_changes: change log (JSONB scopes for filtering)
11
+ * - sync_client_cursors: per-client cursor tracking (pruning/observability)
12
+ */
13
+ import type { ScopeValues, StoredScopes } from '@syncular/core';
14
+ import type { DbExecutor } from '@syncular/server';
15
+ import { BaseServerSyncDialect, type IncrementalPullRow, type IncrementalPullRowsArgs } from '@syncular/server';
16
+ import type { SyncChangeRow, SyncCoreDb } from '@syncular/server/schema';
17
+ import type { Kysely, RawBuilder, Transaction } from 'kysely';
18
+ export declare class PostgresServerSyncDialect extends BaseServerSyncDialect {
19
+ readonly name: "postgres";
20
+ readonly supportsForUpdate = true;
21
+ readonly supportsSavepoints = true;
22
+ protected buildNumberListFilter(values: number[]): RawBuilder<unknown>;
23
+ protected buildStringListFilter(values: string[]): RawBuilder<unknown>;
24
+ ensureSyncSchema<DB extends SyncCoreDb>(db: Kysely<DB>): Promise<void>;
25
+ executeInTransaction<DB extends SyncCoreDb, T>(db: Kysely<DB>, fn: (executor: DbExecutor<DB>) => Promise<T>): Promise<T>;
26
+ setRepeatableRead<DB extends SyncCoreDb>(trx: DbExecutor<DB>): Promise<void>;
27
+ readCommitSeqsForPull<DB extends SyncCoreDb>(db: Kysely<DB> | Transaction<DB>, args: {
28
+ cursor: number;
29
+ limitCommits: number;
30
+ tables: string[];
31
+ partitionId?: string;
32
+ }): Promise<number[]>;
33
+ recordClientCursor<DB extends SyncCoreDb>(db: Kysely<DB> | Transaction<DB>, args: {
34
+ partitionId?: string;
35
+ clientId: string;
36
+ actorId: string;
37
+ cursor: number;
38
+ effectiveScopes: ScopeValues;
39
+ }): Promise<void>;
40
+ readChangesForCommits<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: {
41
+ commitSeqs: number[];
42
+ table: string;
43
+ scopes: ScopeValues;
44
+ partitionId?: string;
45
+ }): Promise<SyncChangeRow[]>;
46
+ protected readIncrementalPullRowsBatch<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: Omit<IncrementalPullRowsArgs, 'batchSize'>): Promise<IncrementalPullRow[]>;
47
+ compactChanges<DB extends SyncCoreDb>(db: DbExecutor<DB>, args: {
48
+ fullHistoryHours: number;
49
+ }): Promise<number>;
50
+ scopesToDb(scopes: StoredScopes): StoredScopes;
51
+ dbToArray(value: unknown): string[];
52
+ arrayToDb(values: string[]): string[];
53
+ ensureConsoleSchema<DB extends SyncCoreDb>(db: Kysely<DB>): Promise<void>;
54
+ private ensureIndex;
55
+ }
56
+ export declare function createPostgresServerDialect(): PostgresServerSyncDialect;
57
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAU,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EACL,qBAAqB,EAGrB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAE7B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAc9D,qBAAa,yBAA0B,SAAQ,qBAAqB;IAClE,QAAQ,CAAC,IAAI,aAAuB;IACpC,QAAQ,CAAC,iBAAiB,QAAQ;IAClC,QAAQ,CAAC,kBAAkB,QAAQ;IAMnC,SAAS,CAAC,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,CAErE;IAED,SAAS,CAAC,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,CAErE;IAMK,gBAAgB,CAAC,EAAE,SAAS,UAAU,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA4M3E;IAMK,oBAAoB,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC,EACjD,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,EACd,EAAE,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3C,OAAO,CAAC,CAAC,CAAC,CAeZ;IAEK,iBAAiB,CAAC,EAAE,SAAS,UAAU,EAC3C,GAAG,EAAE,UAAU,CAAC,EAAE,CAAC,GAClB,OAAO,CAAC,IAAI,CAAC,CAEf;IAMK,qBAAqB,CAAC,EAAE,SAAS,UAAU,EAC/C,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,EAAE,CAAC,EAChC,IAAI,EAAE;QACJ,MAAM,EAAE,MAAM,CAAC;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GACA,OAAO,CAAC,MAAM,EAAE,CAAC,CA0BnB;IAEK,kBAAkB,CAAC,EAAE,SAAS,UAAU,EAC5C,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,EAAE,CAAC,EAChC,IAAI,EAAE;QACJ,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,eAAe,EAAE,WAAW,CAAC;KAC9B,GACA,OAAO,CAAC,IAAI,CAAC,CAcf;IAMK,qBAAqB,CAAC,EAAE,SAAS,UAAU,EAC/C,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC,EAClB,IAAI,EAAE;QACJ,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,WAAW,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GACA,OAAO,CAAC,aAAa,EAAE,CAAC,CA8D1B;IAED,UAAyB,4BAA4B,CAAC,EAAE,SAAS,UAAU,EACzE,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC,EAClB,IAAI,EAAE,IAAI,CAAC,uBAAuB,EAAE,WAAW,CAAC,GAC/C,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAmF/B;IAEK,cAAc,CAAC,EAAE,SAAS,UAAU,EACxC,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC,EAClB,IAAI,EAAE;QAAE,gBAAgB,EAAE,MAAM,CAAA;KAAE,GACjC,OAAO,CAAC,MAAM,CAAC,CAwCjB;IAMD,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAE7C;IAED,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAKlC;IAED,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAEpC;IAMK,mBAAmB,CAAC,EAAE,SAAS,UAAU,EAC7C,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,GACb,OAAO,CAAC,IAAI,CAAC,CAmEf;YAMa,WAAW;CAgB1B;AAED,wBAAgB,2BAA2B,IAAI,yBAAyB,CAEvE"}
package/dist/index.js ADDED
@@ -0,0 +1,479 @@
1
+ /**
2
+ * @syncular/server-dialect-postgres - PostgreSQL Server Sync Dialect
3
+ *
4
+ * Driver-agnostic PostgreSQL dialect for sync. Works with any Postgres-compatible
5
+ * Kysely dialect (pg, pglite, neon, etc.).
6
+ *
7
+ * Tables:
8
+ * - sync_commits: commit log (idempotency + ordering)
9
+ * - sync_table_commits: commit routing index (fast pull by table)
10
+ * - sync_changes: change log (JSONB scopes for filtering)
11
+ * - sync_client_cursors: per-client cursor tracking (pruning/observability)
12
+ */
13
+ import { BaseServerSyncDialect, coerceIsoString, coerceNumber, parseScopes, } from '@syncular/server';
14
+ import { sql } from 'kysely';
15
+ function isActiveTransaction(db) {
16
+ return db.isTransaction === true;
17
+ }
18
+ function createSavepointName() {
19
+ const randomPart = Math.floor(Math.random() * 1_000_000_000).toString(36);
20
+ return `syncular_sp_${Date.now().toString(36)}_${randomPart}`;
21
+ }
22
+ export class PostgresServerSyncDialect extends BaseServerSyncDialect {
23
+ name = 'postgres';
24
+ supportsForUpdate = true;
25
+ supportsSavepoints = true;
26
+ // ===========================================================================
27
+ // SQL Fragment Hooks
28
+ // ===========================================================================
29
+ buildNumberListFilter(values) {
30
+ return sql `= ANY(${values}::bigint[])`;
31
+ }
32
+ buildStringListFilter(values) {
33
+ return sql `= ANY(${values}::text[])`;
34
+ }
35
+ // ===========================================================================
36
+ // Schema Setup
37
+ // ===========================================================================
38
+ async ensureSyncSchema(db) {
39
+ await db.schema
40
+ .createTable('sync_commits')
41
+ .ifNotExists()
42
+ .addColumn('commit_seq', 'bigserial', (col) => col.primaryKey())
43
+ .addColumn('partition_id', 'text', (col) => col.notNull().defaultTo('default'))
44
+ .addColumn('actor_id', 'text', (col) => col.notNull())
45
+ .addColumn('client_id', 'text', (col) => col.notNull())
46
+ .addColumn('client_commit_id', 'text', (col) => col.notNull())
47
+ .addColumn('created_at', 'timestamptz', (col) => col.notNull().defaultTo(sql `now()`))
48
+ .addColumn('meta', 'jsonb')
49
+ .addColumn('result_json', 'jsonb')
50
+ .addColumn('change_count', 'integer', (col) => col.notNull().defaultTo(0))
51
+ .addColumn('affected_tables', sql `text[]`, (col) => col.notNull().defaultTo(sql `ARRAY[]::text[]`))
52
+ .execute();
53
+ // Ensure new columns exist for dev environments that already created the table.
54
+ await sql `ALTER TABLE sync_commits
55
+ ADD COLUMN IF NOT EXISTS change_count integer NOT NULL DEFAULT 0`.execute(db);
56
+ await sql `ALTER TABLE sync_commits
57
+ ADD COLUMN IF NOT EXISTS affected_tables text[] NOT NULL DEFAULT ARRAY[]::text[]`.execute(db);
58
+ await sql `ALTER TABLE sync_commits
59
+ ADD COLUMN IF NOT EXISTS partition_id text NOT NULL DEFAULT 'default'`.execute(db);
60
+ await sql `DROP INDEX IF EXISTS idx_sync_commits_client_commit`.execute(db);
61
+ await db.schema
62
+ .createIndex('idx_sync_commits_client_commit')
63
+ .ifNotExists()
64
+ .on('sync_commits')
65
+ .columns(['partition_id', 'client_id', 'client_commit_id'])
66
+ .unique()
67
+ .execute();
68
+ // Table-based commit routing index
69
+ await db.schema
70
+ .createTable('sync_table_commits')
71
+ .ifNotExists()
72
+ .addColumn('partition_id', 'text', (col) => col.notNull().defaultTo('default'))
73
+ .addColumn('table', 'text', (col) => col.notNull())
74
+ .addColumn('commit_seq', 'bigint', (col) => col.notNull().references('sync_commits.commit_seq').onDelete('cascade'))
75
+ .addPrimaryKeyConstraint('sync_table_commits_pk', [
76
+ 'partition_id',
77
+ 'table',
78
+ 'commit_seq',
79
+ ])
80
+ .execute();
81
+ await sql `ALTER TABLE sync_table_commits
82
+ ADD COLUMN IF NOT EXISTS partition_id text NOT NULL DEFAULT 'default'`.execute(db);
83
+ await db.schema
84
+ .createIndex('idx_sync_table_commits_commit_seq')
85
+ .ifNotExists()
86
+ .on('sync_table_commits')
87
+ .columns(['partition_id', 'commit_seq'])
88
+ .execute();
89
+ // Changes table with JSONB scopes
90
+ await db.schema
91
+ .createTable('sync_changes')
92
+ .ifNotExists()
93
+ .addColumn('change_id', 'bigserial', (col) => col.primaryKey())
94
+ .addColumn('partition_id', 'text', (col) => col.notNull().defaultTo('default'))
95
+ .addColumn('commit_seq', 'bigint', (col) => col.notNull().references('sync_commits.commit_seq').onDelete('cascade'))
96
+ .addColumn('table', 'text', (col) => col.notNull())
97
+ .addColumn('row_id', 'text', (col) => col.notNull())
98
+ .addColumn('op', 'text', (col) => col.notNull())
99
+ .addColumn('row_json', 'jsonb')
100
+ .addColumn('row_version', 'bigint')
101
+ .addColumn('scopes', 'jsonb', (col) => col.notNull())
102
+ .execute();
103
+ await sql `ALTER TABLE sync_changes
104
+ ADD COLUMN IF NOT EXISTS partition_id text NOT NULL DEFAULT 'default'`.execute(db);
105
+ await db.schema
106
+ .createIndex('idx_sync_changes_commit_seq')
107
+ .ifNotExists()
108
+ .on('sync_changes')
109
+ .columns(['partition_id', 'commit_seq'])
110
+ .execute();
111
+ await db.schema
112
+ .createIndex('idx_sync_changes_table')
113
+ .ifNotExists()
114
+ .on('sync_changes')
115
+ .columns(['partition_id', 'table'])
116
+ .execute();
117
+ await this.ensureIndex(db, 'idx_sync_changes_scopes', 'CREATE INDEX idx_sync_changes_scopes ON sync_changes USING GIN (scopes)');
118
+ await db.schema
119
+ .createTable('sync_client_cursors')
120
+ .ifNotExists()
121
+ .addColumn('partition_id', 'text', (col) => col.notNull().defaultTo('default'))
122
+ .addColumn('client_id', 'text', (col) => col.notNull())
123
+ .addColumn('actor_id', 'text', (col) => col.notNull())
124
+ .addColumn('cursor', 'bigint', (col) => col.notNull().defaultTo(0))
125
+ .addColumn('effective_scopes', 'jsonb', (col) => col.notNull().defaultTo(sql `'{}'::jsonb`))
126
+ .addColumn('updated_at', 'timestamptz', (col) => col.notNull().defaultTo(sql `now()`))
127
+ .addPrimaryKeyConstraint('sync_client_cursors_pk', [
128
+ 'partition_id',
129
+ 'client_id',
130
+ ])
131
+ .execute();
132
+ await sql `ALTER TABLE sync_client_cursors
133
+ ADD COLUMN IF NOT EXISTS partition_id text NOT NULL DEFAULT 'default'`.execute(db);
134
+ await db.schema
135
+ .createIndex('idx_sync_client_cursors_updated_at')
136
+ .ifNotExists()
137
+ .on('sync_client_cursors')
138
+ .columns(['updated_at'])
139
+ .execute();
140
+ await db.schema
141
+ .createTable('sync_snapshot_chunks')
142
+ .ifNotExists()
143
+ .addColumn('chunk_id', 'text', (col) => col.primaryKey())
144
+ .addColumn('partition_id', 'text', (col) => col.notNull().defaultTo('default'))
145
+ .addColumn('scope_key', 'text', (col) => col.notNull())
146
+ .addColumn('scope', 'text', (col) => col.notNull())
147
+ .addColumn('as_of_commit_seq', 'bigint', (col) => col.notNull())
148
+ .addColumn('row_cursor', 'text', (col) => col.notNull().defaultTo(''))
149
+ .addColumn('row_limit', 'integer', (col) => col.notNull())
150
+ .addColumn('encoding', 'text', (col) => col.notNull())
151
+ .addColumn('compression', 'text', (col) => col.notNull())
152
+ .addColumn('sha256', 'text', (col) => col.notNull())
153
+ .addColumn('byte_length', 'integer', (col) => col.notNull())
154
+ .addColumn('blob_hash', 'text', (col) => col.notNull().defaultTo(''))
155
+ .addColumn('body', 'bytea') // Deprecated: use blob storage
156
+ .addColumn('created_at', 'timestamptz', (col) => col.notNull().defaultTo(sql `now()`))
157
+ .addColumn('expires_at', 'timestamptz', (col) => col.notNull())
158
+ .execute();
159
+ await sql `ALTER TABLE sync_snapshot_chunks
160
+ ADD COLUMN IF NOT EXISTS partition_id text NOT NULL DEFAULT 'default'`.execute(db);
161
+ await db.schema
162
+ .createIndex('idx_sync_snapshot_chunks_expires_at')
163
+ .ifNotExists()
164
+ .on('sync_snapshot_chunks')
165
+ .columns(['expires_at'])
166
+ .execute();
167
+ await db.schema
168
+ .createIndex('idx_sync_snapshot_chunks_page_key')
169
+ .ifNotExists()
170
+ .on('sync_snapshot_chunks')
171
+ .columns([
172
+ 'partition_id',
173
+ 'scope_key',
174
+ 'scope',
175
+ 'as_of_commit_seq',
176
+ 'row_cursor',
177
+ 'row_limit',
178
+ 'encoding',
179
+ 'compression',
180
+ ])
181
+ .unique()
182
+ .execute();
183
+ }
184
+ // ===========================================================================
185
+ // Transaction Control
186
+ // ===========================================================================
187
+ async executeInTransaction(db, fn) {
188
+ if (isActiveTransaction(db)) {
189
+ const savepoint = createSavepointName();
190
+ await sql.raw(`SAVEPOINT ${savepoint}`).execute(db);
191
+ try {
192
+ const result = await fn(db);
193
+ await sql.raw(`RELEASE SAVEPOINT ${savepoint}`).execute(db);
194
+ return result;
195
+ }
196
+ catch (error) {
197
+ await sql.raw(`ROLLBACK TO SAVEPOINT ${savepoint}`).execute(db);
198
+ await sql.raw(`RELEASE SAVEPOINT ${savepoint}`).execute(db);
199
+ throw error;
200
+ }
201
+ }
202
+ return db.transaction().execute(fn);
203
+ }
204
+ async setRepeatableRead(trx) {
205
+ await sql `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ`.execute(trx);
206
+ }
207
+ // ===========================================================================
208
+ // Overrides (dialect-specific optimizations / casts)
209
+ // ===========================================================================
210
+ async readCommitSeqsForPull(db, args) {
211
+ const partitionId = args.partitionId ?? 'default';
212
+ if (args.tables.length === 0)
213
+ return [];
214
+ // Single-table fast path: skip DISTINCT since (partition_id, table, commit_seq) is PK
215
+ if (args.tables.length === 1) {
216
+ const res = await sql `
217
+ SELECT commit_seq
218
+ FROM sync_table_commits
219
+ WHERE partition_id = ${partitionId}
220
+ AND "table" = ${args.tables[0]}
221
+ AND commit_seq > ${args.cursor}
222
+ ORDER BY commit_seq ASC
223
+ LIMIT ${args.limitCommits}
224
+ `.execute(db);
225
+ return res.rows
226
+ .map((r) => coerceNumber(r.commit_seq))
227
+ .filter((n) => typeof n === 'number' && Number.isFinite(n) && n > args.cursor);
228
+ }
229
+ // Multi-table: use ANY() with DISTINCT
230
+ return super.readCommitSeqsForPull(db, args);
231
+ }
232
+ async recordClientCursor(db, args) {
233
+ const partitionId = args.partitionId ?? 'default';
234
+ const now = new Date().toISOString();
235
+ const scopesJson = JSON.stringify(args.effectiveScopes);
236
+ await sql `
237
+ INSERT INTO sync_client_cursors (partition_id, client_id, actor_id, cursor, effective_scopes, updated_at)
238
+ VALUES (${partitionId}, ${args.clientId}, ${args.actorId}, ${args.cursor}, ${scopesJson}::jsonb, ${now})
239
+ ON CONFLICT(partition_id, client_id) DO UPDATE SET
240
+ actor_id = ${args.actorId},
241
+ cursor = ${args.cursor},
242
+ effective_scopes = ${scopesJson}::jsonb,
243
+ updated_at = ${now}
244
+ `.execute(db);
245
+ }
246
+ // ===========================================================================
247
+ // Commit/Change Log Queries (dialect-specific)
248
+ // ===========================================================================
249
+ async readChangesForCommits(db, args) {
250
+ const partitionId = args.partitionId ?? 'default';
251
+ if (args.commitSeqs.length === 0)
252
+ return [];
253
+ // Build JSONB containment conditions for scope filtering
254
+ const scopeConditions = [];
255
+ for (const [key, value] of Object.entries(args.scopes)) {
256
+ if (Array.isArray(value)) {
257
+ scopeConditions.push(sql `scopes->>${key} = ANY(${value}::text[])`);
258
+ }
259
+ else {
260
+ scopeConditions.push(sql `scopes->>${key} = ${value}`);
261
+ }
262
+ }
263
+ let query = sql `
264
+ SELECT commit_seq, "table", row_id, op, row_json, row_version, scopes
265
+ FROM sync_changes
266
+ WHERE commit_seq = ANY(${args.commitSeqs}::bigint[])
267
+ AND partition_id = ${partitionId}
268
+ AND "table" = ${args.table}
269
+ `;
270
+ if (scopeConditions.length > 0) {
271
+ const scopeFilter = sql.join(scopeConditions, sql ` AND `);
272
+ query = sql `
273
+ SELECT commit_seq, "table", row_id, op, row_json, row_version, scopes
274
+ FROM sync_changes
275
+ WHERE commit_seq = ANY(${args.commitSeqs}::bigint[])
276
+ AND partition_id = ${partitionId}
277
+ AND "table" = ${args.table}
278
+ AND (${scopeFilter})
279
+ ORDER BY commit_seq ASC, change_id ASC
280
+ `;
281
+ }
282
+ const res = await query.execute(db);
283
+ return res.rows.map((row) => ({
284
+ commit_seq: coerceNumber(row.commit_seq) ?? 0,
285
+ table: row.table,
286
+ row_id: row.row_id,
287
+ op: row.op,
288
+ row_json: row.row_json ?? null,
289
+ row_version: coerceNumber(row.row_version),
290
+ scopes: parseScopes(row.scopes),
291
+ }));
292
+ }
293
+ async readIncrementalPullRowsBatch(db, args) {
294
+ const partitionId = args.partitionId ?? 'default';
295
+ const limitCommits = Math.max(1, Math.min(500, args.limitCommits));
296
+ // Build scope filter conditions
297
+ const scopeConditions = [];
298
+ for (const [key, value] of Object.entries(args.scopes)) {
299
+ if (Array.isArray(value)) {
300
+ scopeConditions.push(sql `c.scopes->>${key} = ANY(${value}::text[])`);
301
+ }
302
+ else {
303
+ scopeConditions.push(sql `c.scopes->>${key} = ${value}`);
304
+ }
305
+ }
306
+ const scopeFilter = scopeConditions.length > 0
307
+ ? sql.join(scopeConditions, sql ` AND `)
308
+ : sql `TRUE`;
309
+ const res = await sql `
310
+ WITH commit_seqs AS (
311
+ SELECT DISTINCT tc.commit_seq
312
+ FROM sync_table_commits tc
313
+ JOIN sync_commits cm ON cm.commit_seq = tc.commit_seq
314
+ WHERE tc.partition_id = ${partitionId}
315
+ AND tc."table" = ${args.table}
316
+ AND cm.partition_id = ${partitionId}
317
+ AND tc.commit_seq > ${args.cursor}
318
+ AND EXISTS (
319
+ SELECT 1
320
+ FROM sync_changes c
321
+ WHERE c.commit_seq = tc.commit_seq
322
+ AND c.partition_id = ${partitionId}
323
+ AND c."table" = ${args.table}
324
+ AND (${scopeFilter})
325
+ )
326
+ ORDER BY tc.commit_seq ASC
327
+ LIMIT ${limitCommits}
328
+ )
329
+ SELECT
330
+ cm.commit_seq,
331
+ cm.actor_id,
332
+ cm.created_at,
333
+ c.change_id,
334
+ c."table",
335
+ c.row_id,
336
+ c.op,
337
+ c.row_json,
338
+ c.row_version,
339
+ c.scopes
340
+ FROM commit_seqs cs
341
+ JOIN sync_commits cm ON cm.commit_seq = cs.commit_seq
342
+ JOIN sync_changes c ON c.commit_seq = cs.commit_seq
343
+ WHERE cm.partition_id = ${partitionId}
344
+ AND c.partition_id = ${partitionId}
345
+ AND c."table" = ${args.table}
346
+ AND (${scopeFilter})
347
+ ORDER BY cm.commit_seq ASC, c.change_id ASC
348
+ `.execute(db);
349
+ return res.rows.map((row) => ({
350
+ commit_seq: coerceNumber(row.commit_seq) ?? 0,
351
+ actor_id: row.actor_id,
352
+ created_at: coerceIsoString(row.created_at),
353
+ change_id: coerceNumber(row.change_id) ?? 0,
354
+ table: row.table,
355
+ row_id: row.row_id,
356
+ op: row.op,
357
+ row_json: row.row_json ?? null,
358
+ row_version: coerceNumber(row.row_version),
359
+ scopes: parseScopes(row.scopes),
360
+ }));
361
+ }
362
+ async compactChanges(db, args) {
363
+ const cutoffIso = new Date(Date.now() - args.fullHistoryHours * 60 * 60 * 1000).toISOString();
364
+ const res = await sql `
365
+ WITH ranked AS (
366
+ SELECT
367
+ c.change_id,
368
+ row_number() OVER (
369
+ PARTITION BY c.partition_id, c."table", c.row_id, c.scopes
370
+ ORDER BY c.commit_seq DESC, c.change_id DESC
371
+ ) AS rn
372
+ FROM sync_changes c
373
+ JOIN sync_commits cm ON cm.commit_seq = c.commit_seq
374
+ WHERE cm.created_at < ${cutoffIso}
375
+ )
376
+ DELETE FROM sync_changes
377
+ WHERE change_id IN (SELECT change_id FROM ranked WHERE rn > 1)
378
+ `.execute(db);
379
+ const deletedChanges = Number(res.numAffectedRows ?? 0);
380
+ // Remove routing index entries that no longer have any remaining changes
381
+ await sql `
382
+ DELETE FROM sync_table_commits tc
383
+ USING sync_commits cm
384
+ WHERE cm.commit_seq = tc.commit_seq
385
+ AND cm.partition_id = tc.partition_id
386
+ AND cm.created_at < ${cutoffIso}
387
+ AND NOT EXISTS (
388
+ SELECT 1
389
+ FROM sync_changes c
390
+ WHERE c.commit_seq = tc.commit_seq
391
+ AND c.partition_id = tc.partition_id
392
+ AND c."table" = tc."table"
393
+ )
394
+ `.execute(db);
395
+ return deletedChanges;
396
+ }
397
+ // ===========================================================================
398
+ // Scope Conversion Helpers
399
+ // ===========================================================================
400
+ scopesToDb(scopes) {
401
+ return scopes;
402
+ }
403
+ dbToArray(value) {
404
+ if (Array.isArray(value)) {
405
+ return value.filter((k) => typeof k === 'string');
406
+ }
407
+ return [];
408
+ }
409
+ arrayToDb(values) {
410
+ return values.filter((v) => v.length > 0);
411
+ }
412
+ // ===========================================================================
413
+ // Console Schema (Request Events)
414
+ // ===========================================================================
415
+ async ensureConsoleSchema(db) {
416
+ await sql `
417
+ CREATE TABLE IF NOT EXISTS sync_request_events (
418
+ event_id BIGSERIAL PRIMARY KEY,
419
+ event_type TEXT NOT NULL,
420
+ actor_id TEXT NOT NULL,
421
+ client_id TEXT NOT NULL,
422
+ transport_path TEXT NOT NULL DEFAULT 'direct',
423
+ status_code INTEGER NOT NULL,
424
+ outcome TEXT NOT NULL,
425
+ duration_ms INTEGER NOT NULL,
426
+ commit_seq BIGINT,
427
+ operation_count INTEGER,
428
+ row_count INTEGER,
429
+ tables TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
430
+ error_message TEXT,
431
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
432
+ )
433
+ `.execute(db);
434
+ await sql `
435
+ ALTER TABLE sync_request_events
436
+ ADD COLUMN IF NOT EXISTS transport_path TEXT NOT NULL DEFAULT 'direct'
437
+ `.execute(db);
438
+ await this.ensureIndex(db, 'idx_sync_request_events_created_at', 'CREATE INDEX idx_sync_request_events_created_at ON sync_request_events(created_at DESC)');
439
+ await this.ensureIndex(db, 'idx_sync_request_events_event_type', 'CREATE INDEX idx_sync_request_events_event_type ON sync_request_events(event_type)');
440
+ await this.ensureIndex(db, 'idx_sync_request_events_client_id', 'CREATE INDEX idx_sync_request_events_client_id ON sync_request_events(client_id)');
441
+ // API Keys table
442
+ await sql `
443
+ CREATE TABLE IF NOT EXISTS sync_api_keys (
444
+ key_id TEXT PRIMARY KEY,
445
+ key_hash TEXT NOT NULL,
446
+ key_prefix TEXT NOT NULL,
447
+ name TEXT NOT NULL,
448
+ key_type TEXT NOT NULL,
449
+ scope_keys TEXT[] DEFAULT ARRAY[]::TEXT[],
450
+ actor_id TEXT,
451
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
452
+ expires_at TIMESTAMPTZ,
453
+ last_used_at TIMESTAMPTZ,
454
+ revoked_at TIMESTAMPTZ
455
+ )
456
+ `.execute(db);
457
+ await this.ensureIndex(db, 'idx_sync_api_keys_key_hash', 'CREATE INDEX idx_sync_api_keys_key_hash ON sync_api_keys(key_hash)');
458
+ await this.ensureIndex(db, 'idx_sync_api_keys_key_type', 'CREATE INDEX idx_sync_api_keys_key_type ON sync_api_keys(key_type)');
459
+ }
460
+ // ===========================================================================
461
+ // Private Helpers
462
+ // ===========================================================================
463
+ async ensureIndex(db, indexName, createSql) {
464
+ const exists = await sql `
465
+ SELECT 1 as ok
466
+ FROM pg_indexes
467
+ WHERE schemaname = 'public'
468
+ AND indexname = ${indexName}
469
+ LIMIT 1
470
+ `.execute(db);
471
+ if (exists.rows.length > 0)
472
+ return;
473
+ await sql.raw(createSql).execute(db);
474
+ }
475
+ }
476
+ export function createPostgresServerDialect() {
477
+ return new PostgresServerSyncDialect();
478
+ }
479
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@syncular/server-dialect-postgres",
3
+ "version": "0.0.1-100",
4
+ "description": "PostgreSQL dialect for the Syncular server",
5
+ "license": "MIT",
6
+ "author": "Benjamin Kniffler",
7
+ "homepage": "https://syncular.dev",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/syncular/syncular.git",
11
+ "directory": "packages/server-dialect-postgres"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/syncular/syncular/issues"
15
+ },
16
+ "keywords": [
17
+ "sync",
18
+ "offline-first",
19
+ "realtime",
20
+ "database",
21
+ "typescript"
22
+ ],
23
+ "private": false,
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "type": "module",
28
+ "exports": {
29
+ ".": {
30
+ "bun": "./src/index.ts",
31
+ "import": {
32
+ "types": "./dist/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ }
35
+ }
36
+ },
37
+ "scripts": {
38
+ "tsgo": "tsgo --noEmit",
39
+ "build": "tsgo",
40
+ "release": "bunx syncular-publish"
41
+ },
42
+ "dependencies": {
43
+ "@syncular/core": "0.0.1",
44
+ "@syncular/server": "0.0.1"
45
+ },
46
+ "peerDependencies": {
47
+ "kysely": "^0.28.0"
48
+ },
49
+ "devDependencies": {
50
+ "@syncular/config": "0.0.0",
51
+ "kysely": "*"
52
+ },
53
+ "files": [
54
+ "dist",
55
+ "src"
56
+ ]
57
+ }