@syncular/client 0.0.6-239 → 0.0.6-241

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.
@@ -4,6 +4,7 @@
4
4
  * This wrapper keeps query-builder tracking isolated per chain so branching a
5
5
  * base Kysely builder does not leak joined tables into sibling branches.
6
6
  */
7
+ import { type ColumnCodecDialect, type ColumnCodecSource } from '@syncular/core';
7
8
  import type { Kysely } from 'kysely';
8
9
  import type { FingerprintCollector } from './query/FingerprintCollector';
9
10
  import { type MutationTimestampSource } from './query/fingerprint';
@@ -15,5 +16,5 @@ type TrackedSelectFrom<DB> = Kysely<DB>['selectFrom'];
15
16
  export interface QueryContext<DB extends SyncClientDb = SyncClientDb> {
16
17
  selectFrom: TrackedSelectFrom<DB>;
17
18
  }
18
- export declare function createQueryContext<DB extends SyncClientDb>(db: Kysely<DB>, scopeCollector: Set<string>, fingerprintCollector: FingerprintCollector, engine: MutationTimestampSource, keyField?: string, fingerprintMode?: FingerprintMode): QueryContext<DB>;
19
+ export declare function createQueryContext<DB extends SyncClientDb>(db: Kysely<DB>, scopeCollector: Set<string>, fingerprintCollector: FingerprintCollector, engine: MutationTimestampSource, keyField?: string, fingerprintMode?: FingerprintMode, codecSource?: ColumnCodecSource, codecDialect?: ColumnCodecDialect): QueryContext<DB>;
19
20
  //# sourceMappingURL=query-public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"query-public.d.ts","sourceRoot":"","sources":["../src/query-public.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAIL,KAAK,uBAAuB,EAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EACL,cAAc,EACd,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,CAAC;AAE/C,KAAK,iBAAiB,CAAC,EAAE,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;AAqOtD,MAAM,WAAW,YAAY,CAAC,EAAE,SAAS,YAAY,GAAG,YAAY;IAClE,UAAU,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAC;CACnC;AAED,wBAAgB,kBAAkB,CAAC,EAAE,SAAS,YAAY,EACxD,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,EACd,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,EAC3B,oBAAoB,EAAE,oBAAoB,EAC1C,MAAM,EAAE,uBAAuB,EAC/B,QAAQ,SAAO,EACf,eAAe,GAAE,eAAwB,GACxC,YAAY,CAAC,EAAE,CAAC,CAWlB"}
1
+ {"version":3,"file":"query-public.d.ts","sourceRoot":"","sources":["../src/query-public.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EAGvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,MAAM,EAAqB,MAAM,QAAQ,CAAC;AACxD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAIL,KAAK,uBAAuB,EAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EACL,cAAc,EACd,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,CAAC;AAE/C,KAAK,iBAAiB,CAAC,EAAE,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;AAiTtD,MAAM,WAAW,YAAY,CAAC,EAAE,SAAS,YAAY,GAAG,YAAY;IAClE,UAAU,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAC;CACnC;AAED,wBAAgB,kBAAkB,CAAC,EAAE,SAAS,YAAY,EACxD,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,EACd,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,EAC3B,oBAAoB,EAAE,oBAAoB,EAC1C,MAAM,EAAE,uBAAuB,EAC/B,QAAQ,SAAO,EACf,eAAe,GAAE,eAAwB,EACzC,WAAW,CAAC,EAAE,iBAAiB,EAC/B,YAAY,GAAE,kBAA6B,GAC1C,YAAY,CAAC,EAAE,CAAC,CAalB"}
@@ -4,6 +4,7 @@
4
4
  * This wrapper keeps query-builder tracking isolated per chain so branching a
5
5
  * base Kysely builder does not leak joined tables into sibling branches.
6
6
  */
7
+ import { applyQueryResultPlan, buildQueryResultPlan, createTableColumnCodecsResolver, } from '@syncular/core';
7
8
  import { computeRowFingerprint, computeValueFingerprint, hasKeyField, } from './query/fingerprint.js';
8
9
  export { FingerprintCollector } from './query/FingerprintCollector.js';
9
10
  export { canFingerprint, computeFingerprint, } from './query/fingerprint.js';
@@ -62,15 +63,51 @@ function addTrackedTablesToScopeCollector(scopeCollector, trackedTables) {
62
63
  scopeCollector.add(trackedTable);
63
64
  }
64
65
  }
65
- function createExecuteProxy(builder, primaryTable, trackedTables, scopeCollector, collector, engine, keyField, fingerprintMode) {
66
+ function isOperationNodeSource(value) {
67
+ if (!isRecord(value))
68
+ return false;
69
+ return typeof Reflect.get(value, 'toOperationNode') === 'function';
70
+ }
71
+ function decodeRows(rows, builder, resolveCodecs, codecDialect) {
72
+ if (!resolveCodecs || !builder)
73
+ return rows;
74
+ const plan = buildQueryResultPlan(builder.toOperationNode());
75
+ if (!plan)
76
+ return rows;
77
+ if (Array.isArray(rows)) {
78
+ return rows.map((row) => {
79
+ if (!isRecord(row))
80
+ return row;
81
+ return applyQueryResultPlan({
82
+ row,
83
+ plan,
84
+ resolveTableCodecs: resolveCodecs,
85
+ dialect: codecDialect,
86
+ });
87
+ });
88
+ }
89
+ if (!isRecord(rows))
90
+ return rows;
91
+ return applyQueryResultPlan({
92
+ row: rows,
93
+ plan,
94
+ resolveTableCodecs: resolveCodecs,
95
+ dialect: codecDialect,
96
+ });
97
+ }
98
+ function createExecuteProxy(builder, primaryTable, trackedTables, scopeCollector, collector, engine, keyField, fingerprintMode, resolveCodecs, codecDialect) {
99
+ const operationNodeSource = isOperationNodeSource(builder)
100
+ ? builder
101
+ : undefined;
66
102
  return new Proxy(builder, {
67
103
  get(target, prop, receiver) {
68
104
  if (prop === 'execute') {
69
105
  return async () => {
70
106
  const rows = await target.execute();
107
+ const decoded = decodeRows(rows, operationNodeSource, resolveCodecs, codecDialect);
71
108
  addTrackedTablesToScopeCollector(scopeCollector, trackedTables);
72
109
  addFingerprint({
73
- rows,
110
+ rows: decoded,
74
111
  primaryTable,
75
112
  trackedTables,
76
113
  collector,
@@ -78,15 +115,16 @@ function createExecuteProxy(builder, primaryTable, trackedTables, scopeCollector
78
115
  keyField,
79
116
  fingerprintMode,
80
117
  });
81
- return rows;
118
+ return decoded;
82
119
  };
83
120
  }
84
121
  if (prop === 'executeTakeFirst') {
85
122
  return async () => {
86
123
  const row = await target.executeTakeFirst();
124
+ const decoded = decodeRows(row, operationNodeSource, resolveCodecs, codecDialect);
87
125
  addTrackedTablesToScopeCollector(scopeCollector, trackedTables);
88
126
  addFingerprint({
89
- rows: row,
127
+ rows: decoded,
90
128
  primaryTable,
91
129
  trackedTables,
92
130
  collector,
@@ -94,15 +132,16 @@ function createExecuteProxy(builder, primaryTable, trackedTables, scopeCollector
94
132
  keyField,
95
133
  fingerprintMode,
96
134
  });
97
- return row;
135
+ return decoded;
98
136
  };
99
137
  }
100
138
  if (prop === 'executeTakeFirstOrThrow') {
101
139
  return async () => {
102
140
  const row = await target.executeTakeFirstOrThrow();
141
+ const decoded = decodeRows(row, operationNodeSource, resolveCodecs, codecDialect);
103
142
  addTrackedTablesToScopeCollector(scopeCollector, trackedTables);
104
143
  addFingerprint({
105
- rows: row,
144
+ rows: decoded,
106
145
  primaryTable,
107
146
  trackedTables,
108
147
  collector,
@@ -110,7 +149,7 @@ function createExecuteProxy(builder, primaryTable, trackedTables, scopeCollector
110
149
  keyField,
111
150
  fingerprintMode,
112
151
  });
113
- return row;
152
+ return decoded;
114
153
  };
115
154
  }
116
155
  const value = Reflect.get(target, prop, receiver);
@@ -130,23 +169,26 @@ function createExecuteProxy(builder, primaryTable, trackedTables, scopeCollector
130
169
  if (!isExecutableQuery(result)) {
131
170
  return result;
132
171
  }
133
- return createExecuteProxy(result, primaryTable, nextTrackedTables, scopeCollector, collector, engine, keyField, fingerprintMode);
172
+ return createExecuteProxy(result, primaryTable, nextTrackedTables, scopeCollector, collector, engine, keyField, fingerprintMode, resolveCodecs, codecDialect);
134
173
  };
135
174
  },
136
175
  });
137
176
  }
138
- function createTrackedSelectFrom(db, scopeCollector, fingerprintCollector, engine, keyField = 'id', fingerprintMode = 'auto') {
177
+ function createTrackedSelectFrom(db, scopeCollector, fingerprintCollector, engine, keyField = 'id', fingerprintMode = 'auto', codecSource, codecDialect = 'sqlite') {
178
+ const resolveCodecs = codecSource
179
+ ? createTableColumnCodecsResolver(codecSource, { dialect: codecDialect })
180
+ : undefined;
139
181
  const selectFrom = (...args) => {
140
182
  const trackedTables = new Set(extractTrackedTableNames(args[0]));
141
183
  const primaryTable = Array.from(trackedTables)[0] ?? null;
142
184
  const builder = db.selectFrom(...args);
143
- return createExecuteProxy(builder, primaryTable, trackedTables, scopeCollector, fingerprintCollector, engine, keyField, fingerprintMode);
185
+ return createExecuteProxy(builder, primaryTable, trackedTables, scopeCollector, fingerprintCollector, engine, keyField, fingerprintMode, resolveCodecs, codecDialect);
144
186
  };
145
187
  return selectFrom;
146
188
  }
147
- export function createQueryContext(db, scopeCollector, fingerprintCollector, engine, keyField = 'id', fingerprintMode = 'auto') {
189
+ export function createQueryContext(db, scopeCollector, fingerprintCollector, engine, keyField = 'id', fingerprintMode = 'auto', codecSource, codecDialect = 'sqlite') {
148
190
  return {
149
- selectFrom: createTrackedSelectFrom(db, scopeCollector, fingerprintCollector, engine, keyField, fingerprintMode),
191
+ selectFrom: createTrackedSelectFrom(db, scopeCollector, fingerprintCollector, engine, keyField, fingerprintMode, codecSource, codecDialect),
150
192
  };
151
193
  }
152
194
  //# sourceMappingURL=query-public.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"query-public.js","sourceRoot":"","sources":["../src/query-public.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query-public.js","sourceRoot":"","sources":["../src/query-public.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syncular/client",
3
- "version": "0.0.6-239",
3
+ "version": "0.0.6-241",
4
4
  "description": "Client-side sync engine with offline-first support, outbox, and conflict resolution",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Benjamin Kniffler",
@@ -119,8 +119,8 @@
119
119
  "release": "bunx syncular-publish"
120
120
  },
121
121
  "dependencies": {
122
- "@syncular/core": "0.0.6-239",
123
- "@syncular/transport-http": "0.0.6-239"
122
+ "@syncular/core": "0.0.6-241",
123
+ "@syncular/transport-http": "0.0.6-241"
124
124
  },
125
125
  "peerDependencies": {
126
126
  "kysely": "*"
@@ -0,0 +1,162 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from 'bun:test';
2
+ import { codecs, createDatabase } from '@syncular/core';
3
+ import type { Kysely } from 'kysely';
4
+ import { createBunSqliteDialect } from '../../dialect-bun-sqlite/src';
5
+ import { createQueryContext, FingerprintCollector } from './query-public';
6
+ import type { SyncClientDb } from './schema';
7
+
8
+ interface TasksTable {
9
+ id: string;
10
+ enabled: number | boolean;
11
+ metadata: string | { tags: string[] };
12
+ }
13
+
14
+ interface FlagsTable {
15
+ id: string;
16
+ enabled: number | boolean;
17
+ metadata: string | { tags: string[] };
18
+ }
19
+
20
+ interface TestDb extends SyncClientDb {
21
+ tasks: TasksTable;
22
+ flags: FlagsTable;
23
+ }
24
+
25
+ const engine = {
26
+ getMutationTimestamp(): number {
27
+ return 0;
28
+ },
29
+ };
30
+
31
+ function createCodecs() {
32
+ return (column: { table: string; column: string }) => {
33
+ if (column.column === 'enabled') {
34
+ return codecs.numberBoolean();
35
+ }
36
+ if (column.column === 'metadata') {
37
+ return codecs.stringJson<{ tags: string[] }>();
38
+ }
39
+ return undefined;
40
+ };
41
+ }
42
+
43
+ describe('createQueryContext codec decoding', () => {
44
+ let db: Kysely<TestDb>;
45
+
46
+ beforeEach(async () => {
47
+ db = createDatabase<TestDb>({
48
+ dialect: createBunSqliteDialect({ path: ':memory:' }),
49
+ family: 'sqlite',
50
+ });
51
+
52
+ await db.schema
53
+ .createTable('tasks')
54
+ .addColumn('id', 'text', (col) => col.primaryKey())
55
+ .addColumn('enabled', 'integer', (col) => col.notNull())
56
+ .addColumn('metadata', 'text', (col) => col.notNull())
57
+ .execute();
58
+
59
+ await db.schema
60
+ .createTable('flags')
61
+ .addColumn('id', 'text', (col) => col.primaryKey())
62
+ .addColumn('enabled', 'integer', (col) => col.notNull())
63
+ .addColumn('metadata', 'text', (col) => col.notNull())
64
+ .execute();
65
+
66
+ await db
67
+ .insertInto('tasks')
68
+ .values({
69
+ id: 'task-1',
70
+ enabled: 1,
71
+ metadata: JSON.stringify({ tags: ['task'] }),
72
+ })
73
+ .execute();
74
+
75
+ await db
76
+ .insertInto('flags')
77
+ .values({
78
+ id: 'task-1',
79
+ enabled: 0,
80
+ metadata: JSON.stringify({ tags: ['flag'] }),
81
+ })
82
+ .execute();
83
+ });
84
+
85
+ afterEach(async () => {
86
+ await db.destroy();
87
+ });
88
+
89
+ it('decodes non-aliased columns from the primary table', async () => {
90
+ const ctx = createQueryContext(
91
+ db,
92
+ new Set(),
93
+ new FingerprintCollector(),
94
+ engine,
95
+ 'id',
96
+ 'value',
97
+ createCodecs(),
98
+ 'sqlite'
99
+ );
100
+
101
+ const row = await ctx
102
+ .selectFrom('tasks')
103
+ .selectAll()
104
+ .where('id', '=', 'task-1')
105
+ .executeTakeFirstOrThrow();
106
+
107
+ expect(row).toEqual({
108
+ id: 'task-1',
109
+ enabled: true,
110
+ metadata: { tags: ['task'] },
111
+ });
112
+ });
113
+
114
+ it('decodes aliased columns selected from the primary table', async () => {
115
+ const ctx = createQueryContext(
116
+ db,
117
+ new Set(),
118
+ new FingerprintCollector(),
119
+ engine,
120
+ 'id',
121
+ 'value',
122
+ createCodecs(),
123
+ 'sqlite'
124
+ );
125
+
126
+ const row = await ctx
127
+ .selectFrom('tasks as t')
128
+ .select(['t.enabled as isEnabled', 't.metadata as meta'])
129
+ .where('t.id', '=', 'task-1')
130
+ .executeTakeFirstOrThrow();
131
+
132
+ expect(row).toEqual({
133
+ isEnabled: true,
134
+ meta: { tags: ['task'] },
135
+ });
136
+ });
137
+
138
+ it('decodes aliased columns selected from joined tables', async () => {
139
+ const ctx = createQueryContext(
140
+ db,
141
+ new Set(),
142
+ new FingerprintCollector(),
143
+ engine,
144
+ 'id',
145
+ 'value',
146
+ createCodecs(),
147
+ 'sqlite'
148
+ );
149
+
150
+ const row = await ctx
151
+ .selectFrom('tasks')
152
+ .innerJoin('flags', 'flags.id', 'tasks.id')
153
+ .select(['flags.enabled as flagEnabled', 'flags.metadata as flagMeta'])
154
+ .where('tasks.id', '=', 'task-1')
155
+ .executeTakeFirstOrThrow();
156
+
157
+ expect(row).toEqual({
158
+ flagEnabled: false,
159
+ flagMeta: { tags: ['flag'] },
160
+ });
161
+ });
162
+ });
@@ -5,7 +5,15 @@
5
5
  * base Kysely builder does not leak joined tables into sibling branches.
6
6
  */
7
7
 
8
- import type { Kysely } from 'kysely';
8
+ import {
9
+ applyQueryResultPlan,
10
+ buildQueryResultPlan,
11
+ type ColumnCodecDialect,
12
+ type ColumnCodecSource,
13
+ createTableColumnCodecsResolver,
14
+ type TableColumnCodecs,
15
+ } from '@syncular/core';
16
+ import type { Kysely, RootOperationNode } from 'kysely';
9
17
  import type { FingerprintCollector } from './query/FingerprintCollector';
10
18
  import {
11
19
  computeRowFingerprint,
@@ -33,6 +41,10 @@ type ExecutableQuery = {
33
41
  executeTakeFirstOrThrow: () => Promise<unknown>;
34
42
  };
35
43
 
44
+ type OperationNodeSource = {
45
+ toOperationNode: () => RootOperationNode;
46
+ };
47
+
36
48
  const JOIN_METHODS = new Set([
37
49
  'innerJoin',
38
50
  'leftJoin',
@@ -123,6 +135,42 @@ function addTrackedTablesToScopeCollector(
123
135
  }
124
136
  }
125
137
 
138
+ function isOperationNodeSource(value: unknown): value is OperationNodeSource {
139
+ if (!isRecord(value)) return false;
140
+ return typeof Reflect.get(value, 'toOperationNode') === 'function';
141
+ }
142
+
143
+ function decodeRows(
144
+ rows: unknown,
145
+ builder: OperationNodeSource | undefined,
146
+ resolveCodecs:
147
+ | ((table: string, row: Record<string, unknown>) => TableColumnCodecs)
148
+ | undefined,
149
+ codecDialect: ColumnCodecDialect
150
+ ): unknown {
151
+ if (!resolveCodecs || !builder) return rows;
152
+ const plan = buildQueryResultPlan(builder.toOperationNode());
153
+ if (!plan) return rows;
154
+ if (Array.isArray(rows)) {
155
+ return rows.map((row) => {
156
+ if (!isRecord(row)) return row;
157
+ return applyQueryResultPlan({
158
+ row,
159
+ plan,
160
+ resolveTableCodecs: resolveCodecs,
161
+ dialect: codecDialect,
162
+ });
163
+ });
164
+ }
165
+ if (!isRecord(rows)) return rows;
166
+ return applyQueryResultPlan({
167
+ row: rows,
168
+ plan,
169
+ resolveTableCodecs: resolveCodecs,
170
+ dialect: codecDialect,
171
+ });
172
+ }
173
+
126
174
  function createExecuteProxy<B extends ExecutableQuery>(
127
175
  builder: B,
128
176
  primaryTable: string | null,
@@ -131,16 +179,30 @@ function createExecuteProxy<B extends ExecutableQuery>(
131
179
  collector: FingerprintCollector,
132
180
  engine: MutationTimestampSource,
133
181
  keyField: string,
134
- fingerprintMode: FingerprintMode
182
+ fingerprintMode: FingerprintMode,
183
+ resolveCodecs:
184
+ | ((table: string, row: Record<string, unknown>) => TableColumnCodecs)
185
+ | undefined,
186
+ codecDialect: ColumnCodecDialect
135
187
  ): B {
188
+ const operationNodeSource = isOperationNodeSource(builder)
189
+ ? builder
190
+ : undefined;
191
+
136
192
  return new Proxy(builder, {
137
193
  get(target, prop, receiver) {
138
194
  if (prop === 'execute') {
139
195
  return async () => {
140
196
  const rows = await target.execute();
197
+ const decoded = decodeRows(
198
+ rows,
199
+ operationNodeSource,
200
+ resolveCodecs,
201
+ codecDialect
202
+ );
141
203
  addTrackedTablesToScopeCollector(scopeCollector, trackedTables);
142
204
  addFingerprint({
143
- rows,
205
+ rows: decoded,
144
206
  primaryTable,
145
207
  trackedTables,
146
208
  collector,
@@ -148,16 +210,22 @@ function createExecuteProxy<B extends ExecutableQuery>(
148
210
  keyField,
149
211
  fingerprintMode,
150
212
  });
151
- return rows;
213
+ return decoded;
152
214
  };
153
215
  }
154
216
 
155
217
  if (prop === 'executeTakeFirst') {
156
218
  return async () => {
157
219
  const row = await target.executeTakeFirst();
220
+ const decoded = decodeRows(
221
+ row,
222
+ operationNodeSource,
223
+ resolveCodecs,
224
+ codecDialect
225
+ );
158
226
  addTrackedTablesToScopeCollector(scopeCollector, trackedTables);
159
227
  addFingerprint({
160
- rows: row,
228
+ rows: decoded,
161
229
  primaryTable,
162
230
  trackedTables,
163
231
  collector,
@@ -165,16 +233,22 @@ function createExecuteProxy<B extends ExecutableQuery>(
165
233
  keyField,
166
234
  fingerprintMode,
167
235
  });
168
- return row;
236
+ return decoded;
169
237
  };
170
238
  }
171
239
 
172
240
  if (prop === 'executeTakeFirstOrThrow') {
173
241
  return async () => {
174
242
  const row = await target.executeTakeFirstOrThrow();
243
+ const decoded = decodeRows(
244
+ row,
245
+ operationNodeSource,
246
+ resolveCodecs,
247
+ codecDialect
248
+ );
175
249
  addTrackedTablesToScopeCollector(scopeCollector, trackedTables);
176
250
  addFingerprint({
177
- rows: row,
251
+ rows: decoded,
178
252
  primaryTable,
179
253
  trackedTables,
180
254
  collector,
@@ -182,7 +256,7 @@ function createExecuteProxy<B extends ExecutableQuery>(
182
256
  keyField,
183
257
  fingerprintMode,
184
258
  });
185
- return row;
259
+ return decoded;
186
260
  };
187
261
  }
188
262
 
@@ -217,7 +291,9 @@ function createExecuteProxy<B extends ExecutableQuery>(
217
291
  collector,
218
292
  engine,
219
293
  keyField,
220
- fingerprintMode
294
+ fingerprintMode,
295
+ resolveCodecs,
296
+ codecDialect
221
297
  );
222
298
  };
223
299
  },
@@ -230,8 +306,14 @@ function createTrackedSelectFrom<DB extends SyncClientDb>(
230
306
  fingerprintCollector: FingerprintCollector,
231
307
  engine: MutationTimestampSource,
232
308
  keyField = 'id',
233
- fingerprintMode: FingerprintMode = 'auto'
309
+ fingerprintMode: FingerprintMode = 'auto',
310
+ codecSource?: ColumnCodecSource,
311
+ codecDialect: ColumnCodecDialect = 'sqlite'
234
312
  ): TrackedSelectFrom<DB> {
313
+ const resolveCodecs = codecSource
314
+ ? createTableColumnCodecsResolver(codecSource, { dialect: codecDialect })
315
+ : undefined;
316
+
235
317
  const selectFrom = (...args: SelectFromArgs<DB>) => {
236
318
  const trackedTables = new Set<string>(extractTrackedTableNames(args[0]));
237
319
  const primaryTable = Array.from(trackedTables)[0] ?? null;
@@ -245,7 +327,9 @@ function createTrackedSelectFrom<DB extends SyncClientDb>(
245
327
  fingerprintCollector,
246
328
  engine,
247
329
  keyField,
248
- fingerprintMode
330
+ fingerprintMode,
331
+ resolveCodecs,
332
+ codecDialect
249
333
  ) as SelectFromResult<DB>;
250
334
  };
251
335
 
@@ -262,7 +346,9 @@ export function createQueryContext<DB extends SyncClientDb>(
262
346
  fingerprintCollector: FingerprintCollector,
263
347
  engine: MutationTimestampSource,
264
348
  keyField = 'id',
265
- fingerprintMode: FingerprintMode = 'auto'
349
+ fingerprintMode: FingerprintMode = 'auto',
350
+ codecSource?: ColumnCodecSource,
351
+ codecDialect: ColumnCodecDialect = 'sqlite'
266
352
  ): QueryContext<DB> {
267
353
  return {
268
354
  selectFrom: createTrackedSelectFrom(
@@ -271,7 +357,9 @@ export function createQueryContext<DB extends SyncClientDb>(
271
357
  fingerprintCollector,
272
358
  engine,
273
359
  keyField,
274
- fingerprintMode
360
+ fingerprintMode,
361
+ codecSource,
362
+ codecDialect
275
363
  ),
276
364
  };
277
365
  }