@event-driven-io/pongo 0.17.0-beta.42 → 0.17.0-beta.43

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 (59) hide show
  1. package/dist/cli.cjs +571 -16
  2. package/dist/cli.cjs.map +1 -1
  3. package/dist/cli.js +560 -3
  4. package/dist/cli.js.map +1 -1
  5. package/dist/cloudflare-CzlFuMmZ.js +38 -0
  6. package/dist/cloudflare-CzlFuMmZ.js.map +1 -0
  7. package/dist/cloudflare-WGIFZXop.cjs +42 -0
  8. package/dist/cloudflare-WGIFZXop.cjs.map +1 -0
  9. package/dist/cloudflare.cjs +1463 -12
  10. package/dist/cloudflare.cjs.map +1 -1
  11. package/dist/cloudflare.d.cts +435 -2
  12. package/dist/cloudflare.d.ts +435 -2
  13. package/dist/cloudflare.js +1455 -3
  14. package/dist/cloudflare.js.map +1 -1
  15. package/dist/{core-5npofT4H.js → core-BW9XZXW8.js} +2 -2
  16. package/dist/{core-5npofT4H.js.map → core-BW9XZXW8.js.map} +1 -1
  17. package/dist/{core-q2eF-VHQ.cjs → core-BicrzIKX.cjs} +10 -11
  18. package/dist/{core-q2eF-VHQ.cjs.map → core-BicrzIKX.cjs.map} +1 -1
  19. package/dist/index.cjs +1477 -52
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +717 -1
  22. package/dist/index.d.ts +717 -1
  23. package/dist/index.js +1429 -4
  24. package/dist/index.js.map +1 -1
  25. package/dist/pg-BdtFllz7.cjs +399 -0
  26. package/dist/pg-BdtFllz7.cjs.map +1 -0
  27. package/dist/pg-BtUtOO8Y.js +395 -0
  28. package/dist/pg-BtUtOO8Y.js.map +1 -0
  29. package/dist/pg.cjs +1124 -15
  30. package/dist/pg.cjs.map +1 -1
  31. package/dist/pg.d.cts +430 -2
  32. package/dist/pg.d.ts +430 -2
  33. package/dist/pg.js +1113 -3
  34. package/dist/pg.js.map +1 -1
  35. package/dist/shim.cjs +554 -6
  36. package/dist/shim.cjs.map +1 -1
  37. package/dist/shim.d.cts +445 -1
  38. package/dist/shim.d.ts +445 -1
  39. package/dist/shim.js +551 -2
  40. package/dist/shim.js.map +1 -1
  41. package/dist/sqlite3-CFwH2ot3.cjs +44 -0
  42. package/dist/sqlite3-CFwH2ot3.cjs.map +1 -0
  43. package/dist/sqlite3-Dv0y-lg6.js +40 -0
  44. package/dist/sqlite3-Dv0y-lg6.js.map +1 -0
  45. package/dist/sqlite3.cjs +1463 -12
  46. package/dist/sqlite3.cjs.map +1 -1
  47. package/dist/sqlite3.d.cts +435 -2
  48. package/dist/sqlite3.d.ts +435 -2
  49. package/dist/sqlite3.js +1455 -3
  50. package/dist/sqlite3.js.map +1 -1
  51. package/package.json +2 -2
  52. package/dist/core-BHdOCUrr.js +0 -1429
  53. package/dist/core-BHdOCUrr.js.map +0 -1
  54. package/dist/core-C9SB3XMx.cjs +0 -1717
  55. package/dist/core-C9SB3XMx.cjs.map +0 -1
  56. package/dist/index-C3pnS1S_.d.cts +0 -720
  57. package/dist/index-CZOmOsQt.d.ts +0 -10
  58. package/dist/index-FXnldVnn.d.cts +0 -10
  59. package/dist/index-r7V4paf_.d.ts +0 -720
@@ -0,0 +1,395 @@
1
+ import { OperatorMap, PongoCollectionSchemaComponent, PongoDatabase, PongoDatabaseSchemaComponent, QueryOperators, expectedVersionPredicate, hasOperators, objectEntries, pongoDriverRegistry, pongoSchema } from "./index.js";
2
+ import { JSONParam, JSONSerializer, SQL, dumbo, isSQL, sqlMigration } from "@event-driven-io/dumbo";
3
+ import { PostgreSQLJSON } from "@event-driven-io/dumbo/postgresql";
4
+ import { PgDriverType, pgDumboDriver, postgreSQLMetadata } from "@event-driven-io/dumbo/pg";
5
+
6
+ //#region src/storage/postgresql/core/sqlBuilder/filter/queryOperators.ts
7
+ const handleOperator = (path, operator, value, serializer) => {
8
+ if (path === "_id" || path === "_version") return handleMetadataOperator(path, operator, value);
9
+ switch (operator) {
10
+ case "$eq": {
11
+ const field = PostgreSQLJSON.field(SQL`data`, path);
12
+ return SQL`(${field} = ${JSONParam.value(value, serializer)}::jsonb OR ${field} @> ${JSONParam.arrayContaining(value, serializer)}::jsonb)`;
13
+ }
14
+ case "$gt":
15
+ case "$gte":
16
+ case "$lt":
17
+ case "$lte":
18
+ case "$ne": return SQL`${PostgreSQLJSON.textField(SQL`data`, path)} ${SQL.plain(OperatorMap[operator])} ${value}`;
19
+ case "$in": return SQL`${PostgreSQLJSON.textField(SQL`data`, path)} = ANY (${value})`;
20
+ case "$nin": return SQL`${PostgreSQLJSON.textField(SQL`data`, path)} != ALL (${value})`;
21
+ case "$elemMatch": {
22
+ const field = PostgreSQLJSON.field(SQL`data`, path);
23
+ return SQL`EXISTS (
24
+ SELECT 1
25
+ FROM jsonb_array_elements(${SQL`CASE WHEN jsonb_typeof(${field}) = 'array' THEN ${field} ELSE '[]'::jsonb END`}) AS elem(value)
26
+ WHERE elem.value @> ${JSONParam.value(value, serializer)}::jsonb
27
+ )`;
28
+ }
29
+ case "$all": {
30
+ const serializedValue = JSONParam.value(value, serializer);
31
+ return SQL`${PostgreSQLJSON.field(SQL`data`, path)} @> ${serializedValue}::jsonb`;
32
+ }
33
+ case "$size": return SQL`jsonb_array_length(${PostgreSQLJSON.field(SQL`data`, path)}) = ${value}`;
34
+ default: throw new Error(`Unsupported operator: ${operator}`);
35
+ }
36
+ };
37
+ const handleMetadataOperator = (fieldName, operator, value) => {
38
+ switch (operator) {
39
+ case "$eq": return SQL`${SQL.plain(fieldName)} = ${value}`;
40
+ case "$gt":
41
+ case "$gte":
42
+ case "$lt":
43
+ case "$lte":
44
+ case "$ne": return SQL`${SQL.plain(fieldName)} ${SQL.plain(OperatorMap[operator])} ${value}`;
45
+ case "$in": return SQL`${SQL.plain(fieldName)} = ANY (${value})`;
46
+ case "$nin": return SQL`${SQL.plain(fieldName)} != ALL (${value})`;
47
+ default: throw new Error(`Unsupported operator: ${operator}`);
48
+ }
49
+ };
50
+
51
+ //#endregion
52
+ //#region src/storage/postgresql/core/sqlBuilder/filter/index.ts
53
+ const AND = "AND";
54
+ const OR = "OR";
55
+ const unsupportedRootOperators = [
56
+ "$text",
57
+ "$where",
58
+ "$comment"
59
+ ];
60
+ const constructFilterQuery = (filter, serializer) => {
61
+ ensureSupportedRootOperators(filter);
62
+ const parts = [];
63
+ const fieldFilterQuery = constructFieldFilterQuery(filter, serializer);
64
+ if (!SQL.check.isEmpty(fieldFilterQuery)) parts.push(fieldFilterQuery);
65
+ const orFilterQuery = constructLogicalFilterQuery(filter.$or, OR, serializer);
66
+ if (!SQL.check.isEmpty(orFilterQuery)) parts.push(orFilterQuery);
67
+ const andFilterQuery = constructLogicalFilterQuery(filter.$and, AND, serializer);
68
+ if (!SQL.check.isEmpty(andFilterQuery)) parts.push(andFilterQuery);
69
+ const norFilterQuery = constructNorFilterQuery(filter.$nor, serializer);
70
+ if (!SQL.check.isEmpty(norFilterQuery)) parts.push(norFilterQuery);
71
+ return SQL.merge(parts, ` ${AND} `);
72
+ };
73
+ const constructFieldFilterQuery = (filter, serializer) => SQL.merge(objectEntries(filter).flatMap(([key, value]) => isLogicalRootOperator(key) ? [] : [isRecord(value) ? constructComplexFilterQuery(key, value, serializer) : handleOperator(key, QueryOperators.$eq, value, serializer)]), ` ${AND} `);
74
+ const constructLogicalFilterQuery = (filters, joinOperator, serializer) => {
75
+ if (!filters?.length) return SQL.EMPTY;
76
+ const subFilterQueries = filters.reduce((queries, filter) => {
77
+ const query = constructFilterQuery(filter, serializer);
78
+ if (!SQL.check.isEmpty(query)) queries.push(query);
79
+ return queries;
80
+ }, []);
81
+ if (subFilterQueries.length === 0) return SQL.EMPTY;
82
+ if (subFilterQueries.length === 1) return wrapFilterQuery(subFilterQueries[0]);
83
+ return SQL`(${SQL.merge(subFilterQueries.map(wrapFilterQuery), ` ${joinOperator} `)})`;
84
+ };
85
+ const constructNorFilterQuery = (filters, serializer) => {
86
+ if (!filters?.length) return SQL.EMPTY;
87
+ const logicalFilterQuery = constructLogicalFilterQuery(filters, OR, serializer);
88
+ return SQL.check.isEmpty(logicalFilterQuery) ? SQL.EMPTY : SQL`NOT ${logicalFilterQuery}`;
89
+ };
90
+ const constructComplexFilterQuery = (key, value, serializer) => {
91
+ const isEquality = !hasOperators(value);
92
+ return SQL.merge(objectEntries(value).map(([nestedKey, val]) => isEquality ? handleOperator(`${key}.${nestedKey}`, QueryOperators.$eq, val, serializer) : handleOperator(key, nestedKey, val, serializer)), ` ${AND} `);
93
+ };
94
+ const wrapFilterQuery = (filterQuery) => SQL`(${filterQuery})`;
95
+ const ensureSupportedRootOperators = (filter) => {
96
+ for (const operator of unsupportedRootOperators) if (operator in filter) throw new Error(`Unsupported root operator: ${operator}`);
97
+ };
98
+ const isLogicalRootOperator = (key) => key === "$and" || key === "$nor" || key === "$or";
99
+ const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
100
+
101
+ //#endregion
102
+ //#region src/storage/postgresql/core/sqlBuilder/update/index.ts
103
+ const buildUpdateQuery = (update, serializer) => objectEntries(update).reduce((currentUpdateQuery, [op, value]) => {
104
+ switch (op) {
105
+ case "$set": return buildSetQuery(value, currentUpdateQuery, serializer);
106
+ case "$unset": return buildUnsetQuery(value, currentUpdateQuery);
107
+ case "$inc": return buildIncQuery(value, currentUpdateQuery);
108
+ case "$push": return buildPushQuery(value, currentUpdateQuery, serializer);
109
+ default: return currentUpdateQuery;
110
+ }
111
+ }, SQL`data`);
112
+ const buildSetQuery = (set, currentUpdateQuery, serializer) => SQL`${currentUpdateQuery} || ${JSONParam.value(set, serializer)}::jsonb`;
113
+ const buildUnsetQuery = (unset, currentUpdateQuery) => {
114
+ let query = currentUpdateQuery;
115
+ for (const key of Object.keys(unset)) query = SQL`${query} - ${key}`;
116
+ return query;
117
+ };
118
+ const buildIncQuery = (inc, currentUpdateQuery) => {
119
+ for (const [key, value] of Object.entries(inc)) currentUpdateQuery = typeof value === "bigint" ? SQL`jsonb_set(${currentUpdateQuery}, ${PostgreSQLJSON.path(key)}, to_jsonb((COALESCE((${PostgreSQLJSON.textField(SQL`data`, key)})::BIGINT, 0) + ${value})::TEXT), true)` : SQL`jsonb_set(${currentUpdateQuery}, ${PostgreSQLJSON.path(key)}, to_jsonb(COALESCE((${PostgreSQLJSON.textField(SQL`data`, key)})::NUMERIC, 0) + ${value}), true)`;
120
+ return currentUpdateQuery;
121
+ };
122
+ const buildPushQuery = (push, currentUpdateQuery, serializer) => {
123
+ for (const [key, value] of Object.entries(push)) {
124
+ const serializedValue = JSONParam.arrayContaining(value, serializer);
125
+ currentUpdateQuery = SQL`jsonb_set(${currentUpdateQuery}, ${PostgreSQLJSON.path(key)}, (coalesce(${PostgreSQLJSON.field(SQL`data`, key)}, '[]'::jsonb) || ${serializedValue}::jsonb), true)`;
126
+ }
127
+ return currentUpdateQuery;
128
+ };
129
+
130
+ //#endregion
131
+ //#region src/storage/postgresql/core/sqlBuilder/index.ts
132
+ const versionCheckClause = (collectionName, expectedVersion) => {
133
+ const col = SQL.identifier(collectionName);
134
+ const predicate = expectedVersionPredicate(expectedVersion);
135
+ return predicate.operator === "none" ? SQL.EMPTY : SQL`AND ${col}._version = ${predicate.value}`;
136
+ };
137
+ const createCollection = (collectionName) => SQL`
138
+ CREATE TABLE IF NOT EXISTS ${SQL.identifier(collectionName)} (
139
+ _id TEXT PRIMARY KEY,
140
+ data JSONB NOT NULL,
141
+ metadata JSONB NOT NULL DEFAULT '{}',
142
+ _version BIGINT NOT NULL DEFAULT 1,
143
+ _partition TEXT NOT NULL DEFAULT 'png_global',
144
+ _archived BOOLEAN NOT NULL DEFAULT FALSE,
145
+ _created TIMESTAMPTZ NOT NULL DEFAULT now(),
146
+ _updated TIMESTAMPTZ NOT NULL DEFAULT now()
147
+ )`;
148
+ const pongoCollectionPostgreSQLMigrations = (collectionName) => [sqlMigration(`pongoCollection:${collectionName}:001:createtable`, [createCollection(collectionName)])];
149
+ const postgresSQLBuilder = (collectionName, serializer) => ({
150
+ createCollection: () => createCollection(collectionName),
151
+ insertOne: (document) => {
152
+ const serialized = JSONParam.document(document, serializer);
153
+ const id = document._id;
154
+ const version = document._version ?? 1n;
155
+ return SQL`
156
+ INSERT INTO ${SQL.identifier(collectionName)} (_id, data, _version)
157
+ VALUES (${id}, ${serialized}, ${version}) ON CONFLICT(_id) DO NOTHING;`;
158
+ },
159
+ insertMany: (documents) => {
160
+ const values = SQL.merge(documents.map((doc) => SQL`(${doc._id}, ${JSONParam.document(doc, serializer)}, ${doc._version ?? 1n})`), ",");
161
+ return SQL`
162
+ INSERT INTO ${SQL.identifier(collectionName)} (_id, data, _version) VALUES ${values}
163
+ ON CONFLICT(_id) DO NOTHING
164
+ RETURNING _id;`;
165
+ },
166
+ insertOrReplace: (documents) => {
167
+ const col = SQL.identifier(collectionName);
168
+ return SQL`
169
+ INSERT INTO ${col} (_id, data, _version)
170
+ VALUES ${SQL.merge(documents.map((d) => SQL`(${d._id}::text, ${JSONParam.document(d, serializer)}::jsonb || jsonb_build_object('_id', ${d._id}::text) || jsonb_build_object('_version', '1'::text), 1::bigint)`), ",")}
171
+ ON CONFLICT(_id) DO UPDATE SET
172
+ data = EXCLUDED.data
173
+ || jsonb_build_object('_id', ${col}._id)
174
+ || jsonb_build_object('_version', (${col}._version + 1)::text),
175
+ _version = ${col}._version + 1
176
+ RETURNING _id, _version AS version;`;
177
+ },
178
+ updateOne: (filter, update, options) => {
179
+ const expectedVersionUpdate = versionCheckClause(collectionName, options?.expectedVersion);
180
+ const filterQuery = isSQL(filter) ? filter : constructFilterQuery(filter, serializer);
181
+ const updateQuery = isSQL(update) ? update : buildUpdateQuery(update, serializer);
182
+ return SQL`
183
+ WITH existing AS (
184
+ SELECT _id, _version as current_version
185
+ FROM ${SQL.identifier(collectionName)} ${where(filterQuery)}
186
+ LIMIT 1
187
+ ),
188
+ updated AS (
189
+ UPDATE ${SQL.identifier(collectionName)}
190
+ SET
191
+ data = ${updateQuery} || jsonb_build_object('_id', ${SQL.identifier(collectionName)}._id) || jsonb_build_object('_version', (_version + 1)::text),
192
+ _version = _version + 1
193
+ FROM existing
194
+ WHERE ${SQL.identifier(collectionName)}._id = existing._id ${expectedVersionUpdate}
195
+ RETURNING ${SQL.identifier(collectionName)}._id, ${SQL.identifier(collectionName)}._version
196
+ )
197
+ SELECT
198
+ existing._id,
199
+ COALESCE(updated._version, existing.current_version) AS version,
200
+ COUNT(existing._id) over() AS matched,
201
+ COUNT(updated._id) over() AS modified
202
+ FROM existing
203
+ LEFT JOIN updated
204
+ ON existing._id = updated._id;`;
205
+ },
206
+ replaceOne: (filter, document, options) => {
207
+ const expectedVersionUpdate = versionCheckClause(collectionName, options?.expectedVersion);
208
+ const filterQuery = isSQL(filter) ? filter : constructFilterQuery(filter, serializer);
209
+ return SQL`
210
+ WITH existing AS (
211
+ SELECT _id, _version as current_version
212
+ FROM ${SQL.identifier(collectionName)} ${where(filterQuery)}
213
+ LIMIT 1
214
+ ),
215
+ updated AS (
216
+ UPDATE ${SQL.identifier(collectionName)}
217
+ SET
218
+ data = ${JSONParam.document(document, serializer)} || jsonb_build_object('_id', ${SQL.identifier(collectionName)}._id) || jsonb_build_object('_version', (_version + 1)::text),
219
+ _version = _version + 1
220
+ FROM existing
221
+ WHERE ${SQL.identifier(collectionName)}._id = existing._id ${expectedVersionUpdate}
222
+ RETURNING ${SQL.identifier(collectionName)}._id, ${SQL.identifier(collectionName)}._version
223
+ )
224
+ SELECT
225
+ existing._id,
226
+ COALESCE(updated._version, existing.current_version) AS version,
227
+ COUNT(existing._id) over() AS matched,
228
+ COUNT(updated._id) over() AS modified
229
+ FROM existing
230
+ LEFT JOIN updated
231
+ ON existing._id = updated._id;`;
232
+ },
233
+ updateMany: (filter, update) => {
234
+ const filterQuery = isSQL(filter) ? filter : constructFilterQuery(filter, serializer);
235
+ const updateQuery = isSQL(update) ? update : buildUpdateQuery(update, serializer);
236
+ return SQL`
237
+ UPDATE ${SQL.identifier(collectionName)}
238
+ SET
239
+ data = ${updateQuery} || jsonb_build_object('_version', (_version + 1)::text),
240
+ _version = _version + 1
241
+ ${where(filterQuery)};`;
242
+ },
243
+ deleteOne: (filter, options) => {
244
+ const expectedVersionUpdate = versionCheckClause(collectionName, options?.expectedVersion);
245
+ const filterQuery = isSQL(filter) ? filter : constructFilterQuery(filter, serializer);
246
+ return SQL`
247
+ WITH existing AS (
248
+ SELECT _id
249
+ FROM ${SQL.identifier(collectionName)} ${where(filterQuery)}
250
+ LIMIT 1
251
+ ),
252
+ deleted AS (
253
+ DELETE FROM ${SQL.identifier(collectionName)}
254
+ USING existing
255
+ WHERE ${SQL.identifier(collectionName)}._id = existing._id ${expectedVersionUpdate}
256
+ RETURNING ${SQL.identifier(collectionName)}._id
257
+ )
258
+ SELECT
259
+ existing._id,
260
+ COUNT(existing._id) over() AS matched,
261
+ COUNT(deleted._id) over() AS deleted
262
+ FROM existing
263
+ LEFT JOIN deleted
264
+ ON existing._id = deleted._id;`;
265
+ },
266
+ deleteMany: (filter) => {
267
+ const filterQuery = isSQL(filter) ? filter : constructFilterQuery(filter, serializer);
268
+ return SQL`DELETE FROM ${SQL.identifier(collectionName)} ${where(filterQuery)}`;
269
+ },
270
+ replaceMany: (documents) => {
271
+ if (documents.some((d) => "_version" in d && d._version !== void 0)) return SQL`
272
+ WITH replacements(_id, data, expected_version) AS (
273
+ VALUES ${SQL.merge(documents.map((d) => {
274
+ const expectedVersion = d._version;
275
+ return expectedVersion !== void 0 ? SQL`(${d._id}::text, ${JSONParam.document(d, serializer)}::jsonb, ${expectedVersion}::bigint)` : SQL`(${d._id}::text, ${JSONParam.document(d, serializer)}::jsonb, NULL::bigint)`;
276
+ }), ",")}
277
+ )
278
+ UPDATE ${SQL.identifier(collectionName)} t
279
+ SET
280
+ data = r.data
281
+ || jsonb_build_object('_id', t._id)
282
+ || jsonb_build_object('_version', (t._version + 1)::text),
283
+ _version = t._version + 1
284
+ FROM replacements r
285
+ WHERE t._id = r._id AND (r.expected_version IS NULL OR t._version = r.expected_version)
286
+ RETURNING t._id, t._version AS version;`;
287
+ return SQL`
288
+ WITH replacements(_id, data) AS (
289
+ VALUES ${SQL.merge(documents.map((d) => SQL`(${d._id}::text, ${JSONParam.document(d, serializer)}::jsonb)`), ",")}
290
+ )
291
+ UPDATE ${SQL.identifier(collectionName)} t
292
+ SET
293
+ data = r.data
294
+ || jsonb_build_object('_id', t._id)
295
+ || jsonb_build_object('_version', (t._version + 1)::text),
296
+ _version = t._version + 1
297
+ FROM replacements r
298
+ WHERE t._id = r._id
299
+ RETURNING t._id, t._version AS version;`;
300
+ },
301
+ deleteManyByIds: (ids) => {
302
+ if (ids.some((d) => d._version !== void 0)) return SQL`
303
+ WITH targets(_id, expected_version) AS (
304
+ VALUES ${SQL.merge(ids.map((d) => SQL`(${d._id}::text, ${d._version ?? 0n}::bigint)`), ",")}
305
+ ),
306
+ deleted AS (
307
+ DELETE FROM ${SQL.identifier(collectionName)} t
308
+ USING targets r
309
+ WHERE t._id = r._id AND t._version = r.expected_version
310
+ RETURNING t._id
311
+ )
312
+ SELECT r._id,
313
+ CASE WHEN d._id IS NOT NULL THEN 1 ELSE 0 END as deleted
314
+ FROM targets r
315
+ LEFT JOIN deleted d ON r._id = d._id;`;
316
+ return SQL`
317
+ WITH targets(_id) AS (
318
+ VALUES ${SQL.merge(ids.map((d) => SQL`(${d._id}::text)`), ",")}
319
+ ),
320
+ deleted AS (
321
+ DELETE FROM ${SQL.identifier(collectionName)} t
322
+ USING targets r
323
+ WHERE t._id = r._id
324
+ RETURNING t._id
325
+ )
326
+ SELECT r._id,
327
+ CASE WHEN d._id IS NOT NULL THEN 1 ELSE 0 END as deleted
328
+ FROM targets r
329
+ LEFT JOIN deleted d ON r._id = d._id;`;
330
+ },
331
+ findOne: (filter) => {
332
+ const filterQuery = isSQL(filter) ? filter : constructFilterQuery(filter, serializer);
333
+ return SQL`SELECT data, _id, _version FROM ${SQL.identifier(collectionName)} ${where(filterQuery)} LIMIT 1;`;
334
+ },
335
+ find: (filter, options) => {
336
+ const filterQuery = isSQL(filter) ? filter : constructFilterQuery(filter, serializer);
337
+ const query = [];
338
+ query.push(SQL`SELECT data, _id, _version FROM ${SQL.identifier(collectionName)}`);
339
+ query.push(where(filterQuery));
340
+ if (options?.sort && Object.keys(options.sort).length > 0) {
341
+ const clauses = Object.entries(options.sort).map(([field, dir]) => {
342
+ const accessor = field === "_id" || field === "_version" ? SQL`${SQL.plain(field)}` : PostgreSQLJSON.field(SQL`data`, field);
343
+ return dir === 1 ? SQL`${accessor} ASC NULLS FIRST` : SQL`${accessor} DESC NULLS LAST`;
344
+ });
345
+ query.push(SQL`ORDER BY ${SQL.merge(clauses, ",")}`);
346
+ }
347
+ if (options?.limit) query.push(SQL`LIMIT ${options.limit}`);
348
+ if (options?.skip) query.push(SQL`OFFSET ${options.skip}`);
349
+ return SQL.merge([...query, SQL`;`]);
350
+ },
351
+ countDocuments: (filter) => {
352
+ const filterQuery = SQL.check.isSQL(filter) ? filter : constructFilterQuery(filter, serializer);
353
+ return SQL`SELECT COUNT(1) as count FROM ${SQL.identifier(collectionName)} ${where(filterQuery)};`;
354
+ },
355
+ rename: (newName) => SQL`ALTER TABLE ${SQL.identifier(collectionName)} RENAME TO ${SQL.identifier(newName)};`,
356
+ drop: (targetName = collectionName) => SQL`DROP TABLE IF EXISTS ${SQL.identifier(targetName)}`
357
+ });
358
+ const where = (filterQuery) => SQL.check.isEmpty(filterQuery) ? SQL.EMPTY : SQL.merge([SQL`WHERE `, filterQuery]);
359
+
360
+ //#endregion
361
+ //#region src/storage/postgresql/pg/index.ts
362
+ const pgPongoDriver = {
363
+ driverType: PgDriverType,
364
+ databaseFactory: (options) => {
365
+ const databaseName = options.databaseName ?? postgreSQLMetadata.parseDatabaseName(options.connectionString) ?? postgreSQLMetadata.defaultDatabaseName;
366
+ return PongoDatabase({
367
+ ...options,
368
+ pool: dumbo({
369
+ connectionString: options.connectionString,
370
+ driver: pgDumboDriver,
371
+ ...options.connectionOptions,
372
+ serialization: { serializer: options.serializer }
373
+ }),
374
+ schemaComponent: PongoDatabaseSchemaComponent({
375
+ driverType: PgDriverType,
376
+ collectionFactory: (schema) => PongoCollectionSchemaComponent({
377
+ driverType: PgDriverType,
378
+ definition: schema,
379
+ migrationsOrSchemaComponents: { migrations: pongoCollectionPostgreSQLMigrations(schema.name) },
380
+ sqlBuilder: postgresSQLBuilder(schema.name, options.serialization?.serializer ?? JSONSerializer)
381
+ }),
382
+ definition: options.schema?.definition ?? pongoSchema.db(databaseName, {})
383
+ }),
384
+ databaseName
385
+ });
386
+ }
387
+ };
388
+ const usePgPongoDriver = () => {
389
+ pongoDriverRegistry.register(PgDriverType, pgPongoDriver);
390
+ };
391
+ usePgPongoDriver();
392
+
393
+ //#endregion
394
+ export { pgPongoDriver as pgDriver, pgPongoDriver as pongoDriver, pongoCollectionPostgreSQLMigrations, postgresSQLBuilder, usePgPongoDriver };
395
+ //# sourceMappingURL=pg-BtUtOO8Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg-BtUtOO8Y.js","names":["dumboDriver"],"sources":["../src/storage/postgresql/core/sqlBuilder/filter/queryOperators.ts","../src/storage/postgresql/core/sqlBuilder/filter/index.ts","../src/storage/postgresql/core/sqlBuilder/update/index.ts","../src/storage/postgresql/core/sqlBuilder/index.ts","../src/storage/postgresql/pg/index.ts"],"sourcesContent":["import type { JSONSerializer } from '@event-driven-io/dumbo';\nimport { JSONParam, SQL } from '@event-driven-io/dumbo';\nimport { PostgreSQLJSON } from '@event-driven-io/dumbo/postgresql';\nimport { OperatorMap } from '../../../../../core';\n\nexport const handleOperator = (\n path: string,\n operator: string,\n value: unknown,\n serializer: JSONSerializer,\n): SQL => {\n if (path === '_id' || path === '_version') {\n return handleMetadataOperator(path, operator, value);\n }\n\n switch (operator) {\n case '$eq': {\n const field = PostgreSQLJSON.field(SQL`data`, path);\n const serializedValue = JSONParam.value(value, serializer);\n const serializedArrayValue = JSONParam.arrayContaining(value, serializer);\n\n return SQL`(${field} = ${serializedValue}::jsonb OR ${field} @> ${serializedArrayValue}::jsonb)`;\n }\n case '$gt':\n case '$gte':\n case '$lt':\n case '$lte':\n case '$ne': {\n const field = PostgreSQLJSON.textField(SQL`data`, path);\n\n return SQL`${field} ${SQL.plain(OperatorMap[operator])} ${value}`;\n }\n case '$in': {\n const field = PostgreSQLJSON.textField(SQL`data`, path);\n\n return SQL`${field} = ANY (${value})`;\n }\n case '$nin': {\n const field = PostgreSQLJSON.textField(SQL`data`, path);\n\n return SQL`${field} != ALL (${value})`;\n }\n case '$elemMatch': {\n const field = PostgreSQLJSON.field(SQL`data`, path);\n const arrayField = SQL`CASE WHEN jsonb_typeof(${field}) = 'array' THEN ${field} ELSE '[]'::jsonb END`;\n const serializedValue = JSONParam.value(value, serializer);\n return SQL`EXISTS (\n SELECT 1\n FROM jsonb_array_elements(${arrayField}) AS elem(value)\n WHERE elem.value @> ${serializedValue}::jsonb\n )`;\n }\n case '$all': {\n const serializedValue = JSONParam.value(value, serializer);\n return SQL`${PostgreSQLJSON.field(SQL`data`, path)} @> ${serializedValue}::jsonb`;\n }\n case '$size': {\n return SQL`jsonb_array_length(${PostgreSQLJSON.field(SQL`data`, path)}) = ${value}`;\n }\n default:\n throw new Error(`Unsupported operator: ${operator}`);\n }\n};\n\nconst handleMetadataOperator = (\n fieldName: string,\n operator: string,\n value: unknown,\n): SQL => {\n switch (operator) {\n case '$eq':\n return SQL`${SQL.plain(fieldName)} = ${value}`;\n case '$gt':\n case '$gte':\n case '$lt':\n case '$lte':\n case '$ne':\n return SQL`${SQL.plain(fieldName)} ${SQL.plain(OperatorMap[operator])} ${value}`;\n case '$in':\n return SQL`${SQL.plain(fieldName)} = ANY (${value})`;\n case '$nin':\n return SQL`${SQL.plain(fieldName)} != ALL (${value})`;\n default:\n throw new Error(`Unsupported operator: ${operator}`);\n }\n};\n","import type { JSONSerializer } from '@event-driven-io/dumbo';\nimport { SQL } from '@event-driven-io/dumbo';\nimport {\n hasOperators,\n objectEntries,\n QueryOperators,\n type PongoFilter,\n} from '../../../../../core';\nimport { handleOperator } from './queryOperators';\n\nexport * from './queryOperators';\n\nconst AND = 'AND';\nconst OR = 'OR';\n\nconst unsupportedRootOperators = ['$text', '$where', '$comment'] as const;\n\nexport const constructFilterQuery = <T>(\n filter: PongoFilter<T>,\n serializer: JSONSerializer,\n): SQL => {\n ensureSupportedRootOperators(filter);\n const parts: SQL[] = [];\n\n const fieldFilterQuery = constructFieldFilterQuery(filter, serializer);\n if (!SQL.check.isEmpty(fieldFilterQuery)) {\n parts.push(fieldFilterQuery);\n }\n\n const orFilterQuery = constructLogicalFilterQuery(filter.$or, OR, serializer);\n if (!SQL.check.isEmpty(orFilterQuery)) {\n parts.push(orFilterQuery);\n }\n\n const andFilterQuery = constructLogicalFilterQuery(\n filter.$and,\n AND,\n serializer,\n );\n if (!SQL.check.isEmpty(andFilterQuery)) {\n parts.push(andFilterQuery);\n }\n\n const norFilterQuery = constructNorFilterQuery(filter.$nor, serializer);\n if (!SQL.check.isEmpty(norFilterQuery)) {\n parts.push(norFilterQuery);\n }\n\n return SQL.merge(parts, ` ${AND} `);\n};\n\nconst constructFieldFilterQuery = <T>(\n filter: PongoFilter<T>,\n serializer: JSONSerializer,\n): SQL =>\n SQL.merge(\n objectEntries(filter).flatMap(([key, value]) =>\n isLogicalRootOperator(key)\n ? []\n : [\n isRecord(value)\n ? constructComplexFilterQuery(key, value, serializer)\n : handleOperator(key, QueryOperators.$eq, value, serializer),\n ],\n ),\n ` ${AND} `,\n );\n\nconst constructLogicalFilterQuery = <T>(\n filters: PongoFilter<T>[] | undefined,\n joinOperator: typeof AND | typeof OR,\n serializer: JSONSerializer,\n): SQL => {\n if (!filters?.length) {\n return SQL.EMPTY;\n }\n\n const subFilterQueries = filters.reduce<SQL[]>((queries, filter) => {\n const query = constructFilterQuery(filter, serializer);\n if (!SQL.check.isEmpty(query)) {\n queries.push(query);\n }\n\n return queries;\n }, []);\n\n if (subFilterQueries.length === 0) {\n return SQL.EMPTY;\n }\n\n if (subFilterQueries.length === 1) {\n return wrapFilterQuery(subFilterQueries[0]!);\n }\n\n return SQL`(${SQL.merge(subFilterQueries.map(wrapFilterQuery), ` ${joinOperator} `)})`;\n};\n\nconst constructNorFilterQuery = <T>(\n filters: PongoFilter<T>[] | undefined,\n serializer: JSONSerializer,\n): SQL => {\n if (!filters?.length) {\n return SQL.EMPTY;\n }\n\n const logicalFilterQuery = constructLogicalFilterQuery(\n filters,\n OR,\n serializer,\n );\n return SQL.check.isEmpty(logicalFilterQuery)\n ? SQL.EMPTY\n : SQL`NOT ${logicalFilterQuery}`;\n};\n\nconst constructComplexFilterQuery = (\n key: string,\n value: Record<string, unknown>,\n serializer: JSONSerializer,\n): SQL => {\n const isEquality = !hasOperators(value);\n\n return SQL.merge(\n objectEntries(value).map(([nestedKey, val]) =>\n isEquality\n ? handleOperator(\n `${key}.${nestedKey}`,\n QueryOperators.$eq,\n val,\n serializer,\n )\n : handleOperator(key, nestedKey, val, serializer),\n ),\n ` ${AND} `,\n );\n};\n\nconst wrapFilterQuery = (filterQuery: SQL): SQL => SQL`(${filterQuery})`;\n\nconst ensureSupportedRootOperators = (filter: object): void => {\n for (const operator of unsupportedRootOperators) {\n if (operator in filter) {\n throw new Error(`Unsupported root operator: ${operator}`);\n }\n }\n};\n\nconst isLogicalRootOperator = (key: string): key is '$and' | '$nor' | '$or' =>\n key === '$and' || key === '$nor' || key === '$or';\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n value !== null && typeof value === 'object' && !Array.isArray(value);\n","import type { JSONSerializer } from '@event-driven-io/dumbo';\nimport { JSONParam, SQL } from '@event-driven-io/dumbo';\nimport { PostgreSQLJSON } from '@event-driven-io/dumbo/postgresql';\nimport {\n objectEntries,\n type $inc,\n type $push,\n type $set,\n type $unset,\n type PongoUpdate,\n} from '../../../../../core';\n\nexport const buildUpdateQuery = <T>(\n update: PongoUpdate<T>,\n serializer: JSONSerializer,\n): SQL =>\n objectEntries(update).reduce(\n (currentUpdateQuery, [op, value]) => {\n switch (op) {\n case '$set':\n return buildSetQuery(value, currentUpdateQuery, serializer);\n case '$unset':\n return buildUnsetQuery(value, currentUpdateQuery);\n case '$inc':\n return buildIncQuery(value, currentUpdateQuery);\n case '$push':\n return buildPushQuery(value, currentUpdateQuery, serializer);\n default:\n return currentUpdateQuery;\n }\n },\n SQL`data`,\n );\n\nexport const buildSetQuery = <T>(\n set: $set<T>,\n currentUpdateQuery: SQL,\n serializer: JSONSerializer,\n): SQL =>\n SQL`${currentUpdateQuery} || ${JSONParam.value(set, serializer)}::jsonb`;\n\nexport const buildUnsetQuery = <T>(\n unset: $unset<T>,\n currentUpdateQuery: SQL,\n): SQL => {\n let query = currentUpdateQuery;\n for (const key of Object.keys(unset)) {\n query = SQL`${query} - ${key}`;\n }\n return query;\n};\n\nexport const buildIncQuery = <T>(\n inc: $inc<T>,\n currentUpdateQuery: SQL,\n): SQL => {\n for (const [key, value] of Object.entries(inc)) {\n currentUpdateQuery =\n typeof value === 'bigint'\n ? SQL`jsonb_set(${currentUpdateQuery}, ${PostgreSQLJSON.path(key)}, to_jsonb((COALESCE((${PostgreSQLJSON.textField(SQL`data`, key)})::BIGINT, 0) + ${value})::TEXT), true)`\n : SQL`jsonb_set(${currentUpdateQuery}, ${PostgreSQLJSON.path(key)}, to_jsonb(COALESCE((${PostgreSQLJSON.textField(SQL`data`, key)})::NUMERIC, 0) + ${value}), true)`;\n }\n return currentUpdateQuery;\n};\n\nexport const buildPushQuery = <T>(\n push: $push<T>,\n currentUpdateQuery: SQL,\n serializer: JSONSerializer,\n): SQL => {\n for (const [key, value] of Object.entries(push)) {\n const serializedValue = JSONParam.arrayContaining(value, serializer);\n currentUpdateQuery = SQL`jsonb_set(${currentUpdateQuery}, ${PostgreSQLJSON.path(key)}, (coalesce(${PostgreSQLJSON.field(SQL`data`, key)}, '[]'::jsonb) || ${serializedValue}::jsonb), true)`;\n }\n return currentUpdateQuery;\n};\n","import type { JSONSerializer } from '@event-driven-io/dumbo';\nimport { isSQL, JSONParam, SQL, sqlMigration } from '@event-driven-io/dumbo';\nimport { PostgreSQLJSON } from '@event-driven-io/dumbo/postgresql';\nimport {\n expectedVersionPredicate,\n type DeleteOneOptions,\n type ExpectedDocumentVersion,\n type FindOptions,\n type OptionalUnlessRequiredIdAndVersion,\n type PongoCollectionSQLBuilder,\n type PongoFilter,\n type PongoUpdate,\n type ReplaceOneOptions,\n type UpdateOneOptions,\n type WithId,\n type WithIdAndVersion,\n type WithoutId,\n} from '../../../../core';\nimport { constructFilterQuery } from './filter';\nimport { buildUpdateQuery } from './update';\n\nconst versionCheckClause = (\n collectionName: string,\n expectedVersion: ExpectedDocumentVersion | undefined,\n): SQL => {\n const col = SQL.identifier(collectionName);\n const predicate = expectedVersionPredicate(expectedVersion);\n return predicate.operator === 'none'\n ? SQL.EMPTY\n : SQL`AND ${col}._version = ${predicate.value}`;\n};\n\nconst createCollection = (collectionName: string): SQL =>\n SQL`\n CREATE TABLE IF NOT EXISTS ${SQL.identifier(collectionName)} (\n _id TEXT PRIMARY KEY, \n data JSONB NOT NULL, \n metadata JSONB NOT NULL DEFAULT '{}',\n _version BIGINT NOT NULL DEFAULT 1,\n _partition TEXT NOT NULL DEFAULT 'png_global',\n _archived BOOLEAN NOT NULL DEFAULT FALSE,\n _created TIMESTAMPTZ NOT NULL DEFAULT now(),\n _updated TIMESTAMPTZ NOT NULL DEFAULT now()\n )`;\n\nexport const pongoCollectionPostgreSQLMigrations = (collectionName: string) => [\n sqlMigration(`pongoCollection:${collectionName}:001:createtable`, [\n createCollection(collectionName),\n ]),\n];\n\nexport const postgresSQLBuilder = (\n collectionName: string,\n serializer: JSONSerializer,\n): PongoCollectionSQLBuilder => ({\n createCollection: (): SQL => createCollection(collectionName),\n insertOne: <T>(document: OptionalUnlessRequiredIdAndVersion<T>): SQL => {\n const serialized = JSONParam.document(document, serializer);\n const id = document._id;\n const version = document._version ?? 1n;\n\n return SQL`\n INSERT INTO ${SQL.identifier(collectionName)} (_id, data, _version) \n VALUES (${id}, ${serialized}, ${version}) ON CONFLICT(_id) DO NOTHING;`;\n },\n insertMany: <T>(documents: OptionalUnlessRequiredIdAndVersion<T>[]): SQL => {\n const values = SQL.merge(\n documents.map(\n (doc) =>\n SQL`(${doc._id}, ${JSONParam.document(doc, serializer)}, ${doc._version ?? 1n})`,\n ),\n ',',\n );\n\n return SQL`\n INSERT INTO ${SQL.identifier(collectionName)} (_id, data, _version) VALUES ${values}\n ON CONFLICT(_id) DO NOTHING\n RETURNING _id;`;\n },\n insertOrReplace: <T>(documents: Array<WithId<T>>): SQL => {\n const col = SQL.identifier(collectionName);\n const values = SQL.merge(\n documents.map(\n (d) =>\n SQL`(${d._id}::text, ${JSONParam.document(d, serializer)}::jsonb || jsonb_build_object('_id', ${d._id}::text) || jsonb_build_object('_version', '1'::text), 1::bigint)`,\n ),\n ',',\n );\n\n return SQL`\n INSERT INTO ${col} (_id, data, _version)\n VALUES ${values}\n ON CONFLICT(_id) DO UPDATE SET\n data = EXCLUDED.data\n || jsonb_build_object('_id', ${col}._id)\n || jsonb_build_object('_version', (${col}._version + 1)::text),\n _version = ${col}._version + 1\n RETURNING _id, _version AS version;`;\n },\n updateOne: <T>(\n filter: PongoFilter<T> | SQL,\n update: PongoUpdate<T> | SQL,\n options?: UpdateOneOptions,\n ): SQL => {\n const expectedVersionUpdate = versionCheckClause(\n collectionName,\n options?.expectedVersion,\n );\n\n const filterQuery = isSQL(filter)\n ? filter\n : constructFilterQuery(filter, serializer);\n const updateQuery = isSQL(update)\n ? update\n : buildUpdateQuery(update, serializer);\n\n return SQL`\n WITH existing AS (\n SELECT _id, _version as current_version\n FROM ${SQL.identifier(collectionName)} ${where(filterQuery)}\n LIMIT 1\n ),\n updated AS (\n UPDATE ${SQL.identifier(collectionName)} \n SET \n data = ${updateQuery} || jsonb_build_object('_id', ${SQL.identifier(collectionName)}._id) || jsonb_build_object('_version', (_version + 1)::text),\n _version = _version + 1\n FROM existing \n WHERE ${SQL.identifier(collectionName)}._id = existing._id ${expectedVersionUpdate}\n RETURNING ${SQL.identifier(collectionName)}._id, ${SQL.identifier(collectionName)}._version\n )\n SELECT \n existing._id,\n COALESCE(updated._version, existing.current_version) AS version,\n COUNT(existing._id) over() AS matched,\n COUNT(updated._id) over() AS modified\n FROM existing\n LEFT JOIN updated \n ON existing._id = updated._id;`;\n },\n replaceOne: <T>(\n filter: PongoFilter<T> | SQL,\n document: WithoutId<T>,\n options?: ReplaceOneOptions,\n ): SQL => {\n const expectedVersionUpdate = versionCheckClause(\n collectionName,\n options?.expectedVersion,\n );\n\n const filterQuery = isSQL(filter)\n ? filter\n : constructFilterQuery(filter, serializer);\n\n return SQL`\n WITH existing AS (\n SELECT _id, _version as current_version\n FROM ${SQL.identifier(collectionName)} ${where(filterQuery)}\n LIMIT 1\n ),\n updated AS (\n UPDATE ${SQL.identifier(collectionName)} \n SET \n data = ${JSONParam.document(document, serializer)} || jsonb_build_object('_id', ${SQL.identifier(collectionName)}._id) || jsonb_build_object('_version', (_version + 1)::text),\n _version = _version + 1\n FROM existing \n WHERE ${SQL.identifier(collectionName)}._id = existing._id ${expectedVersionUpdate}\n RETURNING ${SQL.identifier(collectionName)}._id, ${SQL.identifier(collectionName)}._version\n )\n SELECT \n existing._id,\n COALESCE(updated._version, existing.current_version) AS version,\n COUNT(existing._id) over() AS matched,\n COUNT(updated._id) over() AS modified\n FROM existing\n LEFT JOIN updated \n ON existing._id = updated._id;`;\n },\n updateMany: <T>(\n filter: PongoFilter<T> | SQL,\n update: PongoUpdate<T> | SQL,\n ): SQL => {\n const filterQuery = isSQL(filter)\n ? filter\n : constructFilterQuery(filter, serializer);\n const updateQuery = isSQL(update)\n ? update\n : buildUpdateQuery(update, serializer);\n\n return SQL`\n UPDATE ${SQL.identifier(collectionName)} \n SET \n data = ${updateQuery} || jsonb_build_object('_version', (_version + 1)::text),\n _version = _version + 1\n ${where(filterQuery)};`;\n },\n deleteOne: <T>(\n filter: PongoFilter<T> | SQL,\n options?: DeleteOneOptions,\n ): SQL => {\n const expectedVersionUpdate = versionCheckClause(\n collectionName,\n options?.expectedVersion,\n );\n\n const filterQuery = isSQL(filter)\n ? filter\n : constructFilterQuery(filter, serializer);\n\n return SQL`\n WITH existing AS (\n SELECT _id\n FROM ${SQL.identifier(collectionName)} ${where(filterQuery)}\n LIMIT 1\n ),\n deleted AS (\n DELETE FROM ${SQL.identifier(collectionName)}\n USING existing\n WHERE ${SQL.identifier(collectionName)}._id = existing._id ${expectedVersionUpdate}\n RETURNING ${SQL.identifier(collectionName)}._id\n )\n SELECT \n existing._id,\n COUNT(existing._id) over() AS matched,\n COUNT(deleted._id) over() AS deleted\n FROM existing\n LEFT JOIN deleted \n ON existing._id = deleted._id;`;\n },\n deleteMany: <T>(filter: PongoFilter<T> | SQL): SQL => {\n const filterQuery = isSQL(filter)\n ? filter\n : constructFilterQuery(filter, serializer);\n\n return SQL`DELETE FROM ${SQL.identifier(collectionName)} ${where(filterQuery)}`;\n },\n replaceMany: <T>(\n documents: Array<WithIdAndVersion<T>> | Array<WithId<T>>,\n ): SQL => {\n const hasVersions = documents.some(\n (d) => '_version' in d && d._version !== undefined,\n );\n\n if (hasVersions) {\n const values = SQL.merge(\n documents.map((d) => {\n const expectedVersion = (d as WithIdAndVersion<T>)._version;\n return expectedVersion !== undefined\n ? SQL`(${d._id}::text, ${JSONParam.document(d, serializer)}::jsonb, ${expectedVersion}::bigint)`\n : SQL`(${d._id}::text, ${JSONParam.document(d, serializer)}::jsonb, NULL::bigint)`;\n }),\n ',',\n );\n return SQL`\n WITH replacements(_id, data, expected_version) AS (\n VALUES ${values}\n )\n UPDATE ${SQL.identifier(collectionName)} t\n SET\n data = r.data\n || jsonb_build_object('_id', t._id)\n || jsonb_build_object('_version', (t._version + 1)::text),\n _version = t._version + 1\n FROM replacements r\n WHERE t._id = r._id AND (r.expected_version IS NULL OR t._version = r.expected_version)\n RETURNING t._id, t._version AS version;`;\n }\n\n const values = SQL.merge(\n documents.map(\n (d) =>\n SQL`(${d._id}::text, ${JSONParam.document(d, serializer)}::jsonb)`,\n ),\n ',',\n );\n return SQL`\n WITH replacements(_id, data) AS (\n VALUES ${values}\n )\n UPDATE ${SQL.identifier(collectionName)} t\n SET\n data = r.data\n || jsonb_build_object('_id', t._id)\n || jsonb_build_object('_version', (t._version + 1)::text),\n _version = t._version + 1\n FROM replacements r\n WHERE t._id = r._id\n RETURNING t._id, t._version AS version;`;\n },\n deleteManyByIds: (ids: Array<{ _id: string; _version?: bigint }>): SQL => {\n const hasVersions = ids.some((d) => d._version !== undefined);\n\n if (hasVersions) {\n const values = SQL.merge(\n ids.map((d) => SQL`(${d._id}::text, ${d._version ?? 0n}::bigint)`),\n ',',\n );\n\n return SQL`\n WITH targets(_id, expected_version) AS (\n VALUES ${values}\n ),\n deleted AS (\n DELETE FROM ${SQL.identifier(collectionName)} t\n USING targets r\n WHERE t._id = r._id AND t._version = r.expected_version\n RETURNING t._id\n )\n SELECT r._id,\n CASE WHEN d._id IS NOT NULL THEN 1 ELSE 0 END as deleted\n FROM targets r\n LEFT JOIN deleted d ON r._id = d._id;`;\n }\n\n const values = SQL.merge(\n ids.map((d) => SQL`(${d._id}::text)`),\n ',',\n );\n\n return SQL`\n WITH targets(_id) AS (\n VALUES ${values}\n ),\n deleted AS (\n DELETE FROM ${SQL.identifier(collectionName)} t\n USING targets r\n WHERE t._id = r._id\n RETURNING t._id\n )\n SELECT r._id,\n CASE WHEN d._id IS NOT NULL THEN 1 ELSE 0 END as deleted\n FROM targets r\n LEFT JOIN deleted d ON r._id = d._id;`;\n },\n findOne: <T>(filter: PongoFilter<T> | SQL): SQL => {\n const filterQuery = isSQL(filter)\n ? filter\n : constructFilterQuery(filter, serializer);\n\n return SQL`SELECT data, _id, _version FROM ${SQL.identifier(collectionName)} ${where(filterQuery)} LIMIT 1;`;\n },\n find: <T>(filter: PongoFilter<T> | SQL, options?: FindOptions): SQL => {\n const filterQuery = isSQL(filter)\n ? filter\n : constructFilterQuery(filter, serializer);\n const query: SQL[] = [];\n\n query.push(\n SQL`SELECT data, _id, _version FROM ${SQL.identifier(collectionName)}`,\n );\n\n query.push(where(filterQuery));\n\n if (options?.sort && Object.keys(options.sort).length > 0) {\n const clauses = Object.entries(options.sort).map(([field, dir]) => {\n const isMetadata = field === '_id' || field === '_version';\n // _id and _version are native columns, not JSON fields.\n // Use -> / #> (returns jsonb) rather than ->> / #>> (returns text) so\n // that numeric fields are sorted numerically, not lexicographically.\n const accessor = isMetadata\n ? SQL`${SQL.plain(field)}`\n : PostgreSQLJSON.field(SQL`data`, field);\n // Match MongoDB's null ordering: missing/null values sort first on ASC,\n // last on DESC. PostgreSQL's default is the opposite for ASC (NULLS LAST).\n return dir === 1\n ? SQL`${accessor} ASC NULLS FIRST`\n : SQL`${accessor} DESC NULLS LAST`;\n });\n query.push(SQL`ORDER BY ${SQL.merge(clauses, ',')}`);\n }\n\n if (options?.limit) {\n query.push(SQL`LIMIT ${options.limit}`);\n }\n\n if (options?.skip) {\n query.push(SQL`OFFSET ${options.skip}`);\n }\n\n return SQL.merge([...query, SQL`;`]);\n },\n countDocuments: <T>(filter: PongoFilter<T> | SQL): SQL => {\n const filterQuery = SQL.check.isSQL(filter)\n ? filter\n : constructFilterQuery(filter, serializer);\n return SQL`SELECT COUNT(1) as count FROM ${SQL.identifier(collectionName)} ${where(filterQuery)};`;\n },\n rename: (newName: string): SQL =>\n SQL`ALTER TABLE ${SQL.identifier(collectionName)} RENAME TO ${SQL.identifier(newName)};`,\n drop: (targetName: string = collectionName): SQL =>\n SQL`DROP TABLE IF EXISTS ${SQL.identifier(targetName)}`,\n});\n\nconst where = (filterQuery: SQL): SQL =>\n SQL.check.isEmpty(filterQuery)\n ? SQL.EMPTY\n : SQL.merge([SQL`WHERE `, filterQuery]);\n","import { dumbo, JSONSerializer } from '@event-driven-io/dumbo';\nimport {\n pgDumboDriver as dumboDriver,\n PgDriverType,\n postgreSQLMetadata,\n type PgConnection,\n} from '@event-driven-io/dumbo/pg';\nimport type pg from 'pg';\nimport {\n PongoCollectionSchemaComponent,\n PongoDatabase,\n PongoDatabaseSchemaComponent,\n pongoDriverRegistry,\n pongoSchema,\n type PongoDb,\n type PongoDriver,\n type PongoDriverOptions,\n} from '../../../core';\nimport {\n pongoCollectionPostgreSQLMigrations,\n postgresSQLBuilder,\n} from '../core';\n\nexport type PgPongoClientOptions =\n PooledPongoClientOptions | NotPooledPongoOptions;\n\nexport type PooledPongoClientOptions =\n | {\n pool: pg.Pool;\n }\n | {\n pooled: true;\n }\n | {\n pool: pg.Pool;\n pooled: true;\n }\n | object;\n\nexport type NotPooledPongoOptions =\n | {\n client: pg.Client;\n }\n | {\n pooled: false;\n }\n | {\n client: pg.Client;\n pooled: false;\n }\n | {\n connection: PgConnection;\n pooled?: false;\n };\n\ntype PgDatabaseDriverOptions = PongoDriverOptions<PgPongoClientOptions> & {\n databaseName?: string | undefined;\n connectionString: string;\n};\n\nconst pgPongoDriver: PongoDriver<\n PongoDb<PgDriverType>,\n PgDatabaseDriverOptions\n> = {\n driverType: PgDriverType,\n databaseFactory: (options) => {\n const databaseName =\n options.databaseName ??\n postgreSQLMetadata.parseDatabaseName(options.connectionString) ??\n postgreSQLMetadata.defaultDatabaseName;\n\n return PongoDatabase({\n ...options,\n pool: dumbo({\n connectionString: options.connectionString,\n driver: dumboDriver,\n ...options.connectionOptions,\n serialization: { serializer: options.serializer },\n }),\n schemaComponent: PongoDatabaseSchemaComponent({\n driverType: PgDriverType,\n collectionFactory: (schema) =>\n PongoCollectionSchemaComponent({\n driverType: PgDriverType,\n definition: schema,\n migrationsOrSchemaComponents: {\n migrations: pongoCollectionPostgreSQLMigrations(schema.name),\n },\n sqlBuilder: postgresSQLBuilder(\n schema.name,\n options.serialization?.serializer ?? JSONSerializer,\n ),\n }),\n definition:\n options.schema?.definition ?? pongoSchema.db(databaseName, {}),\n }),\n databaseName,\n });\n },\n};\n\nexport const usePgPongoDriver = () => {\n pongoDriverRegistry.register(PgDriverType, pgPongoDriver);\n};\n\nusePgPongoDriver();\n\nexport { pgPongoDriver as pgDriver, pgPongoDriver as pongoDriver };\n"],"mappings":"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"}