@powersync/service-module-postgres-storage 0.11.2 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/@types/migrations/scripts/1771232439485-storage-version.d.ts +3 -0
  4. package/dist/@types/migrations/scripts/1771424826685-current-data-pending-deletes.d.ts +3 -0
  5. package/dist/@types/migrations/scripts/1771491856000-sync-plan.d.ts +3 -0
  6. package/dist/@types/storage/PostgresBucketStorageFactory.d.ts +6 -10
  7. package/dist/@types/storage/PostgresCompactor.d.ts +10 -3
  8. package/dist/@types/storage/PostgresSyncRulesStorage.d.ts +5 -3
  9. package/dist/@types/storage/batch/OperationBatch.d.ts +2 -2
  10. package/dist/@types/storage/batch/PostgresBucketBatch.d.ts +12 -9
  11. package/dist/@types/storage/batch/PostgresPersistedBatch.d.ts +17 -5
  12. package/dist/@types/storage/current-data-store.d.ts +85 -0
  13. package/dist/@types/storage/current-data-table.d.ts +9 -0
  14. package/dist/@types/storage/sync-rules/PostgresPersistedSyncRulesContent.d.ts +1 -10
  15. package/dist/@types/storage/table-id.d.ts +2 -0
  16. package/dist/@types/types/models/CurrentData.d.ts +18 -3
  17. package/dist/@types/types/models/SyncRules.d.ts +12 -2
  18. package/dist/@types/types/models/json.d.ts +11 -0
  19. package/dist/@types/types/types.d.ts +2 -0
  20. package/dist/@types/utils/bson.d.ts +1 -1
  21. package/dist/@types/utils/db.d.ts +9 -0
  22. package/dist/@types/utils/test-utils.d.ts +1 -1
  23. package/dist/migrations/scripts/1771232439485-storage-version.js +111 -0
  24. package/dist/migrations/scripts/1771232439485-storage-version.js.map +1 -0
  25. package/dist/migrations/scripts/1771424826685-current-data-pending-deletes.js +8 -0
  26. package/dist/migrations/scripts/1771424826685-current-data-pending-deletes.js.map +1 -0
  27. package/dist/migrations/scripts/1771491856000-sync-plan.js +91 -0
  28. package/dist/migrations/scripts/1771491856000-sync-plan.js.map +1 -0
  29. package/dist/storage/PostgresBucketStorageFactory.js +56 -58
  30. package/dist/storage/PostgresBucketStorageFactory.js.map +1 -1
  31. package/dist/storage/PostgresCompactor.js +55 -66
  32. package/dist/storage/PostgresCompactor.js.map +1 -1
  33. package/dist/storage/PostgresSyncRulesStorage.js +23 -15
  34. package/dist/storage/PostgresSyncRulesStorage.js.map +1 -1
  35. package/dist/storage/batch/OperationBatch.js +2 -1
  36. package/dist/storage/batch/OperationBatch.js.map +1 -1
  37. package/dist/storage/batch/PostgresBucketBatch.js +286 -213
  38. package/dist/storage/batch/PostgresBucketBatch.js.map +1 -1
  39. package/dist/storage/batch/PostgresPersistedBatch.js +86 -81
  40. package/dist/storage/batch/PostgresPersistedBatch.js.map +1 -1
  41. package/dist/storage/current-data-store.js +270 -0
  42. package/dist/storage/current-data-store.js.map +1 -0
  43. package/dist/storage/current-data-table.js +22 -0
  44. package/dist/storage/current-data-table.js.map +1 -0
  45. package/dist/storage/sync-rules/PostgresPersistedSyncRulesContent.js +14 -30
  46. package/dist/storage/sync-rules/PostgresPersistedSyncRulesContent.js.map +1 -1
  47. package/dist/storage/table-id.js +8 -0
  48. package/dist/storage/table-id.js.map +1 -0
  49. package/dist/types/models/CurrentData.js +11 -2
  50. package/dist/types/models/CurrentData.js.map +1 -1
  51. package/dist/types/models/SyncRules.js +12 -1
  52. package/dist/types/models/SyncRules.js.map +1 -1
  53. package/dist/types/models/json.js +21 -0
  54. package/dist/types/models/json.js.map +1 -0
  55. package/dist/utils/bson.js.map +1 -1
  56. package/dist/utils/db.js +41 -0
  57. package/dist/utils/db.js.map +1 -1
  58. package/dist/utils/test-utils.js +50 -14
  59. package/dist/utils/test-utils.js.map +1 -1
  60. package/package.json +9 -9
  61. package/src/migrations/scripts/1771232439485-storage-version.ts +44 -0
  62. package/src/migrations/scripts/1771424826685-current-data-pending-deletes.ts +10 -0
  63. package/src/migrations/scripts/1771491856000-sync-plan.ts +21 -0
  64. package/src/storage/PostgresBucketStorageFactory.ts +69 -68
  65. package/src/storage/PostgresCompactor.ts +63 -72
  66. package/src/storage/PostgresSyncRulesStorage.ts +30 -17
  67. package/src/storage/batch/OperationBatch.ts +4 -3
  68. package/src/storage/batch/PostgresBucketBatch.ts +306 -238
  69. package/src/storage/batch/PostgresPersistedBatch.ts +92 -84
  70. package/src/storage/current-data-store.ts +326 -0
  71. package/src/storage/current-data-table.ts +26 -0
  72. package/src/storage/sync-rules/PostgresPersistedSyncRulesContent.ts +13 -33
  73. package/src/storage/table-id.ts +9 -0
  74. package/src/types/models/CurrentData.ts +17 -4
  75. package/src/types/models/SyncRules.ts +16 -1
  76. package/src/types/models/json.ts +26 -0
  77. package/src/utils/bson.ts +1 -1
  78. package/src/utils/db.ts +47 -0
  79. package/src/utils/test-utils.ts +42 -15
  80. package/test/src/__snapshots__/storage.test.ts.snap +148 -6
  81. package/test/src/__snapshots__/storage_compacting.test.ts.snap +17 -0
  82. package/test/src/__snapshots__/storage_sync.test.ts.snap +2211 -21
  83. package/test/src/migrations.test.ts +9 -2
  84. package/test/src/storage.test.ts +137 -131
  85. package/test/src/storage_compacting.test.ts +113 -2
  86. package/test/src/storage_sync.test.ts +148 -4
  87. package/test/src/util.ts +5 -2
@@ -0,0 +1,270 @@
1
+ import { pick } from '../utils/ts-codec.js';
2
+ import * as models from '../types/models/CurrentData.js';
3
+ const TruncateCurrentDataCodec = pick(models.V1CurrentData, ['buckets', 'lookups', 'source_key']);
4
+ const LookupKeyCodec = pick(models.V1CurrentData, ['source_key', 'source_table']);
5
+ export const V1_CURRENT_DATA_TABLE = 'current_data';
6
+ export const V3_CURRENT_DATA_TABLE = 'v3_current_data';
7
+ export class PostgresCurrentDataStore {
8
+ table;
9
+ softDeleteEnabled;
10
+ constructor(storageConfig) {
11
+ this.softDeleteEnabled = storageConfig.softDeleteCurrentData;
12
+ this.table = storageConfig.softDeleteCurrentData ? V3_CURRENT_DATA_TABLE : V1_CURRENT_DATA_TABLE;
13
+ }
14
+ streamTruncateRows(db, options) {
15
+ return db.streamRows({
16
+ statement: `
17
+ SELECT
18
+ buckets,
19
+ lookups,
20
+ source_key
21
+ FROM
22
+ ${this.table}
23
+ WHERE
24
+ group_id = $1
25
+ AND source_table = $2
26
+ ${this.wherePendingDelete({ onlyLiveRows: true })}
27
+ LIMIT
28
+ $3
29
+ FOR NO KEY UPDATE
30
+ `,
31
+ params: [
32
+ { type: 'int4', value: options.groupId },
33
+ { type: 'varchar', value: options.sourceTableId },
34
+ { type: 'int4', value: options.limit }
35
+ ]
36
+ });
37
+ }
38
+ decodeTruncateRow(row) {
39
+ return TruncateCurrentDataCodec.decode(row);
40
+ }
41
+ streamSizeRows(db, options) {
42
+ return db.streamRows({
43
+ statement: `
44
+ WITH
45
+ filter_data AS (
46
+ SELECT
47
+ decode(FILTER ->> 'source_key', 'hex') AS source_key,
48
+ (FILTER ->> 'source_table') AS source_table_id
49
+ FROM
50
+ jsonb_array_elements($1::jsonb) AS FILTER
51
+ )
52
+ SELECT
53
+ octet_length(c.data) AS data_size,
54
+ c.source_table,
55
+ c.source_key
56
+ FROM
57
+ ${this.table} c
58
+ JOIN filter_data f ON c.source_table = f.source_table_id
59
+ AND c.source_key = f.source_key
60
+ WHERE
61
+ c.group_id = $2
62
+ FOR NO KEY UPDATE
63
+ `,
64
+ params: [
65
+ { type: 'jsonb', value: options.lookups },
66
+ { type: 'int4', value: options.groupId }
67
+ ]
68
+ });
69
+ }
70
+ streamLookupRows(db, options) {
71
+ const selectColumns = options.skipExistingRows ? `c.source_table, c.source_key` : `c.*`;
72
+ return db.streamRows({
73
+ statement: `
74
+ SELECT
75
+ ${selectColumns}
76
+ FROM
77
+ ${this.table} c
78
+ JOIN (
79
+ SELECT
80
+ decode(FILTER ->> 'source_key', 'hex') AS source_key,
81
+ FILTER ->> 'source_table' AS source_table_id
82
+ FROM
83
+ jsonb_array_elements($1::jsonb) AS FILTER
84
+ ) f ON c.source_table = f.source_table_id
85
+ AND c.source_key = f.source_key
86
+ WHERE
87
+ c.group_id = $2
88
+ FOR NO KEY UPDATE;
89
+ `,
90
+ params: [
91
+ { type: 'jsonb', value: options.lookups },
92
+ { type: 'int4', value: options.groupId }
93
+ ]
94
+ });
95
+ }
96
+ decodeLookupRow(row, skipExistingRows) {
97
+ if (skipExistingRows) {
98
+ return LookupKeyCodec.decode(row);
99
+ }
100
+ return this.softDeleteEnabled ? models.V3CurrentData.decode(row) : models.V1CurrentData.decode(row);
101
+ }
102
+ async flushUpserts(db, updates) {
103
+ if (updates.length == 0) {
104
+ return;
105
+ }
106
+ if (this.softDeleteEnabled) {
107
+ await db.sql `
108
+ INSERT INTO
109
+ v3_current_data (
110
+ group_id,
111
+ source_table,
112
+ source_key,
113
+ buckets,
114
+ data,
115
+ lookups,
116
+ pending_delete
117
+ )
118
+ SELECT
119
+ group_id,
120
+ source_table,
121
+ decode(source_key, 'hex') AS source_key,
122
+ buckets::jsonb AS buckets,
123
+ decode(data, 'hex') AS data,
124
+ array(
125
+ SELECT
126
+ decode(element, 'hex')
127
+ FROM
128
+ unnest(lookups) AS element
129
+ ) AS lookups,
130
+ CASE
131
+ WHEN pending_delete IS NOT NULL THEN nextval('op_id_sequence')
132
+ ELSE NULL
133
+ END AS pending_delete
134
+ FROM
135
+ json_to_recordset(${{ type: 'json', value: updates }}::json) AS t (
136
+ group_id integer,
137
+ source_table text,
138
+ source_key text,
139
+ buckets text,
140
+ data text,
141
+ lookups TEXT[],
142
+ pending_delete bigint
143
+ )
144
+ ON CONFLICT (group_id, source_table, source_key) DO UPDATE
145
+ SET
146
+ buckets = EXCLUDED.buckets,
147
+ data = EXCLUDED.data,
148
+ lookups = EXCLUDED.lookups,
149
+ pending_delete = EXCLUDED.pending_delete;
150
+ `.execute();
151
+ return;
152
+ }
153
+ await db.sql `
154
+ INSERT INTO
155
+ current_data (
156
+ group_id,
157
+ source_table,
158
+ source_key,
159
+ buckets,
160
+ data,
161
+ lookups
162
+ )
163
+ SELECT
164
+ group_id,
165
+ source_table,
166
+ decode(source_key, 'hex') AS source_key,
167
+ buckets::jsonb AS buckets,
168
+ decode(data, 'hex') AS data,
169
+ array(
170
+ SELECT
171
+ decode(element, 'hex')
172
+ FROM
173
+ unnest(lookups) AS element
174
+ ) AS lookups
175
+ FROM
176
+ json_to_recordset(${{ type: 'json', value: updates }}::json) AS t (
177
+ group_id integer,
178
+ source_table text,
179
+ source_key text,
180
+ buckets text,
181
+ data text,
182
+ lookups TEXT[]
183
+ )
184
+ ON CONFLICT (group_id, source_table, source_key) DO UPDATE
185
+ SET
186
+ buckets = EXCLUDED.buckets,
187
+ data = EXCLUDED.data,
188
+ lookups = EXCLUDED.lookups;
189
+ `.execute();
190
+ }
191
+ async flushDeletes(db, options) {
192
+ if (options.deletes.length == 0) {
193
+ return;
194
+ }
195
+ if (this.softDeleteEnabled) {
196
+ await db.sql `
197
+ WITH
198
+ conditions AS (
199
+ SELECT
200
+ source_table,
201
+ decode(source_key_hex, 'hex') AS source_key
202
+ FROM
203
+ jsonb_to_recordset(${{
204
+ type: 'jsonb',
205
+ value: options.deletes
206
+ }}::jsonb) AS t (source_table text, source_key_hex text)
207
+ )
208
+ DELETE FROM v3_current_data USING conditions
209
+ WHERE
210
+ v3_current_data.group_id = ${{ type: 'int4', value: options.groupId }}
211
+ AND v3_current_data.source_table = conditions.source_table
212
+ AND v3_current_data.source_key = conditions.source_key;
213
+ `.execute();
214
+ return;
215
+ }
216
+ await db.sql `
217
+ WITH
218
+ conditions AS (
219
+ SELECT
220
+ source_table,
221
+ decode(source_key_hex, 'hex') AS source_key
222
+ FROM
223
+ jsonb_to_recordset(${{
224
+ type: 'jsonb',
225
+ value: options.deletes
226
+ }}::jsonb) AS t (source_table text, source_key_hex text)
227
+ )
228
+ DELETE FROM current_data USING conditions
229
+ WHERE
230
+ current_data.group_id = ${{ type: 'int4', value: options.groupId }}
231
+ AND current_data.source_table = conditions.source_table
232
+ AND current_data.source_key = conditions.source_key;
233
+ `.execute();
234
+ }
235
+ async cleanupPendingDeletes(db, options) {
236
+ if (!this.softDeleteEnabled) {
237
+ return;
238
+ }
239
+ await db.sql `
240
+ DELETE FROM v3_current_data
241
+ WHERE
242
+ group_id = ${{ type: 'int4', value: options.groupId }}
243
+ AND pending_delete IS NOT NULL
244
+ AND pending_delete <= ${{ type: 'int8', value: options.lastCheckpoint }}
245
+ `.execute();
246
+ }
247
+ async deleteGroupRows(db, options) {
248
+ if (this.softDeleteEnabled) {
249
+ await db.sql `
250
+ DELETE FROM v3_current_data
251
+ WHERE
252
+ group_id = ${{ type: 'int4', value: options.groupId }}
253
+ `.execute();
254
+ }
255
+ else {
256
+ await db.sql `
257
+ DELETE FROM current_data
258
+ WHERE
259
+ group_id = ${{ type: 'int4', value: options.groupId }}
260
+ `.execute();
261
+ }
262
+ }
263
+ wherePendingDelete(options) {
264
+ if (this.softDeleteEnabled && options.onlyLiveRows) {
265
+ return `AND pending_delete IS NULL`;
266
+ }
267
+ return ``;
268
+ }
269
+ }
270
+ //# sourceMappingURL=current-data-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"current-data-store.js","sourceRoot":"","sources":["../../src/storage/current-data-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { ServiceAssertionError } from '@powersync/lib-services-framework';
2
+ export const V1_CURRENT_DATA_TABLE = 'current_data';
3
+ export const V3_CURRENT_DATA_TABLE = 'v3_current_data';
4
+ /**
5
+ * The table used by a specific storage version for general current_data access.
6
+ */
7
+ export function getCommonCurrentDataTable(storageConfig) {
8
+ return storageConfig.softDeleteCurrentData ? V3_CURRENT_DATA_TABLE : V1_CURRENT_DATA_TABLE;
9
+ }
10
+ export function getV1CurrentDataTable(storageConfig) {
11
+ if (storageConfig.softDeleteCurrentData) {
12
+ throw new ServiceAssertionError('current_data table cannot be used when softDeleteCurrentData is enabled');
13
+ }
14
+ return V1_CURRENT_DATA_TABLE;
15
+ }
16
+ export function getV3CurrentDataTable(storageConfig) {
17
+ if (!storageConfig.softDeleteCurrentData) {
18
+ throw new ServiceAssertionError('v3_current_data table cannot be used when softDeleteCurrentData is disabled');
19
+ }
20
+ return V3_CURRENT_DATA_TABLE;
21
+ }
22
+ //# sourceMappingURL=current-data-table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"current-data-table.js","sourceRoot":"","sources":["../../src/storage/current-data-table.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAG1E,MAAM,CAAC,MAAM,qBAAqB,GAAG,cAAc,CAAC;AACpD,MAAM,CAAC,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;AAEvD;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,aAA2C;IACnF,OAAO,aAAa,CAAC,qBAAqB,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,qBAAqB,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,aAA2C;IAC/E,IAAI,aAAa,CAAC,qBAAqB,EAAE,CAAC;QACxC,MAAM,IAAI,qBAAqB,CAAC,yEAAyE,CAAC,CAAC;IAC7G,CAAC;IACD,OAAO,qBAAqB,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,aAA2C;IAC/E,IAAI,CAAC,aAAa,CAAC,qBAAqB,EAAE,CAAC;QACzC,MAAM,IAAI,qBAAqB,CAAC,6EAA6E,CAAC,CAAC;IACjH,CAAC;IACD,OAAO,qBAAqB,CAAC;AAC/B,CAAC"}
@@ -1,39 +1,23 @@
1
1
  import * as lib_postgres from '@powersync/lib-service-postgres';
2
2
  import { ErrorCode, logger, ServiceError } from '@powersync/lib-services-framework';
3
- import { SqlSyncRules, versionedHydrationState } from '@powersync/service-sync-rules';
4
- export class PostgresPersistedSyncRulesContent {
3
+ import { storage } from '@powersync/service-core';
4
+ export class PostgresPersistedSyncRulesContent extends storage.PersistedSyncRulesContent {
5
5
  db;
6
- slot_name;
7
- id;
8
- sync_rules_content;
9
- last_checkpoint_lsn;
10
- last_fatal_error;
11
- last_keepalive_ts;
12
- last_checkpoint_ts;
13
- active;
14
6
  current_lock = null;
15
7
  constructor(db, row) {
8
+ super({
9
+ id: Number(row.id),
10
+ sync_rules_content: row.content,
11
+ compiled_plan: row.sync_plan,
12
+ last_checkpoint_lsn: row.last_checkpoint_lsn,
13
+ slot_name: row.slot_name,
14
+ last_fatal_error: row.last_fatal_error,
15
+ last_checkpoint_ts: row.last_checkpoint_ts ? new Date(row.last_checkpoint_ts) : null,
16
+ last_keepalive_ts: row.last_keepalive_ts ? new Date(row.last_keepalive_ts) : null,
17
+ active: row.state == 'ACTIVE',
18
+ storageVersion: row.storage_version ?? storage.LEGACY_STORAGE_VERSION
19
+ });
16
20
  this.db = db;
17
- this.id = Number(row.id);
18
- this.sync_rules_content = row.content;
19
- this.last_checkpoint_lsn = row.last_checkpoint_lsn;
20
- this.slot_name = row.slot_name;
21
- this.last_fatal_error = row.last_fatal_error;
22
- this.last_checkpoint_ts = row.last_checkpoint_ts ? new Date(row.last_checkpoint_ts) : null;
23
- this.last_keepalive_ts = row.last_keepalive_ts ? new Date(row.last_keepalive_ts) : null;
24
- this.active = row.state == 'ACTIVE';
25
- }
26
- parsed(options) {
27
- return {
28
- id: this.id,
29
- slot_name: this.slot_name,
30
- sync_rules: SqlSyncRules.fromYaml(this.sync_rules_content, options),
31
- hydratedSyncRules() {
32
- return this.sync_rules.config.hydrate({
33
- hydrationState: versionedHydrationState(this.id)
34
- });
35
- }
36
- };
37
21
  }
38
22
  async lock() {
39
23
  const manager = new lib_postgres.PostgresLockManager({
@@ -1 +1 @@
1
- {"version":3,"file":"PostgresPersistedSyncRulesContent.js","sourceRoot":"","sources":["../../../src/storage/sync-rules/PostgresPersistedSyncRulesContent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PostgresPersistedSyncRulesContent.js","sourceRoot":"","sources":["../../../src/storage/sync-rules/PostgresPersistedSyncRulesContent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,YAAY,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAGlD,MAAM,OAAO,iCAAkC,SAAQ,OAAO,CAAC,yBAAyB;IAI5E;IAHV,YAAY,GAAmC,IAAI,CAAC;IAEpD,YACU,EAA+B,EACvC,GAA4B;QAE5B,KAAK,CAAC;YACJ,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAClB,kBAAkB,EAAE,GAAG,CAAC,OAAO;YAC/B,aAAa,EAAE,GAAG,CAAC,SAAS;YAC5B,mBAAmB,EAAE,GAAG,CAAC,mBAAmB;YAC5C,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;YACtC,kBAAkB,EAAE,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,IAAI;YACpF,iBAAiB,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI;YACjF,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,QAAQ;YAC7B,cAAc,EAAE,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC,sBAAsB;SACtE,CAAC,CAAC;QAdK,OAAE,GAAF,EAAE,CAA6B;IAezC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,mBAAmB,CAAC;YACnD,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,cAAc,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE;SAChD,CAAC,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3C,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,YAAY,CACpB,SAAS,CAAC,WAAW,EACrB,eAAe,IAAI,CAAC,EAAE,uDAAuD,CAC9E,CAAC;QACJ,CAAC;QAED,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;YACtC,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC;YAC7B,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,CAAC,CAAC,CAAC;gBAC1C,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC,EAAE,MAAM,CAAC,CAAC;QAEX,OAAO,CAAC,IAAI,CAAC,YAAY,GAAG;YAC1B,aAAa,EAAE,IAAI,CAAC,EAAE;YACtB,OAAO,EAAE,KAAK,IAAI,EAAE;gBAClB,aAAa,CAAC,QAAQ,CAAC,CAAC;gBACxB,OAAO,UAAU,CAAC,OAAO,EAAE,CAAC;YAC9B,CAAC;SACF,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ import { ServiceAssertionError } from '@powersync/lib-services-framework';
2
+ export function postgresTableId(id) {
3
+ if (typeof id == 'string') {
4
+ return id;
5
+ }
6
+ throw new ServiceAssertionError(`Expected string table id, got ObjectId`);
7
+ }
8
+ //# sourceMappingURL=table-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-id.js","sourceRoot":"","sources":["../../src/storage/table-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAG1E,MAAM,UAAU,eAAe,CAAC,EAAyB;IACvD,IAAI,OAAO,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,IAAI,qBAAqB,CAAC,wCAAwC,CAAC,CAAC;AAC5E,CAAC"}
@@ -1,11 +1,11 @@
1
1
  import * as t from 'ts-codec';
2
- import { hexBuffer, jsonb, pgwire_number } from '../codecs.js';
2
+ import { bigint, hexBuffer, jsonb, pgwire_number } from '../codecs.js';
3
3
  export const CurrentBucket = t.object({
4
4
  bucket: t.string,
5
5
  table: t.string,
6
6
  id: t.string
7
7
  });
8
- export const CurrentData = t.object({
8
+ export const V1CurrentData = t.object({
9
9
  buckets: jsonb(t.array(CurrentBucket)),
10
10
  data: hexBuffer,
11
11
  group_id: pgwire_number,
@@ -13,4 +13,13 @@ export const CurrentData = t.object({
13
13
  source_key: hexBuffer,
14
14
  source_table: t.string
15
15
  });
16
+ export const V3CurrentData = t.object({
17
+ buckets: jsonb(t.array(CurrentBucket)),
18
+ data: hexBuffer,
19
+ group_id: pgwire_number,
20
+ lookups: t.array(hexBuffer),
21
+ source_key: hexBuffer,
22
+ source_table: t.string,
23
+ pending_delete: t.Null.or(bigint)
24
+ });
16
25
  //# sourceMappingURL=CurrentData.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CurrentData.js","sourceRoot":"","sources":["../../../src/types/models/CurrentData.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE/D,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,MAAM,EAAE,CAAC,CAAC,MAAM;IAChB,KAAK,EAAE,CAAC,CAAC,MAAM;IACf,EAAE,EAAE,CAAC,CAAC,MAAM;CACb,CAAC,CAAC;AAKH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACtC,IAAI,EAAE,SAAS;IACf,QAAQ,EAAE,aAAa;IACvB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;IAC3B,UAAU,EAAE,SAAS;IACrB,YAAY,EAAE,CAAC,CAAC,MAAM;CACvB,CAAC,CAAC"}
1
+ {"version":3,"file":"CurrentData.js","sourceRoot":"","sources":["../../../src/types/models/CurrentData.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEvE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,MAAM,EAAE,CAAC,CAAC,MAAM;IAChB,KAAK,EAAE,CAAC,CAAC,MAAM;IACf,EAAE,EAAE,CAAC,CAAC,MAAM;CACb,CAAC,CAAC;AAKH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACtC,IAAI,EAAE,SAAS;IACf,QAAQ,EAAE,aAAa;IACvB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;IAC3B,UAAU,EAAE,SAAS;IACrB,YAAY,EAAE,CAAC,CAAC,MAAM;CACvB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACtC,IAAI,EAAE,SAAS;IACf,QAAQ,EAAE,aAAa;IACvB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;IAC3B,UAAU,EAAE,SAAS;IACrB,YAAY,EAAE,CAAC,CAAC,MAAM;IACtB,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC;CAClC,CAAC,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { framework, storage } from '@powersync/service-core';
2
2
  import * as t from 'ts-codec';
3
3
  import { bigint, pgwire_number } from '../codecs.js';
4
+ import { jsonContainerObject } from './json.js';
4
5
  export const SyncRules = t.object({
5
6
  id: pgwire_number,
6
7
  state: t.Enum(storage.SyncRuleState),
@@ -46,6 +47,16 @@ export const SyncRules = t.object({
46
47
  */
47
48
  last_fatal_error: t.Null.or(t.string),
48
49
  keepalive_op: t.Null.or(bigint),
49
- content: t.string
50
+ storage_version: t.Null.or(pgwire_number).optional(),
51
+ content: t.string,
52
+ sync_plan: t.Null.or(jsonContainerObject(t.object({
53
+ plan: t.any,
54
+ compatibility: t.object({
55
+ edition: t.number,
56
+ overrides: t.record(t.boolean),
57
+ maxTimeValuePrecision: t.number.optional()
58
+ }),
59
+ eventDescriptors: t.record(t.array(t.string))
60
+ })))
50
61
  });
51
62
  //# sourceMappingURL=SyncRules.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SyncRules.js","sourceRoot":"","sources":["../../../src/types/models/SyncRules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAErD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,EAAE,EAAE,aAAa;IACjB,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;IACpC;;;;OAIG;IACH,aAAa,EAAE,CAAC,CAAC,OAAO;IACxB;;OAEG;IACH,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACjC;;;;OAIG;IACH,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC;IAClC;;OAEG;IACH,mBAAmB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACxC;;OAEG;IACH,oBAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACzC,SAAS,EAAE,CAAC,CAAC,MAAM;IACnB;;;;OAIG;IACH,kBAAkB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC;IACpD;;;;OAIG;IACH,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC;IACnD;;OAEG;IACH,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACrC,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC;IAC/B,OAAO,EAAE,CAAC,CAAC,MAAM;CAClB,CAAC,CAAC"}
1
+ {"version":3,"file":"SyncRules.js","sourceRoot":"","sources":["../../../src/types/models/SyncRules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,EAAE,EAAE,aAAa;IACjB,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;IACpC;;;;OAIG;IACH,aAAa,EAAE,CAAC,CAAC,OAAO;IACxB;;OAEG;IACH,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACjC;;;;OAIG;IACH,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC;IAClC;;OAEG;IACH,mBAAmB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACxC;;OAEG;IACH,oBAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACzC,SAAS,EAAE,CAAC,CAAC,MAAM;IACnB;;;;OAIG;IACH,kBAAkB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC;IACpD;;;;OAIG;IACH,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC;IACnD;;OAEG;IACH,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACrC,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC;IAC/B,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE;IACpD,OAAO,EAAE,CAAC,CAAC,MAAM;IACjB,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAClB,mBAAmB,CACjB,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,GAAG;QACX,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC;YACtB,OAAO,EAAE,CAAC,CAAC,MAAM;YACjB,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9B,qBAAqB,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE;SAC3C,CAAC;QACF,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;KAC9C,CAAC,CACH,CACF;CACF,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { JsonContainer } from '@powersync/service-jsonbig';
2
+ import { codec } from 'ts-codec';
3
+ /**
4
+ * Wraps a codec to support {@link JsonContainer} values.
5
+ *
6
+ * Because our postgres client implementation wraps JSON objects in a {@link JsonContainer}, this intermediate layer is
7
+ * required to use JSON columns from Postgres in `ts-codec` models.
8
+ *
9
+ * Note that this serializes and deserializes values using {@link JSON}, so bigints are not supported.
10
+ */
11
+ export function jsonContainerObject(inner) {
12
+ return codec(inner._tag, (input) => {
13
+ return new JsonContainer(JSON.stringify(inner.encode(input)));
14
+ }, (json) => {
15
+ if (!(json instanceof JsonContainer)) {
16
+ throw new Error('Expected JsonContainer');
17
+ }
18
+ return inner.decode(JSON.parse(json.data));
19
+ });
20
+ }
21
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../../src/types/models/json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAS,KAAK,EAAE,MAAM,UAAU,CAAC;AAExC;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAO,KAAkB;IAC1D,OAAO,KAAK,CACV,KAAK,CAAC,IAAI,EACV,CAAC,KAAK,EAAE,EAAE;QACR,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChE,CAAC,EACD,CAAC,IAAI,EAAE,EAAE;QACP,IAAI,CAAC,CAAC,IAAI,YAAY,aAAa,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7C,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"bson.js","sourceRoot":"","sources":["../../src/utils/bson.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;GAGG;AAEH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,EAAqB;IACtE,oCAAoC;IACpC,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;QACvB,mDAAmD;QACnD,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;IAC1C,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"bson.js","sourceRoot":"","sources":["../../src/utils/bson.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;GAGG;AAEH,MAAM,UAAU,iBAAiB,CAAC,OAA8B,EAAE,EAAqB;IACrF,oCAAoC;IACpC,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;QACvB,mDAAmD;QACnD,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;IAC1C,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;AAC3C,CAAC"}
package/dist/utils/db.js CHANGED
@@ -5,6 +5,9 @@ export const NOTIFICATION_CHANNEL = 'powersynccheckpoints';
5
5
  * Re export for prettier to detect the tag better
6
6
  */
7
7
  export const sql = lib_postgres.sql;
8
+ /**
9
+ * Drop all Postgres storage tables used by the service, including migrations.
10
+ */
8
11
  export const dropTables = async (client) => {
9
12
  // Lock a connection for automatic schema search paths
10
13
  await client.lockConnection(async (db) => {
@@ -14,11 +17,49 @@ export const dropTables = async (client) => {
14
17
  await db.sql `DROP TABLE IF EXISTS instance`.execute();
15
18
  await db.sql `DROP TABLE IF EXISTS bucket_data`.execute();
16
19
  await db.sql `DROP TABLE IF EXISTS current_data`.execute();
20
+ await db.sql `DROP TABLE IF EXISTS v3_current_data`.execute();
17
21
  await db.sql `DROP TABLE IF EXISTS source_tables`.execute();
18
22
  await db.sql `DROP TABLE IF EXISTS write_checkpoints`.execute();
19
23
  await db.sql `DROP TABLE IF EXISTS custom_write_checkpoints`.execute();
20
24
  await db.sql `DROP SEQUENCE IF EXISTS op_id_sequence`.execute();
21
25
  await db.sql `DROP SEQUENCE IF EXISTS sync_rules_id_sequence`.execute();
26
+ await db.sql `DROP TABLE IF EXISTS migrations`.execute();
27
+ });
28
+ };
29
+ /**
30
+ * Clear all Postgres storage tables and reset sequences.
31
+ *
32
+ * Does not clear migration state.
33
+ */
34
+ export const truncateTables = async (db) => {
35
+ // Lock a connection for automatic schema search paths
36
+ await db.query({
37
+ statement: `TRUNCATE TABLE bucket_data,
38
+ bucket_parameters,
39
+ sync_rules,
40
+ instance,
41
+ current_data,
42
+ source_tables,
43
+ write_checkpoints,
44
+ custom_write_checkpoints,
45
+ connection_report_events RESTART IDENTITY CASCADE
46
+ `
47
+ }, {
48
+ // TRUNCATE if v3_current_data exists
49
+ statement: `DO $$
50
+ BEGIN
51
+ IF to_regclass('v3_current_data') IS NOT NULL THEN
52
+ EXECUTE 'TRUNCATE TABLE v3_current_data RESTART IDENTITY CASCADE';
53
+ END IF;
54
+ END $$;`
55
+ }, {
56
+ statement: `ALTER SEQUENCE IF EXISTS op_id_sequence RESTART
57
+ WITH
58
+ 1`
59
+ }, {
60
+ statement: `ALTER SEQUENCE IF EXISTS sync_rules_id_sequence RESTART
61
+ WITH
62
+ 1`
22
63
  });
23
64
  };
24
65
  //# sourceMappingURL=db.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/utils/db.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,YAAY,MAAM,iCAAiC,CAAC;AAEhE,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAAC;AAE/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAE3D;;GAEG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC;AAEpC,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,MAAmC,EAAE,EAAE;IACtE,sDAAsD;IACtD,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACvC,MAAM,EAAE,CAAC,GAAG,CAAA,kCAAkC,CAAC,OAAO,EAAE,CAAC;QACzD,MAAM,EAAE,CAAC,GAAG,CAAA,wCAAwC,CAAC,OAAO,EAAE,CAAC;QAC/D,MAAM,EAAE,CAAC,GAAG,CAAA,iCAAiC,CAAC,OAAO,EAAE,CAAC;QACxD,MAAM,EAAE,CAAC,GAAG,CAAA,+BAA+B,CAAC,OAAO,EAAE,CAAC;QACtD,MAAM,EAAE,CAAC,GAAG,CAAA,kCAAkC,CAAC,OAAO,EAAE,CAAC;QACzD,MAAM,EAAE,CAAC,GAAG,CAAA,mCAAmC,CAAC,OAAO,EAAE,CAAC;QAC1D,MAAM,EAAE,CAAC,GAAG,CAAA,oCAAoC,CAAC,OAAO,EAAE,CAAC;QAC3D,MAAM,EAAE,CAAC,GAAG,CAAA,wCAAwC,CAAC,OAAO,EAAE,CAAC;QAC/D,MAAM,EAAE,CAAC,GAAG,CAAA,+CAA+C,CAAC,OAAO,EAAE,CAAC;QACtE,MAAM,EAAE,CAAC,GAAG,CAAA,wCAAwC,CAAC,OAAO,EAAE,CAAC;QAC/D,MAAM,EAAE,CAAC,GAAG,CAAA,gDAAgD,CAAC,OAAO,EAAE,CAAC;IACzE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/utils/db.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,YAAY,MAAM,iCAAiC,CAAC;AAEhE,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAAC;AAE/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAE3D;;GAEG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC;AAEpC;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,MAAmC,EAAE,EAAE;IACtE,sDAAsD;IACtD,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACvC,MAAM,EAAE,CAAC,GAAG,CAAA,kCAAkC,CAAC,OAAO,EAAE,CAAC;QACzD,MAAM,EAAE,CAAC,GAAG,CAAA,wCAAwC,CAAC,OAAO,EAAE,CAAC;QAC/D,MAAM,EAAE,CAAC,GAAG,CAAA,iCAAiC,CAAC,OAAO,EAAE,CAAC;QACxD,MAAM,EAAE,CAAC,GAAG,CAAA,+BAA+B,CAAC,OAAO,EAAE,CAAC;QACtD,MAAM,EAAE,CAAC,GAAG,CAAA,kCAAkC,CAAC,OAAO,EAAE,CAAC;QACzD,MAAM,EAAE,CAAC,GAAG,CAAA,mCAAmC,CAAC,OAAO,EAAE,CAAC;QAC1D,MAAM,EAAE,CAAC,GAAG,CAAA,sCAAsC,CAAC,OAAO,EAAE,CAAC;QAC7D,MAAM,EAAE,CAAC,GAAG,CAAA,oCAAoC,CAAC,OAAO,EAAE,CAAC;QAC3D,MAAM,EAAE,CAAC,GAAG,CAAA,wCAAwC,CAAC,OAAO,EAAE,CAAC;QAC/D,MAAM,EAAE,CAAC,GAAG,CAAA,+CAA+C,CAAC,OAAO,EAAE,CAAC;QACtE,MAAM,EAAE,CAAC,GAAG,CAAA,wCAAwC,CAAC,OAAO,EAAE,CAAC;QAC/D,MAAM,EAAE,CAAC,GAAG,CAAA,gDAAgD,CAAC,OAAO,EAAE,CAAC;QACvE,MAAM,EAAE,CAAC,GAAG,CAAA,iCAAiC,CAAC,OAAO,EAAE,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,EAA+B,EAAE,EAAE;IACtE,sDAAsD;IACtD,MAAM,EAAE,CAAC,KAAK,CACZ;QACE,SAAS,EAAE;;;;;;;;;KASZ;KACA,EACD;QACE,qCAAqC;QACrC,SAAS,EAAE;;;;;gBAKD;KACX,EACD;QACE,SAAS,EAAE;;UAEP;KACL,EACD;QACE,SAAS,EAAE;;UAEP;KACL,CACF,CAAC;AACJ,CAAC,CAAC"}