@event-driven-io/pongo 0.17.0-beta.34 → 0.17.0-beta.36

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 (61) hide show
  1. package/dist/cli.cjs +311 -494
  2. package/dist/cli.cjs.map +1 -1
  3. package/dist/cli.d.cts +4 -4
  4. package/dist/cli.d.ts +4 -3
  5. package/dist/cli.js +279 -494
  6. package/dist/cli.js.map +1 -1
  7. package/dist/cloudflare.cjs +36 -48
  8. package/dist/cloudflare.cjs.map +1 -1
  9. package/dist/cloudflare.d.cts +7 -7
  10. package/dist/cloudflare.d.ts +7 -7
  11. package/dist/cloudflare.js +29 -47
  12. package/dist/cloudflare.js.map +1 -1
  13. package/dist/core-CwxxuUAn.cjs +1590 -0
  14. package/dist/core-CwxxuUAn.cjs.map +1 -0
  15. package/dist/core-D_iZiiYe.js +1308 -0
  16. package/dist/core-D_iZiiYe.js.map +1 -0
  17. package/dist/core-DwoTLYbR.cjs +319 -0
  18. package/dist/core-DwoTLYbR.cjs.map +1 -0
  19. package/dist/core-fsJmsQDa.js +307 -0
  20. package/dist/core-fsJmsQDa.js.map +1 -0
  21. package/dist/index-DMq6F3x9.d.ts +705 -0
  22. package/dist/index-Du_IHXAj.d.ts +10 -0
  23. package/dist/index-ZKOB86ub.d.cts +10 -0
  24. package/dist/index-qeC-p0Tq.d.cts +705 -0
  25. package/dist/index.cjs +61 -118
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +11 -130
  28. package/dist/index.d.ts +11 -130
  29. package/dist/index.js +14 -119
  30. package/dist/index.js.map +1 -1
  31. package/dist/pg.cjs +214 -320
  32. package/dist/pg.cjs.map +1 -1
  33. package/dist/pg.d.cts +24 -22
  34. package/dist/pg.d.ts +24 -22
  35. package/dist/pg.js +209 -321
  36. package/dist/pg.js.map +1 -1
  37. package/dist/shim.cjs +281 -367
  38. package/dist/shim.cjs.map +1 -1
  39. package/dist/shim.d.cts +140 -137
  40. package/dist/shim.d.ts +140 -137
  41. package/dist/shim.js +275 -366
  42. package/dist/shim.js.map +1 -1
  43. package/dist/sqlite3.cjs +41 -56
  44. package/dist/sqlite3.cjs.map +1 -1
  45. package/dist/sqlite3.d.cts +9 -9
  46. package/dist/sqlite3.d.ts +9 -9
  47. package/dist/sqlite3.js +35 -56
  48. package/dist/sqlite3.js.map +1 -1
  49. package/package.json +15 -15
  50. package/dist/chunk-OJVG4KXA.js +0 -399
  51. package/dist/chunk-OJVG4KXA.js.map +0 -1
  52. package/dist/chunk-TYTEQJBC.cjs +0 -1583
  53. package/dist/chunk-TYTEQJBC.cjs.map +0 -1
  54. package/dist/chunk-U4NNEXNH.js +0 -1583
  55. package/dist/chunk-U4NNEXNH.js.map +0 -1
  56. package/dist/chunk-UP6HTRMM.cjs +0 -399
  57. package/dist/chunk-UP6HTRMM.cjs.map +0 -1
  58. package/dist/index-DHszkVjP.d.ts +0 -8
  59. package/dist/index-DLDCIBgH.d.cts +0 -8
  60. package/dist/pongoTransactionCache-BsigBOq1.d.cts +0 -556
  61. package/dist/pongoTransactionCache-BsigBOq1.d.ts +0 -556
@@ -0,0 +1,1308 @@
1
+ import { LRUCache } from "lru-cache";
2
+ import { JSONSerializer, getDatabaseMetadata, mapColumnToBigint, mapColumnToJSON, runSQLMigrations, schemaComponent, single } from "@event-driven-io/dumbo";
3
+ import { v7 } from "uuid";
4
+
5
+ //#region src/core/cache/pongoCacheWrapper.ts
6
+ const pongoCacheWrapper = (options) => {
7
+ const { provider, hooks } = options;
8
+ const onError = (error, operation) => {
9
+ hooks?.onError?.(error, operation);
10
+ };
11
+ let isClosed = false;
12
+ return {
13
+ cacheType: provider.cacheType,
14
+ async get(key) {
15
+ try {
16
+ const result = await provider.get(key);
17
+ if (result !== void 0) hooks?.onHit?.(key);
18
+ else hooks?.onMiss?.(key);
19
+ return result;
20
+ } catch (error) {
21
+ onError(error, "get");
22
+ hooks?.onMiss?.(key);
23
+ return;
24
+ }
25
+ },
26
+ async getMany(keys) {
27
+ try {
28
+ return await provider.getMany(keys);
29
+ } catch (error) {
30
+ onError(error, "getMany");
31
+ return [];
32
+ }
33
+ },
34
+ async set(key, value) {
35
+ try {
36
+ await provider.set(key, value);
37
+ } catch (error) {
38
+ onError(error, "set");
39
+ }
40
+ },
41
+ async setMany(entries) {
42
+ try {
43
+ await provider.setMany(entries);
44
+ } catch (error) {
45
+ onError(error, "setMany");
46
+ }
47
+ },
48
+ async update(key, updater) {
49
+ try {
50
+ await provider.update(key, updater);
51
+ } catch (error) {
52
+ onError(error, "update");
53
+ }
54
+ },
55
+ async updateMany(keys, updater) {
56
+ try {
57
+ await provider.updateMany(keys, updater);
58
+ } catch (error) {
59
+ onError(error, "updateMany");
60
+ }
61
+ },
62
+ async delete(key) {
63
+ try {
64
+ await provider.delete(key);
65
+ hooks?.onEvict?.(key);
66
+ } catch (error) {
67
+ onError(error, "delete");
68
+ }
69
+ },
70
+ async deleteMany(keys) {
71
+ try {
72
+ await provider.deleteMany(keys);
73
+ for (const key of keys) hooks?.onEvict?.(key);
74
+ } catch (error) {
75
+ onError(error, "deleteMany");
76
+ }
77
+ },
78
+ clear() {
79
+ return provider.clear();
80
+ },
81
+ close() {
82
+ if (isClosed) return;
83
+ isClosed = true;
84
+ return provider.close();
85
+ }
86
+ };
87
+ };
88
+
89
+ //#endregion
90
+ //#region src/core/cache/providers/identityMapCache.ts
91
+ const identityMapCache = () => {
92
+ const store = /* @__PURE__ */ new Map();
93
+ return {
94
+ cacheType: "pongo:cache:identity-map",
95
+ get: (key) => Promise.resolve(store.has(key) ? store.get(key) : void 0),
96
+ getMany: (keys) => keys.map((k) => store.has(k) ? store.get(k) : void 0),
97
+ set: (key, value) => {
98
+ store.set(key, value);
99
+ },
100
+ setMany: (entries) => {
101
+ for (const { key, value } of entries) store.set(key, value);
102
+ },
103
+ update: (key, _updater) => {
104
+ store.delete(key);
105
+ },
106
+ updateMany: (keys, _updater) => {
107
+ for (const key of keys) store.delete(key);
108
+ },
109
+ delete: (key) => {
110
+ store.delete(key);
111
+ },
112
+ deleteMany: (keys) => {
113
+ for (const key of keys) store.delete(key);
114
+ },
115
+ clear: () => {
116
+ store.clear();
117
+ },
118
+ close: () => {
119
+ store.clear();
120
+ }
121
+ };
122
+ };
123
+
124
+ //#endregion
125
+ //#region src/core/cache/providers/lruCache.ts
126
+ const defaultLRUCacheOptions = { max: 1e3 };
127
+ const lruCache = (options) => {
128
+ const cache = new LRUCache({
129
+ ...defaultLRUCacheOptions,
130
+ ...options
131
+ });
132
+ return {
133
+ cacheType: "pongo:cache:lru",
134
+ get: (key) => {
135
+ const entry = cache.get(key);
136
+ if (entry === void 0) return void 0;
137
+ return entry.doc;
138
+ },
139
+ getMany: (keys) => keys.map((k) => {
140
+ const entry = cache.get(k);
141
+ if (entry === void 0) return void 0;
142
+ return entry.doc;
143
+ }),
144
+ set: (key, value) => {
145
+ cache.set(key, { doc: value });
146
+ },
147
+ setMany: (entries) => {
148
+ for (const { key, value } of entries) cache.set(key, { doc: value });
149
+ },
150
+ update: (key, _updater) => {
151
+ cache.delete(key);
152
+ },
153
+ updateMany(keys, _updater) {
154
+ for (const key of keys) cache.delete(key);
155
+ },
156
+ delete: (key) => {
157
+ cache.delete(key);
158
+ },
159
+ deleteMany: (keys) => {
160
+ for (const key of keys) cache.delete(key);
161
+ },
162
+ clear: () => {
163
+ cache.clear();
164
+ },
165
+ close: () => {
166
+ cache.clear();
167
+ }
168
+ };
169
+ };
170
+
171
+ //#endregion
172
+ //#region src/core/cache/providers/noopCache.ts
173
+ const noopCacheProvider = {
174
+ cacheType: "pongo:cache:no-op",
175
+ get: () => void 0,
176
+ set: () => {},
177
+ update: () => {},
178
+ delete: () => {},
179
+ getMany: (keys) => keys.map(() => void 0),
180
+ setMany: () => {},
181
+ updateMany: () => {},
182
+ deleteMany: () => {},
183
+ clear: () => {},
184
+ close: () => {}
185
+ };
186
+
187
+ //#endregion
188
+ //#region src/core/cache/pongoCache.ts
189
+ const DEFAULT_CONFIG = { type: "in-memory" };
190
+ const pongoCache = (options) => {
191
+ if (options === void 0 || options === "disabled") return noopCacheProvider;
192
+ if ("cacheType" in options) return options;
193
+ const config = options ?? DEFAULT_CONFIG;
194
+ if (config.type === "identity-map") return identityMapCache();
195
+ return pongoCacheWrapper({ provider: lruCache(config) });
196
+ };
197
+
198
+ //#endregion
199
+ //#region src/core/cache/transactions/pongoTransactionCache.ts
200
+ const pongoTransactionCache = (options) => {
201
+ const innerCache = options?.cache ?? identityMapCache();
202
+ const operations = [];
203
+ return {
204
+ type: "pongo:cache:transaction-buffer",
205
+ get(key) {
206
+ return innerCache.get(key);
207
+ },
208
+ set(key, value, options) {
209
+ const { mainCache } = options;
210
+ innerCache.set(key, value);
211
+ operations.push({
212
+ type: "set",
213
+ key,
214
+ value,
215
+ mainCache
216
+ });
217
+ },
218
+ update(key, updater, options) {
219
+ const { mainCache } = options;
220
+ innerCache.update(key, updater);
221
+ operations.push({
222
+ type: "update",
223
+ key,
224
+ updater,
225
+ mainCache
226
+ });
227
+ },
228
+ delete(key, options) {
229
+ innerCache.delete(key);
230
+ operations.push({
231
+ type: "delete",
232
+ key,
233
+ mainCache: options.mainCache
234
+ });
235
+ },
236
+ getMany(keys) {
237
+ return innerCache.getMany(keys);
238
+ },
239
+ setMany(entries, options) {
240
+ innerCache.setMany(entries);
241
+ operations.push({
242
+ type: "setMany",
243
+ entries,
244
+ mainCache: options.mainCache
245
+ });
246
+ },
247
+ updateMany(keys, updater, options) {
248
+ const { mainCache } = options;
249
+ innerCache.updateMany(keys, updater);
250
+ operations.push({
251
+ type: "updateMany",
252
+ keys,
253
+ updater,
254
+ mainCache
255
+ });
256
+ },
257
+ deleteMany(keys, options) {
258
+ innerCache.deleteMany(keys);
259
+ operations.push({
260
+ type: "deleteMany",
261
+ keys,
262
+ mainCache: options.mainCache
263
+ });
264
+ },
265
+ clear() {
266
+ innerCache.clear();
267
+ operations.length = 0;
268
+ },
269
+ async commit() {
270
+ for (const op of operations) switch (op.type) {
271
+ case "set":
272
+ await op.mainCache.set(op.key, op.value);
273
+ break;
274
+ case "setMany":
275
+ await op.mainCache.setMany(op.entries);
276
+ break;
277
+ case "update":
278
+ await op.mainCache.update(op.key, op.updater);
279
+ break;
280
+ case "updateMany":
281
+ await op.mainCache.updateMany(op.keys, op.updater);
282
+ break;
283
+ case "delete":
284
+ await op.mainCache.delete(op.key);
285
+ break;
286
+ case "deleteMany":
287
+ await op.mainCache.deleteMany(op.keys);
288
+ break;
289
+ }
290
+ innerCache.clear();
291
+ operations.length = 0;
292
+ }
293
+ };
294
+ };
295
+
296
+ //#endregion
297
+ //#region src/core/collection/filters/filters.ts
298
+ const asPlainObjectWithSingleKey = (filter, key) => filter && typeof filter === "object" && !Array.isArray(filter) && Object.keys(filter).length === 1 && key in filter ? filter : void 0;
299
+ const idFromFilter = (filter) => {
300
+ const idFilter = asPlainObjectWithSingleKey(filter, "_id");
301
+ return typeof idFilter?.["_id"] === "string" ? idFilter["_id"] : void 0;
302
+ };
303
+ const getIdsFromIdOnlyFilter = (filter) => {
304
+ const idFilter = asPlainObjectWithSingleKey(filter, "_id");
305
+ if (!idFilter) return void 0;
306
+ const idValue = idFilter["_id"];
307
+ if (typeof idValue === "string") return [idValue];
308
+ const $in = idValue && typeof idValue === "object" && "$in" in idValue ? idValue["$in"] : void 0;
309
+ return Array.isArray($in) && $in.every((i) => typeof i === "string") ? $in : void 0;
310
+ };
311
+
312
+ //#endregion
313
+ //#region src/core/collection/handle.ts
314
+ function DocumentCommandHandler(deps) {
315
+ const fn = async (input, handler, options) => {
316
+ const results = (await handleDocuments(deps.storage, normalizeInput(input), handler, options)).map(({ change, result: outcome }) => toHandleResult(deps, change, outcome));
317
+ return Array.isArray(input) ? results : results[0];
318
+ };
319
+ return fn;
320
+ }
321
+ async function handleDocuments(storage, inputs, handler, options) {
322
+ if (inputs.length === 0) return [];
323
+ const { parallel, ...operationOptions } = options ?? {};
324
+ await storage.ensureCollectionCreated(operationOptions);
325
+ const docs = await storage.fetchByIds(inputs.map((i) => i._id), operationOptions);
326
+ return await executeStorageChanges(storage, await mapAsync(inputs, (item, i) => handleDocument({
327
+ ...item,
328
+ existing: docs[i] ?? null
329
+ }, handler), { parallel }), operationOptions);
330
+ }
331
+ async function handleDocument(item, handler) {
332
+ const { _id: id, existing, expectedVersion } = item;
333
+ if (hasVersionMismatch(existing, expectedVersion)) return {
334
+ type: "noop",
335
+ existing,
336
+ versionMismatch: true
337
+ };
338
+ return toDocumentChange(id, existing, await handler(existing ? { ...existing } : null, id));
339
+ }
340
+ async function executeStorageChanges(storage, changes, operationOptions) {
341
+ const toInsert = changes.flatMap((c) => c.type === "insert" ? [c.doc] : []);
342
+ const toReplace = changes.flatMap((c) => {
343
+ if (c.type !== "replace") return [];
344
+ const { _version: _, ...cleanResult } = c.result;
345
+ return [c._version !== void 0 ? {
346
+ ...cleanResult,
347
+ _version: c._version
348
+ } : cleanResult];
349
+ });
350
+ const toDelete = changes.flatMap((c) => c.type === "delete" ? [c._version !== void 0 ? {
351
+ _id: c.docId,
352
+ _version: c._version
353
+ } : { _id: c.docId }] : []);
354
+ const insertedIds = toInsert.length > 0 ? new Set((await storage.insertMany(toInsert, operationOptions)).insertedIds) : /* @__PURE__ */ new Set();
355
+ const replaceResult = toReplace.length > 0 ? await storage.replaceMany(toReplace, operationOptions) : null;
356
+ const deletedIds = toDelete.length > 0 ? (await storage.deleteManyByIds(toDelete, operationOptions)).deletedIds : /* @__PURE__ */ new Set();
357
+ const toDocumentHandlerResult = (change) => {
358
+ if (change.type === "noop") return { succeeded: !change.versionMismatch };
359
+ if (change.type === "insert") return {
360
+ succeeded: insertedIds.has(change.doc._id),
361
+ newVersion: 1n
362
+ };
363
+ if (change.type === "delete") return { succeeded: deletedIds.has(change.docId) };
364
+ const id = change.result._id;
365
+ return {
366
+ succeeded: replaceResult?.modifiedIds.includes(id) ?? false,
367
+ newVersion: replaceResult?.nextExpectedVersions.get(id) ?? 0n
368
+ };
369
+ };
370
+ return changes.map((change) => ({
371
+ change,
372
+ result: toDocumentHandlerResult(change)
373
+ }));
374
+ }
375
+ function normalizeInput(input) {
376
+ if (typeof input === "string") return [{ _id: input }];
377
+ if (!Array.isArray(input)) return [input];
378
+ return input.map((item) => typeof item === "string" ? { _id: item } : item);
379
+ }
380
+ function hasVersionMismatch(existing, version) {
381
+ const expected = expectedVersionValue(version);
382
+ return existing == null && version === "DOCUMENT_EXISTS" || existing == null && expected != null || existing != null && version === "DOCUMENT_DOES_NOT_EXIST" || existing != null && expected !== null && existing._version !== expected;
383
+ }
384
+ function toDocumentChange(docId, existing, result) {
385
+ if (deepEquals(existing, result)) return {
386
+ type: "noop",
387
+ existing
388
+ };
389
+ if (!existing && result) return {
390
+ type: "insert",
391
+ doc: {
392
+ ...result,
393
+ _id: docId
394
+ }
395
+ };
396
+ if (existing && !result) return {
397
+ type: "delete",
398
+ docId,
399
+ _version: existing._version
400
+ };
401
+ return {
402
+ type: "replace",
403
+ existing,
404
+ result: {
405
+ ...result,
406
+ _id: docId
407
+ },
408
+ _version: existing._version
409
+ };
410
+ }
411
+ function toHandleResult(deps, change, { succeeded, newVersion }) {
412
+ const opMeta = {
413
+ operationName: "handle",
414
+ collectionName: deps.collectionName,
415
+ serializer: deps.serializer,
416
+ errors: deps.errors
417
+ };
418
+ const toResult = (op, document) => ({
419
+ ...operationResult(op, opMeta),
420
+ document
421
+ });
422
+ if (change.type === "noop") return toResult({ successful: succeeded }, change.existing);
423
+ if (change.type === "insert") return toResult({
424
+ successful: succeeded,
425
+ insertedId: succeeded ? change.doc._id : null,
426
+ nextExpectedVersion: 1n
427
+ }, succeeded ? {
428
+ ...change.doc,
429
+ _version: 1n
430
+ } : null);
431
+ if (change.type === "delete") return toResult({
432
+ successful: succeeded,
433
+ deletedCount: succeeded ? 1 : 0,
434
+ matchedCount: 1
435
+ }, null);
436
+ return toResult({
437
+ successful: succeeded,
438
+ modifiedCount: succeeded ? 1 : 0,
439
+ matchedCount: 1,
440
+ nextExpectedVersion: newVersion ?? 0n
441
+ }, succeeded ? {
442
+ ...change.result,
443
+ _version: newVersion
444
+ } : change.existing);
445
+ }
446
+
447
+ //#endregion
448
+ //#region src/core/collection/pongoCollection.ts
449
+ const enlistIntoTransactionIfActive = async (db, options) => {
450
+ const transaction = options?.session?.transaction;
451
+ if (!transaction || !transaction.isActive) return null;
452
+ return await transaction.enlistDatabase(db);
453
+ };
454
+ const transactionExecutorOrDefault = async (db, options, defaultSqlExecutor) => {
455
+ return (await enlistIntoTransactionIfActive(db, options))?.execute ?? defaultSqlExecutor;
456
+ };
457
+ const pongoCollection = ({ db, collectionName, pool, schemaComponent, schema, errors, serializer, cache: cacheOptions }) => {
458
+ const SqlFor = schemaComponent.sqlBuilder;
459
+ const sqlExecutor = pool.execute;
460
+ const cache = pongoCache(cacheOptions);
461
+ const columnMapping = { mapping: {
462
+ ...mapColumnToJSON("data", serializer),
463
+ ...mapColumnToBigint("_version")
464
+ } };
465
+ const command = async (sql, options) => (await transactionExecutorOrDefault(db, options, sqlExecutor)).command(sql, columnMapping);
466
+ const query = async (sql, options) => (await transactionExecutorOrDefault(db, options, sqlExecutor)).query(sql, columnMapping);
467
+ let shouldMigrate = schema?.autoMigration !== "None";
468
+ const createCollection = (options) => {
469
+ shouldMigrate = false;
470
+ if (options?.session) return command(SqlFor.createCollection(), options);
471
+ else return command(SqlFor.createCollection());
472
+ };
473
+ const ensureCollectionCreated = (options) => {
474
+ if (!shouldMigrate) return Promise.resolve();
475
+ return createCollection(options);
476
+ };
477
+ const upcast = schema?.versioning?.upcast ?? ((doc) => doc);
478
+ const downcast = schema?.versioning?.downcast ?? ((doc) => doc);
479
+ const rowToDoc = (row) => upcast({
480
+ ...row.data,
481
+ _version: row._version
482
+ });
483
+ const findOneFromDb = async (filter, options) => {
484
+ const row = (await query(SqlFor.findOne(filter), options)).rows[0];
485
+ return row ? rowToDoc(row) : null;
486
+ };
487
+ const cacheKey = (id) => `${db.databaseName}:${collectionName}:${id}`;
488
+ const txCacheFor = (options) => options?.session?.transaction?.cache ?? null;
489
+ const resolveFromCache = async (key, options) => {
490
+ const txCache = txCacheFor(options);
491
+ if (txCache) {
492
+ const cached = await txCache.get(key);
493
+ if (cached !== void 0) return cached;
494
+ }
495
+ return cache.get(key);
496
+ };
497
+ const findManyFromCache = async (keys, options) => {
498
+ const txCache = txCacheFor(options);
499
+ if (!txCache) return cache.getMany(keys);
500
+ const txResults = await txCache.getMany(keys);
501
+ const mainResults = await cache.getMany(keys);
502
+ return keys.map((_, i) => txResults[i] !== void 0 ? txResults[i] : mainResults[i]);
503
+ };
504
+ const fetchByIds = async (ids, options) => {
505
+ const cachedResults = await findManyFromCache(ids.map(cacheKey), options);
506
+ const missIds = ids.filter((_, i) => cachedResults[i] === void 0);
507
+ let dbDocsById = /* @__PURE__ */ new Map();
508
+ if (missIds.length > 0) {
509
+ const dbDocs = (await query(SqlFor.find({ _id: { $in: missIds } }, options))).rows.map(rowToDoc);
510
+ dbDocsById = new Map(dbDocs.map((d) => [d["_id"], d]));
511
+ const leftovers = missIds.map((id) => [id, dbDocsById.get(id) ?? null]);
512
+ await cacheSetMany(leftovers.map((d) => d[1]).filter((d) => d !== null), options);
513
+ await cacheDeleteMany(leftovers.filter(([, doc]) => doc === null).map(([id]) => id), options);
514
+ }
515
+ return ids.map((id, i) => {
516
+ const cached = cachedResults[i];
517
+ if (cached !== void 0) return cached !== null ? upcast({ ...cached }) : null;
518
+ return dbDocsById.get(id) ?? null;
519
+ });
520
+ };
521
+ const findManyByIds = async (ids, options) => {
522
+ return (await fetchByIds(ids, options)).filter((doc) => doc !== null);
523
+ };
524
+ const cacheSet = (value, options) => {
525
+ const key = cacheKey(value._id);
526
+ const txCache = txCacheFor(options);
527
+ if (txCache) return txCache.set(key, value, { mainCache: cache });
528
+ return cache.set(key, value);
529
+ };
530
+ const cacheSetMany = (documents, options) => {
531
+ const txCache = txCacheFor(options);
532
+ const entries = documents.map((d) => ({
533
+ key: cacheKey(d._id),
534
+ value: d
535
+ }));
536
+ if (txCache) return txCache.setMany(entries, { mainCache: cache });
537
+ return cache.setMany(entries);
538
+ };
539
+ const cacheDelete = (id, options) => {
540
+ const txCache = txCacheFor(options);
541
+ const key = cacheKey(id);
542
+ if (txCache) return txCache.delete(key, { mainCache: cache });
543
+ return cache.delete(key);
544
+ };
545
+ const cacheDeleteMany = (ids, options) => {
546
+ const txCache = txCacheFor(options);
547
+ const keys = ids.map(cacheKey);
548
+ if (txCache) return txCache.deleteMany(keys, { mainCache: cache });
549
+ return cache.deleteMany(keys);
550
+ };
551
+ const deleteManyByIds = async (ids, options) => {
552
+ await ensureCollectionCreated(options);
553
+ const result = await command(SqlFor.deleteManyByIds(ids), options);
554
+ const deletedIds = new Set(result.rows.filter((row) => (row.deleted ?? 1) > 0).map((row) => row._id));
555
+ if (!options?.skipCache) await cacheDeleteMany([...deletedIds], options);
556
+ return operationResult({
557
+ successful: deletedIds.size > 0,
558
+ deletedCount: deletedIds.size,
559
+ matchedCount: ids.length,
560
+ deletedIds
561
+ }, {
562
+ operationName: "deleteManyByIds",
563
+ collectionName,
564
+ serializer,
565
+ errors
566
+ });
567
+ };
568
+ const collection = {
569
+ dbName: db.databaseName,
570
+ collectionName,
571
+ createCollection: async (options) => {
572
+ await createCollection(options);
573
+ },
574
+ insertOne: async (document, options) => {
575
+ await ensureCollectionCreated(options);
576
+ const _id = document._id ?? v7();
577
+ const _version = document._version ?? 1n;
578
+ const downcasted = downcast(document);
579
+ const successful = ((await command(SqlFor.insertOne({
580
+ ...downcasted,
581
+ _id,
582
+ _version
583
+ }), options)).rowCount ?? 0) > 0;
584
+ if (successful && !options?.skipCache) await cacheSet({
585
+ ...document,
586
+ _id,
587
+ _version
588
+ }, options);
589
+ return operationResult({
590
+ successful,
591
+ insertedId: successful ? _id : null,
592
+ nextExpectedVersion: _version
593
+ }, {
594
+ operationName: "insertOne",
595
+ collectionName,
596
+ serializer,
597
+ errors
598
+ });
599
+ },
600
+ insertMany: async (documents, options) => {
601
+ await ensureCollectionCreated(options);
602
+ const documentsWithMetadata = documents.map((doc) => doc._id && doc._version ? doc : {
603
+ ...doc,
604
+ _id: doc._id ?? v7(),
605
+ _version: doc._version ?? 1n
606
+ });
607
+ const rows = documentsWithMetadata.map((d) => ({
608
+ ...downcast(d),
609
+ _id: d._id,
610
+ _version: d._version
611
+ }));
612
+ const result = await command(SqlFor.insertMany(rows), options);
613
+ if (!options?.skipCache) {
614
+ const insertedIdSet = new Set(result.rows.map((d) => d._id));
615
+ await cacheSetMany(documentsWithMetadata.filter((d) => insertedIdSet.has(d._id)), options);
616
+ }
617
+ return operationResult({
618
+ successful: result.rowCount === rows.length,
619
+ insertedCount: result.rowCount ?? 0,
620
+ insertedIds: result.rows.map((d) => d._id)
621
+ }, {
622
+ operationName: "insertMany",
623
+ collectionName,
624
+ serializer,
625
+ errors
626
+ });
627
+ },
628
+ updateOne: async (filter, update, options) => {
629
+ await ensureCollectionCreated(options);
630
+ const result = await command(SqlFor.updateOne(filter, update, options), options);
631
+ const opResult = operationResult({
632
+ successful: result.rows.length > 0 && result.rows[0].modified === result.rows[0].matched,
633
+ modifiedCount: Number(result.rows[0]?.modified ?? 0),
634
+ matchedCount: Number(result.rows[0]?.matched ?? 0),
635
+ nextExpectedVersion: BigInt(result.rows[0]?.version ?? 0n)
636
+ }, {
637
+ operationName: "updateOne",
638
+ collectionName,
639
+ serializer,
640
+ errors
641
+ });
642
+ if (opResult.successful && !options?.skipCache) {
643
+ const id = idFromFilter(filter);
644
+ if (id) await cacheDelete(id, options);
645
+ }
646
+ return opResult;
647
+ },
648
+ replaceOne: async (filter, document, options) => {
649
+ await ensureCollectionCreated(options);
650
+ const downcasted = downcast(document);
651
+ const result = await command(SqlFor.replaceOne(filter, downcasted, options), options);
652
+ const opResult = operationResult({
653
+ successful: result.rows.length > 0 && result.rows[0].modified > 0,
654
+ modifiedCount: Number(result.rows[0]?.modified ?? 0),
655
+ matchedCount: Number(result.rows[0]?.matched ?? 0),
656
+ nextExpectedVersion: BigInt(result.rows[0]?.version ?? 0n)
657
+ }, {
658
+ operationName: "replaceOne",
659
+ collectionName,
660
+ serializer,
661
+ errors
662
+ });
663
+ if (opResult.successful && !options?.skipCache) {
664
+ const _id = idFromFilter(filter);
665
+ if (_id) await cacheSet({
666
+ ...document,
667
+ _id,
668
+ _version: opResult.nextExpectedVersion
669
+ }, options);
670
+ }
671
+ return opResult;
672
+ },
673
+ updateMany: async (filter, update, options) => {
674
+ await ensureCollectionCreated(options);
675
+ const result = await command(SqlFor.updateMany(filter, update), options);
676
+ return operationResult({
677
+ successful: true,
678
+ modifiedCount: result.rowCount ?? 0,
679
+ matchedCount: result.rowCount ?? 0
680
+ }, {
681
+ operationName: "updateMany",
682
+ collectionName,
683
+ serializer,
684
+ errors
685
+ });
686
+ },
687
+ deleteOne: async (filter, options) => {
688
+ await ensureCollectionCreated(options);
689
+ const result = await command(SqlFor.deleteOne(filter ?? {}, options), options);
690
+ const opResult = operationResult({
691
+ successful: result.rows.length > 0 && result.rows[0].deleted > 0,
692
+ deletedCount: Number(result.rows[0]?.deleted ?? 0),
693
+ matchedCount: Number(result.rows[0]?.matched ?? 0)
694
+ }, {
695
+ operationName: "deleteOne",
696
+ collectionName,
697
+ serializer,
698
+ errors
699
+ });
700
+ if (opResult.successful && !options?.skipCache && filter) {
701
+ const id = idFromFilter(filter);
702
+ if (id) await cacheDelete(id, options);
703
+ }
704
+ return opResult;
705
+ },
706
+ deleteMany: async (filter, options) => {
707
+ const ids = filter ? getIdsFromIdOnlyFilter(filter) : null;
708
+ if (ids) return deleteManyByIds(ids.map((id) => ({ _id: id })), options);
709
+ await ensureCollectionCreated(options);
710
+ const result = await command(SqlFor.deleteMany(filter ?? {}), options);
711
+ return operationResult({
712
+ successful: (result.rowCount ?? 0) > 0,
713
+ deletedCount: result.rowCount ?? 0,
714
+ matchedCount: result.rowCount ?? 0
715
+ }, {
716
+ operationName: "deleteMany",
717
+ collectionName,
718
+ serializer,
719
+ errors
720
+ });
721
+ },
722
+ findOne: async (filter, options) => {
723
+ await ensureCollectionCreated(options);
724
+ const id = filter && !options?.skipCache ? idFromFilter(filter) : null;
725
+ if (id) {
726
+ const cached = await resolveFromCache(cacheKey(id), options);
727
+ if (cached !== void 0) return cached !== null ? upcast({ ...cached }) : null;
728
+ const doc = await findOneFromDb(filter, options);
729
+ if (doc) await cacheSet(doc, options);
730
+ else await cacheDelete(id, options);
731
+ return doc;
732
+ }
733
+ return findOneFromDb(filter ?? {}, options);
734
+ },
735
+ findOneAndDelete: async (filter, options) => {
736
+ await ensureCollectionCreated(options);
737
+ const existingDoc = await collection.findOne(filter, options);
738
+ if (existingDoc === null) return null;
739
+ await collection.deleteOne(filter, options);
740
+ return existingDoc;
741
+ },
742
+ findOneAndReplace: async (filter, replacement, options) => {
743
+ await ensureCollectionCreated(options);
744
+ const existingDoc = await collection.findOne(filter, options);
745
+ if (existingDoc === null) return null;
746
+ await collection.replaceOne(filter, replacement, options);
747
+ return existingDoc;
748
+ },
749
+ findOneAndUpdate: async (filter, update, options) => {
750
+ await ensureCollectionCreated(options);
751
+ const existingDoc = await collection.findOne(filter, options);
752
+ if (existingDoc === null) return null;
753
+ await collection.updateOne(filter, update, options);
754
+ return existingDoc;
755
+ },
756
+ replaceMany: async (documents, options) => {
757
+ await ensureCollectionCreated(options);
758
+ const downcasted = documents.map((d) => downcast(d));
759
+ const result = await command(SqlFor.replaceMany(downcasted), options);
760
+ const modifiedIds = result.rows.map((row) => row._id);
761
+ const conflictIds = documents.map((d) => d._id).filter((id) => !modifiedIds.includes(id));
762
+ const versions = new Map(result.rows.map((row) => [row._id, BigInt(row.version ?? 1n)]));
763
+ if (!options?.skipCache) {
764
+ const cacheEntries = documents.filter((d) => modifiedIds.includes(d._id)).map((doc) => doc._version ? doc : {
765
+ ...doc,
766
+ _version: versions.get(doc._id) ?? 1n
767
+ });
768
+ if (cacheEntries.length > 0) await cacheSetMany(cacheEntries, options);
769
+ if (conflictIds.length > 0) await cacheDeleteMany([...conflictIds], options);
770
+ }
771
+ return operationResult({
772
+ successful: modifiedIds.length > 0 && conflictIds.length === 0,
773
+ modifiedCount: modifiedIds.length,
774
+ matchedCount: documents.length,
775
+ modifiedIds: [...modifiedIds],
776
+ conflictIds: [...conflictIds],
777
+ nextExpectedVersions: versions
778
+ }, {
779
+ operationName: "replaceMany",
780
+ collectionName,
781
+ serializer,
782
+ errors
783
+ });
784
+ },
785
+ handle: DocumentCommandHandler({
786
+ collectionName,
787
+ serializer,
788
+ errors,
789
+ storage: {
790
+ ensureCollectionCreated,
791
+ fetchByIds,
792
+ insertMany: (docs, options) => collection.insertMany(docs, options),
793
+ replaceMany: (docs, options) => collection.replaceMany(docs, options),
794
+ deleteManyByIds
795
+ }
796
+ }),
797
+ find: async (filter, options) => {
798
+ await ensureCollectionCreated(options);
799
+ if (!options?.skipCache && filter) {
800
+ const ids = getIdsFromIdOnlyFilter(filter);
801
+ if (ids && ids.length > 0) return findManyByIds(ids, options);
802
+ }
803
+ return (await query(SqlFor.find(filter ?? {}, options))).rows.map(rowToDoc);
804
+ },
805
+ countDocuments: async (filter, options) => {
806
+ await ensureCollectionCreated(options);
807
+ const { count } = await single(query(SqlFor.countDocuments(filter ?? {})));
808
+ return count;
809
+ },
810
+ drop: async (options) => {
811
+ await ensureCollectionCreated(options);
812
+ return ((await command(SqlFor.drop()))?.rowCount ?? 0) > 0;
813
+ },
814
+ rename: async (newName, options) => {
815
+ await ensureCollectionCreated(options);
816
+ await command(SqlFor.rename(newName));
817
+ collectionName = newName;
818
+ return collection;
819
+ },
820
+ close: () => cache.close(),
821
+ sql: {
822
+ async query(sql, options) {
823
+ await ensureCollectionCreated(options);
824
+ return (await query(sql, options)).rows;
825
+ },
826
+ async command(sql, options) {
827
+ await ensureCollectionCreated(options);
828
+ return command(sql, options);
829
+ }
830
+ },
831
+ schema: {
832
+ component: schemaComponent,
833
+ migrate: (options) => runSQLMigrations(pool, schemaComponent.migrations, options)
834
+ }
835
+ };
836
+ return collection;
837
+ };
838
+
839
+ //#endregion
840
+ //#region src/core/collection/pongoCollectionSchemaComponent.ts
841
+ const PongoCollectionSchemaComponent = ({ definition, migrationsOrSchemaComponents, sqlBuilder }) => ({
842
+ ...schemaComponent(`sc:pongo:collection:${definition.name}`, migrationsOrSchemaComponents),
843
+ sqlBuilder,
844
+ definition,
845
+ collectionName: definition.name
846
+ });
847
+
848
+ //#endregion
849
+ //#region src/core/collection/query.ts
850
+ const QueryOperators = {
851
+ $eq: "$eq",
852
+ $gt: "$gt",
853
+ $gte: "$gte",
854
+ $lt: "$lt",
855
+ $lte: "$lte",
856
+ $ne: "$ne",
857
+ $in: "$in",
858
+ $nin: "$nin",
859
+ $elemMatch: "$elemMatch",
860
+ $all: "$all",
861
+ $size: "$size"
862
+ };
863
+ const OperatorMap = {
864
+ $gt: ">",
865
+ $gte: ">=",
866
+ $lt: "<",
867
+ $lte: "<=",
868
+ $ne: "!="
869
+ };
870
+ const isOperator = (key) => key.startsWith("$");
871
+ const hasOperators = (value) => Object.keys(value).some(isOperator);
872
+
873
+ //#endregion
874
+ //#region src/core/database/pongoDatabaseCache.ts
875
+ const PongoDatabaseCache = ({ driver, typedSchema }) => {
876
+ const dbClients = /* @__PURE__ */ new Map();
877
+ const getDatabaseDefinition = (dbName) => Object.values(typedSchema?.dbs ?? {}).find((d) => d.name === dbName);
878
+ return {
879
+ getOrCreate: (createOptions) => {
880
+ const metadata = getDatabaseMetadata(driver.driverType);
881
+ const dbName = createOptions.databaseName ?? metadata?.parseDatabaseName?.("connectionString" in createOptions ? createOptions.connectionString : void 0) ?? "db:default";
882
+ const existing = dbClients.get(dbName);
883
+ if (existing) return existing;
884
+ const definition = getDatabaseDefinition(createOptions.databaseName);
885
+ const newDb = driver.databaseFactory({
886
+ ...createOptions,
887
+ databaseName: dbName,
888
+ schema: {
889
+ ...createOptions.schema,
890
+ ...definition ? { definition } : {}
891
+ }
892
+ });
893
+ dbClients.set(dbName, newDb);
894
+ return newDb;
895
+ },
896
+ all: () => Array.from(dbClients.values()),
897
+ forAll: (func) => {
898
+ return Promise.all(Array.from(dbClients.values()).map((v) => v).map(func));
899
+ }
900
+ };
901
+ };
902
+
903
+ //#endregion
904
+ //#region src/core/typing/entries.ts
905
+ const objectEntries = (obj) => Object.entries(obj).map(([key, value]) => [key, value]);
906
+
907
+ //#endregion
908
+ //#region src/core/errors/index.ts
909
+ const isNumber = (val) => typeof val === "number" && val === val;
910
+ const isString = (val) => typeof val === "string";
911
+ var PongoError = class PongoError extends Error {
912
+ errorCode;
913
+ constructor(options) {
914
+ const errorCode = options && typeof options === "object" && "errorCode" in options ? options.errorCode : isNumber(options) ? options : 500;
915
+ const message = options && typeof options === "object" && "message" in options ? options.message : isString(options) ? options : `Error with status code '${errorCode}' ocurred during Pongo processing`;
916
+ super(message);
917
+ this.errorCode = errorCode;
918
+ Object.setPrototypeOf(this, PongoError.prototype);
919
+ }
920
+ };
921
+ var ConcurrencyError = class ConcurrencyError extends PongoError {
922
+ constructor(message) {
923
+ super({
924
+ errorCode: 412,
925
+ message: message ?? `Expected document state does not match current one!`
926
+ });
927
+ Object.setPrototypeOf(this, ConcurrencyError.prototype);
928
+ }
929
+ };
930
+
931
+ //#endregion
932
+ //#region src/core/typing/operations.ts
933
+ const ObjectId = (value) => value ?? v7();
934
+ const DOCUMENT_EXISTS = "DOCUMENT_EXISTS";
935
+ const DOCUMENT_DOES_NOT_EXIST = "DOCUMENT_DOES_NOT_EXIST";
936
+ const NO_CONCURRENCY_CHECK = "NO_CONCURRENCY_CHECK";
937
+ const isGeneralExpectedDocumentVersion = (version) => version === "DOCUMENT_DOES_NOT_EXIST" || version === "DOCUMENT_EXISTS" || version === "NO_CONCURRENCY_CHECK";
938
+ const expectedVersionValue = (version) => version === void 0 || isGeneralExpectedDocumentVersion(version) ? null : version;
939
+ const expectedVersion = (version) => {
940
+ return version ? BigInt(version) : NO_CONCURRENCY_CHECK;
941
+ };
942
+ const operationResult = (result, options) => {
943
+ const operationResult = {
944
+ ...result,
945
+ acknowledged: true,
946
+ successful: result.successful,
947
+ assertSuccessful: (errorMessage) => {
948
+ const { successful } = result;
949
+ const { operationName, collectionName } = options;
950
+ if (!successful) throw new ConcurrencyError(errorMessage ?? `${operationName} on ${collectionName} failed. Expected document state does not match current one! Result: ${options.serializer.serialize(result)}!`);
951
+ }
952
+ };
953
+ if (options.errors?.throwOnOperationFailures) operationResult.assertSuccessful();
954
+ return operationResult;
955
+ };
956
+
957
+ //#endregion
958
+ //#region src/core/schema/index.ts
959
+ const pongoCollectionSchema = (name) => ({ name });
960
+ pongoCollectionSchema.from = (collectionNames) => collectionNames.reduce((acc, collectionName) => (acc[collectionName] = pongoSchema.collection(collectionName), acc), {});
961
+ function pongoDbSchema(nameOrCollections, collections) {
962
+ if (collections === void 0) {
963
+ if (typeof nameOrCollections === "string") throw new Error("You need to provide colleciton definition");
964
+ return { collections: nameOrCollections };
965
+ }
966
+ return nameOrCollections && typeof nameOrCollections === "string" ? {
967
+ name: nameOrCollections,
968
+ collections
969
+ } : { collections };
970
+ }
971
+ pongoDbSchema.from = (databaseName, collectionNames) => databaseName ? pongoDbSchema(databaseName, pongoCollectionSchema.from(collectionNames)) : pongoDbSchema(pongoCollectionSchema.from(collectionNames));
972
+ const pongoClientSchema = (dbs) => ({ dbs });
973
+ const pongoSchema = {
974
+ client: pongoClientSchema,
975
+ db: pongoDbSchema,
976
+ collection: pongoCollectionSchema
977
+ };
978
+ const proxyPongoDbWithSchema = (pongoDb, dbSchema, collections) => {
979
+ const collectionNames = Object.keys(dbSchema.collections);
980
+ for (const collectionName of collectionNames) collections.set(collectionName, pongoDb.collection(collectionName));
981
+ return new Proxy(pongoDb, { get(target, prop) {
982
+ return collections.get(prop) ?? target[prop];
983
+ } });
984
+ };
985
+ const proxyClientWithSchema = (client, schema) => {
986
+ if (!schema) return client;
987
+ const dbNames = Object.keys(schema.dbs);
988
+ return new Proxy(client, { get(target, prop) {
989
+ if (dbNames.includes(prop)) return client.db(schema.dbs[prop]?.name);
990
+ return target[prop];
991
+ } });
992
+ };
993
+ const toDbSchemaMetadata = (schema) => ({
994
+ name: schema.name,
995
+ collections: objectEntries(schema.collections).map((c) => ({ name: c[1].name }))
996
+ });
997
+ const toClientSchemaMetadata = (schema) => {
998
+ const databases = objectEntries(schema.dbs).map((e) => toDbSchemaMetadata(e[1]));
999
+ return {
1000
+ databases,
1001
+ database: (name) => databases.find((db) => db.name === name)
1002
+ };
1003
+ };
1004
+
1005
+ //#endregion
1006
+ //#region src/core/database/pongoDatabaseSchemaComponent.ts
1007
+ const PongoDatabaseSchemaComponent = ({ definition, collectionFactory }) => {
1008
+ const collections = Object.values(definition.collections).map(collectionFactory) ?? [];
1009
+ return {
1010
+ ...schemaComponent(`sc:dumbo:database:${definition.name}`, { components: collections }),
1011
+ definition,
1012
+ collections,
1013
+ collection: (schema) => {
1014
+ const existing = collections.find((c) => c.collectionName === schema.name);
1015
+ if (existing) return existing;
1016
+ const newCollection = collectionFactory(pongoSchema.collection(schema.name));
1017
+ collections.push(newCollection);
1018
+ definition.collections[schema.name] = schema;
1019
+ return newCollection;
1020
+ }
1021
+ };
1022
+ };
1023
+
1024
+ //#endregion
1025
+ //#region src/core/database/pongoDb.ts
1026
+ const PongoDatabase = (options) => {
1027
+ const { databaseName, schemaComponent, pool, cache: cacheOptions, serializer } = options;
1028
+ const cache = cacheOptions === "disabled" || cacheOptions === void 0 ? "disabled" : pongoCache(cacheOptions);
1029
+ const collections = /* @__PURE__ */ new Map();
1030
+ const command = async (sql, options) => (await transactionExecutorOrDefault(db, options, pool.execute)).command(sql, options);
1031
+ const query = async (sql, options) => (await transactionExecutorOrDefault(db, options, pool.execute)).query(sql, options);
1032
+ const db = {
1033
+ driverType: pool.driverType,
1034
+ databaseName,
1035
+ connect: () => Promise.resolve(),
1036
+ close: async () => {
1037
+ await Promise.allSettled([
1038
+ pool.close(),
1039
+ cache !== "disabled" ? cache.close() : Promise.resolve(),
1040
+ ...collections.values().map((collection) => collection.close())
1041
+ ]);
1042
+ },
1043
+ collections: () => [...collections.values()],
1044
+ collection: (collectionName, collectionOptions) => collections.get(collectionName) ?? pongoCollection({
1045
+ collectionName,
1046
+ db,
1047
+ pool,
1048
+ schemaComponent: schemaComponent.collection(pongoSchema.collection(collectionName)),
1049
+ schema: {
1050
+ ...options.schema,
1051
+ ...collectionOptions?.schema
1052
+ },
1053
+ serializer,
1054
+ errors: {
1055
+ ...options.errors,
1056
+ ...collectionOptions?.errors
1057
+ },
1058
+ cache: collectionOptions?.cache !== void 0 ? collectionOptions.cache : cache
1059
+ }),
1060
+ transaction: () => pool.transaction(),
1061
+ withTransaction: (handle) => pool.withTransaction(handle),
1062
+ schema: {
1063
+ component: schemaComponent,
1064
+ migrate: (options) => runSQLMigrations(pool, schemaComponent.migrations, options)
1065
+ },
1066
+ sql: {
1067
+ async query(sql, options) {
1068
+ return (await query(sql, options)).rows;
1069
+ },
1070
+ async command(sql, options) {
1071
+ return command(sql, options);
1072
+ }
1073
+ }
1074
+ };
1075
+ const dbSchema = options?.schema?.definition;
1076
+ if (dbSchema) return proxyPongoDbWithSchema(db, dbSchema, collections);
1077
+ return db;
1078
+ };
1079
+
1080
+ //#endregion
1081
+ //#region src/core/drivers/databaseDriver.ts
1082
+ const PongoDriverRegistry = () => {
1083
+ const drivers = /* @__PURE__ */ new Map();
1084
+ const register = (driverType, driver) => {
1085
+ const entry = drivers.get(driverType);
1086
+ if (entry && (typeof entry !== "function" || typeof driver === "function")) return;
1087
+ drivers.set(driverType, driver);
1088
+ };
1089
+ const tryResolve = async (driverType) => {
1090
+ const entry = drivers.get(driverType);
1091
+ if (!entry) return null;
1092
+ if (typeof entry !== "function") return entry;
1093
+ const driver = await entry();
1094
+ register(driverType, driver);
1095
+ return driver;
1096
+ };
1097
+ const tryGet = (driverType) => {
1098
+ const entry = drivers.get(driverType);
1099
+ return entry && typeof entry !== "function" ? entry : null;
1100
+ };
1101
+ const has = (driverType) => drivers.has(driverType);
1102
+ return {
1103
+ register,
1104
+ tryResolve,
1105
+ tryGet,
1106
+ has,
1107
+ get databaseDriverTypes() {
1108
+ return Array.from(drivers.keys());
1109
+ }
1110
+ };
1111
+ };
1112
+ const pongoDriverRegistry = globalThis.pongoDriverRegistry = globalThis.pongoDriverRegistry ?? PongoDriverRegistry();
1113
+
1114
+ //#endregion
1115
+ //#region src/core/pongoTransaction.ts
1116
+ const pongoTransaction = (options) => {
1117
+ let isCommitted = false;
1118
+ let isRolledBack = false;
1119
+ let databaseName = null;
1120
+ let transaction = null;
1121
+ const cache = pongoTransactionCache();
1122
+ return {
1123
+ cache,
1124
+ enlistDatabase: async (db) => {
1125
+ if (transaction && databaseName !== db.databaseName) throw new Error("There's already other database assigned to transaction");
1126
+ if (transaction && databaseName === db.databaseName) return transaction;
1127
+ databaseName = db.databaseName;
1128
+ transaction = db.transaction();
1129
+ await transaction.begin();
1130
+ return transaction;
1131
+ },
1132
+ commit: async () => {
1133
+ if (isCommitted) return;
1134
+ if (isRolledBack) throw new Error("Transaction is not active!");
1135
+ isCommitted = true;
1136
+ if (transaction) {
1137
+ await transaction.commit();
1138
+ transaction = null;
1139
+ }
1140
+ await cache.commit();
1141
+ },
1142
+ rollback: async (error) => {
1143
+ if (isCommitted) throw new Error("Cannot rollback commited transaction!");
1144
+ if (isRolledBack) return;
1145
+ isRolledBack = true;
1146
+ if (transaction) {
1147
+ await transaction.rollback(error);
1148
+ transaction = null;
1149
+ }
1150
+ cache.clear();
1151
+ },
1152
+ databaseName,
1153
+ isStarting: false,
1154
+ isCommitted,
1155
+ get isActive() {
1156
+ return !isCommitted && !isRolledBack;
1157
+ },
1158
+ get sqlExecutor() {
1159
+ if (transaction === null) throw new Error("No database transaction was started");
1160
+ return transaction.execute;
1161
+ },
1162
+ options
1163
+ };
1164
+ };
1165
+
1166
+ //#endregion
1167
+ //#region src/core/pongoSession.ts
1168
+ const isActive = (transaction) => transaction?.isActive === true;
1169
+ function assertInActiveTransaction(transaction) {
1170
+ if (!isActive(transaction)) throw new Error("No active transaction exists!");
1171
+ }
1172
+ function assertNotInActiveTransaction(transaction) {
1173
+ if (isActive(transaction)) throw new Error("Active transaction already exists!");
1174
+ }
1175
+ const pongoSession = (options) => {
1176
+ const explicit = options?.explicit === true;
1177
+ const defaultTransactionOptions = options?.defaultTransactionOptions ?? { get snapshotEnabled() {
1178
+ return false;
1179
+ } };
1180
+ let transaction = null;
1181
+ let hasEnded = false;
1182
+ const startTransaction = (options) => {
1183
+ assertNotInActiveTransaction(transaction);
1184
+ transaction = pongoTransaction(options ?? defaultTransactionOptions);
1185
+ };
1186
+ const commitTransaction = async () => {
1187
+ assertInActiveTransaction(transaction);
1188
+ await transaction.commit();
1189
+ };
1190
+ const abortTransaction = async () => {
1191
+ assertInActiveTransaction(transaction);
1192
+ await transaction.rollback();
1193
+ };
1194
+ const endSession = async () => {
1195
+ if (hasEnded) return;
1196
+ hasEnded = true;
1197
+ if (isActive(transaction)) await transaction.rollback();
1198
+ };
1199
+ const session = {
1200
+ get hasEnded() {
1201
+ return hasEnded;
1202
+ },
1203
+ explicit,
1204
+ defaultTransactionOptions: defaultTransactionOptions ?? { get snapshotEnabled() {
1205
+ return false;
1206
+ } },
1207
+ get transaction() {
1208
+ return transaction;
1209
+ },
1210
+ get snapshotEnabled() {
1211
+ return defaultTransactionOptions.snapshotEnabled;
1212
+ },
1213
+ endSession,
1214
+ incrementTransactionNumber: () => {},
1215
+ inTransaction: () => isActive(transaction),
1216
+ startTransaction,
1217
+ commitTransaction,
1218
+ abortTransaction,
1219
+ withTransaction: async (fn, options) => {
1220
+ startTransaction(options);
1221
+ try {
1222
+ const result = await fn(session);
1223
+ await commitTransaction();
1224
+ return result;
1225
+ } catch (error) {
1226
+ await abortTransaction();
1227
+ throw error;
1228
+ }
1229
+ }
1230
+ };
1231
+ return session;
1232
+ };
1233
+
1234
+ //#endregion
1235
+ //#region src/core/pongoClient.ts
1236
+ const pongoClient = (options) => {
1237
+ const { driver, schema, errors, cache: cacheOptions, serialization, ...connectionOptions } = options;
1238
+ const dbClients = PongoDatabaseCache({
1239
+ driver,
1240
+ typedSchema: schema?.definition
1241
+ });
1242
+ const serializer = JSONSerializer.from(options);
1243
+ const cache = cacheOptions === "disabled" || cacheOptions === void 0 ? "disabled" : pongoCache(cacheOptions);
1244
+ const pongoClient = {
1245
+ driverType: driver.driverType,
1246
+ connect: async () => {
1247
+ await dbClients.forAll((db) => db.connect());
1248
+ return pongoClient;
1249
+ },
1250
+ close: async () => {
1251
+ await dbClients.forAll((db) => db.close());
1252
+ },
1253
+ db: (dbName, options) => {
1254
+ return dbClients.getOrCreate({
1255
+ ...connectionOptions,
1256
+ databaseName: dbName,
1257
+ serializer,
1258
+ errors,
1259
+ cache: options?.cache ?? cache,
1260
+ serialization
1261
+ });
1262
+ },
1263
+ startSession: pongoSession,
1264
+ withSession: async (callback) => {
1265
+ const session = pongoSession();
1266
+ try {
1267
+ return await callback(session);
1268
+ } finally {
1269
+ await session.endSession();
1270
+ }
1271
+ }
1272
+ };
1273
+ return proxyClientWithSchema(pongoClient, schema?.definition);
1274
+ };
1275
+
1276
+ //#endregion
1277
+ //#region src/core/utils/deepEquals.ts
1278
+ const deepEquals = (left, right) => {
1279
+ if (isEquatable(left)) return left.equals(right);
1280
+ if (Array.isArray(left)) return Array.isArray(right) && left.length === right.length && left.every((val, index) => deepEquals(val, right[index]));
1281
+ if (typeof left !== "object" || typeof right !== "object" || left === null || right === null) return left === right;
1282
+ if (Array.isArray(right)) return false;
1283
+ const keys1 = Object.keys(left);
1284
+ const keys2 = Object.keys(right);
1285
+ if (keys1.length !== keys2.length || !keys1.every((key) => keys2.includes(key))) return false;
1286
+ for (const key in left) {
1287
+ if (left[key] instanceof Function && right[key] instanceof Function) continue;
1288
+ if (!deepEquals(left[key], right[key])) return false;
1289
+ }
1290
+ return true;
1291
+ };
1292
+ const isEquatable = (left) => {
1293
+ return left && typeof left === "object" && "equals" in left && typeof left["equals"] === "function";
1294
+ };
1295
+
1296
+ //#endregion
1297
+ //#region src/core/utils/mapAsync.ts
1298
+ async function mapSequential(items, fn) {
1299
+ const results = [];
1300
+ for (let i = 0; i < items.length; i++) results.push(await fn(items[i], i));
1301
+ return results;
1302
+ }
1303
+ const mapParallel = (items, fn) => Promise.all(items.map(fn));
1304
+ const mapAsync = (items, fn, options = { parallel: false }) => options?.parallel ? mapParallel(items, fn) : mapSequential(items, fn);
1305
+
1306
+ //#endregion
1307
+ export { objectEntries as A, getIdsFromIdOnlyFilter as B, expectedVersionValue as C, PongoError as D, ConcurrencyError as E, isOperator as F, lruCache as G, pongoTransactionCache as H, PongoCollectionSchemaComponent as I, identityMapCache as K, pongoCollection as L, OperatorMap as M, QueryOperators as N, isNumber as O, hasOperators as P, transactionExecutorOrDefault as R, expectedVersion as S, operationResult as T, pongoCache as U, idFromFilter as V, noopCacheProvider as W, toDbSchemaMetadata as _, isEquatable as a, NO_CONCURRENCY_CHECK as b, pongoTransaction as c, PongoDatabase as d, PongoDatabaseSchemaComponent as f, toClientSchemaMetadata as g, proxyPongoDbWithSchema as h, deepEquals as i, PongoDatabaseCache as j, isString as k, PongoDriverRegistry as l, proxyClientWithSchema as m, mapParallel as n, pongoClient as o, pongoSchema as p, pongoCacheWrapper as q, mapSequential as r, pongoSession as s, mapAsync as t, pongoDriverRegistry as u, DOCUMENT_DOES_NOT_EXIST as v, isGeneralExpectedDocumentVersion as w, ObjectId as x, DOCUMENT_EXISTS as y, DocumentCommandHandler as z };
1308
+ //# sourceMappingURL=core-D_iZiiYe.js.map