@prosopo/database 1.0.2 → 2.0.1

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 (44) hide show
  1. package/dist/captchaDatabase/captchaDatabase.d.ts +4 -0
  2. package/dist/captchaDatabase/captchaDatabase.d.ts.map +1 -0
  3. package/dist/captchaDatabase/captchaDatabase.js +31 -0
  4. package/dist/captchaDatabase/captchaDatabase.js.map +1 -0
  5. package/dist/captchaDatabase/index.d.ts +1 -1
  6. package/dist/captchaDatabase/index.d.ts.map +1 -1
  7. package/dist/captchaDatabase/index.js +1 -1
  8. package/dist/captchaDatabase/index.js.map +1 -1
  9. package/dist/cjs/captchaDatabase/captchaDatabase.cjs +37 -0
  10. package/dist/cjs/captchaDatabase/index.cjs +2 -2
  11. package/dist/cjs/databases/mongo.cjs +176 -69
  12. package/dist/cjs/databases/mongoMemory.cjs +1 -1
  13. package/dist/cjs/index.cjs +2 -2
  14. package/dist/databases/index.d.ts +2 -2
  15. package/dist/databases/index.d.ts.map +1 -1
  16. package/dist/databases/index.js +3 -3
  17. package/dist/databases/index.js.map +1 -1
  18. package/dist/databases/mongo.d.ts +8 -7
  19. package/dist/databases/mongo.d.ts.map +1 -1
  20. package/dist/databases/mongo.js +191 -119
  21. package/dist/databases/mongo.js.map +1 -1
  22. package/dist/databases/mongoMemory.d.ts +2 -2
  23. package/dist/databases/mongoMemory.d.ts.map +1 -1
  24. package/dist/databases/mongoMemory.js +2 -2
  25. package/dist/databases/mongoMemory.js.map +1 -1
  26. package/dist/eventsDatabase/eventsDatabase.d.ts +1 -1
  27. package/dist/eventsDatabase/eventsDatabase.d.ts.map +1 -1
  28. package/dist/eventsDatabase/eventsDatabase.js +8 -6
  29. package/dist/eventsDatabase/eventsDatabase.js.map +1 -1
  30. package/dist/eventsDatabase/index.d.ts +1 -1
  31. package/dist/eventsDatabase/index.d.ts.map +1 -1
  32. package/dist/eventsDatabase/index.js +1 -1
  33. package/dist/eventsDatabase/index.js.map +1 -1
  34. package/dist/index.d.ts +3 -3
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +3 -3
  37. package/dist/index.js.map +1 -1
  38. package/package.json +44 -53
  39. package/vite.cjs.config.ts +3 -3
  40. package/dist/captchaDatabase/captchaDatabse.d.ts +0 -3
  41. package/dist/captchaDatabase/captchaDatabse.d.ts.map +0 -1
  42. package/dist/captchaDatabase/captchaDatabse.js +0 -12
  43. package/dist/captchaDatabase/captchaDatabse.js.map +0 -1
  44. package/dist/cjs/captchaDatabase/captchaDatabse.cjs +0 -14
@@ -1,17 +1,16 @@
1
- import { AsyncFactory, ProsopoDBError, ProsopoEnvError, getLoggerDefault } from '@prosopo/common';
2
- import { CaptchaStates, DatasetWithIdsAndTreeSchema, ScheduledTaskNames, ScheduledTaskStatus, } from '@prosopo/types';
3
- import { CaptchaRecordSchema, DatasetRecordSchema, PendingRecordSchema, PowCaptchaRecordSchema, ScheduledTaskRecordSchema, ScheduledTaskSchema, SolutionRecordSchema, UserCommitmentRecordSchema, UserCommitmentSchema, UserSolutionRecordSchema, UserSolutionSchema, } from '@prosopo/types-database';
4
- import { CaptchaStatus } from '@prosopo/captcha-contract/types-returns';
5
- import { ServerApiVersion } from 'mongodb';
6
- import { isHex } from '@polkadot/util/is';
7
- import mongoose from 'mongoose';
8
- mongoose.set('strictQuery', false);
9
- const DEFAULT_ENDPOINT = 'mongodb://127.0.0.1:27017';
1
+ import { isHex } from "@polkadot/util/is";
2
+ import { AsyncFactory, ProsopoDBError, ProsopoEnvError, getLoggerDefault, } from "@prosopo/common";
3
+ import { CaptchaStates, CaptchaStatus, DatasetWithIdsAndTreeSchema, ScheduledTaskNames, ScheduledTaskStatus, } from "@prosopo/types";
4
+ import { CaptchaRecordSchema, DatasetRecordSchema, PendingRecordSchema, PowCaptchaRecordSchema, ScheduledTaskRecordSchema, ScheduledTaskSchema, SolutionRecordSchema, UserCommitmentRecordSchema, UserCommitmentSchema, UserSolutionRecordSchema, UserSolutionSchema, } from "@prosopo/types-database";
5
+ import { ServerApiVersion } from "mongodb";
6
+ import mongoose from "mongoose";
7
+ mongoose.set("strictQuery", false);
8
+ const DEFAULT_ENDPOINT = "mongodb://127.0.0.1:27017";
10
9
  export class ProsopoDatabase extends AsyncFactory {
11
10
  constructor() {
12
11
  super();
13
- this.url = '';
14
- this.dbname = '';
12
+ this.url = "";
13
+ this.dbname = "";
15
14
  this.logger = getLoggerDefault();
16
15
  }
17
16
  async init(url, dbname, logger, authSource) {
@@ -19,7 +18,7 @@ export class ProsopoDatabase extends AsyncFactory {
19
18
  const parsedUrl = new URL(baseEndpoint);
20
19
  parsedUrl.pathname = dbname;
21
20
  if (authSource) {
22
- parsedUrl.searchParams.set('authSource', authSource);
21
+ parsedUrl.searchParams.set("authSource", authSource);
23
22
  }
24
23
  this.url = parsedUrl.toString();
25
24
  this.dbname = dbname;
@@ -28,7 +27,7 @@ export class ProsopoDatabase extends AsyncFactory {
28
27
  }
29
28
  getTables() {
30
29
  if (!this.tables) {
31
- throw new ProsopoDBError('DATABASE.TABLES_UNDEFINED', {
30
+ throw new ProsopoDBError("DATABASE.TABLES_UNDEFINED", {
32
31
  context: { failedFuncName: this.getTables.name },
33
32
  logger: this.logger,
34
33
  });
@@ -37,7 +36,7 @@ export class ProsopoDatabase extends AsyncFactory {
37
36
  }
38
37
  getConnection() {
39
38
  if (!this.connection) {
40
- throw new ProsopoDBError('DATABASE.CONNECTION_UNDEFINED', {
39
+ throw new ProsopoDBError("DATABASE.CONNECTION_UNDEFINED", {
41
40
  context: { failedFuncName: this.getConnection.name },
42
41
  logger: this.logger,
43
42
  });
@@ -45,48 +44,51 @@ export class ProsopoDatabase extends AsyncFactory {
45
44
  return this.connection;
46
45
  }
47
46
  async connect() {
48
- this.logger.info(`Mongo url: ${this.url.replace(/\w+:\w+/, '<Credentials>')}`);
47
+ this.logger.info(`Mongo url: ${this.url.replace(/\w+:\w+/, "<Credentials>")}`);
49
48
  this.connection = await new Promise((resolve, reject) => {
50
49
  const connection = mongoose.createConnection(this.url, {
51
50
  dbName: this.dbname,
52
51
  serverApi: ServerApiVersion.v1,
53
52
  });
54
- connection.on('open', () => {
53
+ connection.on("open", () => {
55
54
  this.logger.info(`Database connection to ${this.url} opened`);
56
55
  resolve(connection);
57
56
  });
58
- connection.on('error', (err) => {
57
+ connection.on("error", (err) => {
59
58
  this.logger.error(`Database error: ${err}`);
60
59
  reject(err);
61
60
  });
62
- connection.on('connected', () => {
61
+ connection.on("connected", () => {
63
62
  this.logger.info(`Database connected to ${this.url}`);
63
+ resolve(connection);
64
64
  });
65
- connection.on('disconnected', () => {
65
+ connection.on("disconnected", () => {
66
66
  this.logger.info(`Database disconnected from ${this.url}`);
67
67
  });
68
- connection.on('reconnected', () => {
68
+ connection.on("reconnected", () => {
69
69
  this.logger.info(`Database reconnected to ${this.url}`);
70
+ resolve(connection);
70
71
  });
71
- connection.on('reconnectFailed', () => {
72
+ connection.on("reconnectFailed", () => {
72
73
  this.logger.error(`Database reconnect failed to ${this.url}`);
73
74
  });
74
- connection.on('close', () => {
75
+ connection.on("close", () => {
75
76
  this.logger.info(`Database connection to ${this.url} closed`);
76
77
  });
77
- connection.on('fullsetup', () => {
78
+ connection.on("fullsetup", () => {
78
79
  this.logger.info(`Database connection to ${this.url} is fully setup`);
80
+ resolve(connection);
79
81
  });
80
82
  });
81
83
  this.tables = {
82
- captcha: this.connection.model('Captcha', CaptchaRecordSchema),
83
- powCaptcha: this.connection.model('PowCaptcha', PowCaptchaRecordSchema),
84
- dataset: this.connection.model('Dataset', DatasetRecordSchema),
85
- solution: this.connection.model('Solution', SolutionRecordSchema),
86
- commitment: this.connection.model('UserCommitment', UserCommitmentRecordSchema),
87
- usersolution: this.connection.model('UserSolution', UserSolutionRecordSchema),
88
- pending: this.connection.model('Pending', PendingRecordSchema),
89
- scheduler: this.connection.model('Scheduler', ScheduledTaskRecordSchema),
84
+ captcha: this.connection.model("Captcha", CaptchaRecordSchema),
85
+ powCaptcha: this.connection.model("PowCaptcha", PowCaptchaRecordSchema),
86
+ dataset: this.connection.model("Dataset", DatasetRecordSchema),
87
+ solution: this.connection.model("Solution", SolutionRecordSchema),
88
+ commitment: this.connection.model("UserCommitment", UserCommitmentRecordSchema),
89
+ usersolution: this.connection.model("UserSolution", UserSolutionRecordSchema),
90
+ pending: this.connection.model("Pending", PendingRecordSchema),
91
+ scheduler: this.connection.model("Scheduler", ScheduledTaskRecordSchema),
90
92
  };
91
93
  }
92
94
  async close() {
@@ -95,7 +97,7 @@ export class ProsopoDatabase extends AsyncFactory {
95
97
  }
96
98
  async storeDataset(dataset) {
97
99
  try {
98
- this.logger.debug(`Storing dataset in database`);
100
+ this.logger.debug("Storing dataset in database");
99
101
  const parsedDataset = DatasetWithIdsAndTreeSchema.parse(dataset);
100
102
  const datasetDoc = {
101
103
  datasetId: parsedDataset.datasetId,
@@ -112,7 +114,7 @@ export class ProsopoDatabase extends AsyncFactory {
112
114
  index,
113
115
  solved: !!solution?.length,
114
116
  }));
115
- this.logger.debug(`Inserting captcha records`);
117
+ this.logger.debug("Inserting captcha records");
116
118
  if (captchaDocs.length) {
117
119
  await this.tables?.captcha.bulkWrite(captchaDocs.map((captchaDoc) => ({
118
120
  updateOne: {
@@ -132,7 +134,7 @@ export class ProsopoDatabase extends AsyncFactory {
132
134
  datasetId: parsedDataset.datasetId,
133
135
  datasetContentId: parsedDataset.datasetContentId,
134
136
  }));
135
- this.logger.debug(`Inserting solution records`);
137
+ this.logger.debug("Inserting solution records");
136
138
  if (captchaSolutionDocs.length) {
137
139
  await this.tables?.solution.bulkWrite(captchaSolutionDocs.map((captchaSolutionDoc) => ({
138
140
  updateOne: {
@@ -142,23 +144,23 @@ export class ProsopoDatabase extends AsyncFactory {
142
144
  },
143
145
  })));
144
146
  }
145
- this.logger.debug(`Dataset stored in database`);
147
+ this.logger.debug("Dataset stored in database");
146
148
  }
147
149
  catch (err) {
148
- throw new ProsopoDBError('DATABASE.DATASET_LOAD_FAILED', {
150
+ throw new ProsopoDBError("DATABASE.DATASET_LOAD_FAILED", {
149
151
  context: { failedFuncName: this.storeDataset.name, error: err },
150
152
  logger: this.logger,
151
153
  });
152
154
  }
153
155
  }
154
156
  async getSolutions(datasetId) {
155
- const docs = await this.tables?.solution.find({ datasetId }).lean();
157
+ const docs = await this.tables?.solution
158
+ .find({ datasetId })
159
+ .lean();
156
160
  return docs ? docs : [];
157
161
  }
158
162
  async getDataset(datasetId) {
159
- const datasetDoc = await this.tables?.dataset
160
- .findOne({ datasetId: datasetId })
161
- .lean();
163
+ const datasetDoc = await this.tables?.dataset.findOne({ datasetId: datasetId }).lean();
162
164
  if (datasetDoc) {
163
165
  const { datasetContentId, format, contentTree, solutionTree } = datasetDoc;
164
166
  const captchas = (await this.tables?.captcha.find({ datasetId }).lean()) || [];
@@ -188,13 +190,13 @@ export class ProsopoDatabase extends AsyncFactory {
188
190
  }),
189
191
  };
190
192
  }
191
- throw new ProsopoDBError('DATABASE.DATASET_GET_FAILED', {
193
+ throw new ProsopoDBError("DATABASE.DATASET_GET_FAILED", {
192
194
  context: { failedFuncName: this.getDataset.name, datasetId },
193
195
  });
194
196
  }
195
197
  async getRandomCaptcha(solved, datasetId, size) {
196
198
  if (!isHex(datasetId)) {
197
- throw new ProsopoDBError('DATABASE.INVALID_HASH', {
199
+ throw new ProsopoDBError("DATABASE.INVALID_HASH", {
198
200
  context: { failedFuncName: this.getRandomCaptcha.name, datasetId },
199
201
  });
200
202
  }
@@ -214,26 +216,33 @@ export class ProsopoDatabase extends AsyncFactory {
214
216
  },
215
217
  ]);
216
218
  const docs = await cursor;
217
- if (docs && docs.length) {
219
+ if (docs?.length) {
218
220
  return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
219
221
  }
220
- throw new ProsopoDBError('DATABASE.CAPTCHA_GET_FAILED', {
221
- context: { failedFuncName: this.getRandomCaptcha.name, solved, datasetId, size },
222
+ throw new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
223
+ context: {
224
+ failedFuncName: this.getRandomCaptcha.name,
225
+ solved,
226
+ datasetId,
227
+ size,
228
+ },
222
229
  });
223
230
  }
224
231
  async getCaptchaById(captchaId) {
225
- const cursor = this.tables?.captcha.find({ captchaId: { $in: captchaId } }).lean();
232
+ const cursor = this.tables?.captcha
233
+ .find({ captchaId: { $in: captchaId } })
234
+ .lean();
226
235
  const docs = await cursor;
227
- if (docs && docs.length) {
236
+ if (docs?.length) {
228
237
  return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
229
238
  }
230
- throw new ProsopoDBError('DATABASE.CAPTCHA_GET_FAILED', {
239
+ throw new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
231
240
  context: { failedFuncName: this.getCaptchaById.name, captchaId },
232
241
  });
233
242
  }
234
243
  async updateCaptcha(captcha, datasetId) {
235
244
  if (!isHex(datasetId)) {
236
- throw new ProsopoDBError('DATABASE.INVALID_HASH', {
245
+ throw new ProsopoDBError("DATABASE.INVALID_HASH", {
237
246
  context: { failedFuncName: this.updateCaptcha.name, datasetId },
238
247
  });
239
248
  }
@@ -241,7 +250,7 @@ export class ProsopoDatabase extends AsyncFactory {
241
250
  await this.tables?.captcha.updateOne({ datasetId }, { $set: captcha }, { upsert: false });
242
251
  }
243
252
  catch (err) {
244
- throw new ProsopoDBError('DATABASE.CAPTCHA_UPDATE_FAILED', {
253
+ throw new ProsopoDBError("DATABASE.CAPTCHA_UPDATE_FAILED", {
245
254
  context: { failedFuncName: this.getDatasetDetails.name, error: err },
246
255
  });
247
256
  }
@@ -251,16 +260,21 @@ export class ProsopoDatabase extends AsyncFactory {
251
260
  }
252
261
  async getDatasetDetails(datasetId) {
253
262
  if (!isHex(datasetId)) {
254
- throw new ProsopoDBError('DATABASE.INVALID_HASH', {
263
+ throw new ProsopoDBError("DATABASE.INVALID_HASH", {
255
264
  context: { failedFuncName: this.getDatasetDetails.name, datasetId },
256
265
  });
257
266
  }
258
- const doc = await this.tables?.dataset.findOne({ datasetId }).lean();
267
+ const doc = await this.tables?.dataset
268
+ .findOne({ datasetId })
269
+ .lean();
259
270
  if (doc) {
260
271
  return doc;
261
272
  }
262
- throw new ProsopoDBError('DATABASE.DATASET_GET_FAILED', {
263
- context: { failedFuncName: this.getDatasetDetails.name, datasetId },
273
+ throw new ProsopoDBError("DATABASE.DATASET_GET_FAILED", {
274
+ context: {
275
+ failedFuncName: this.getDatasetDetails.name,
276
+ datasetId,
277
+ },
264
278
  });
265
279
  }
266
280
  async storeDappUserSolution(captchas, commit) {
@@ -288,24 +302,29 @@ export class ProsopoDatabase extends AsyncFactory {
288
302
  await this.tables?.usersolution.bulkWrite(ops);
289
303
  }
290
304
  }
291
- async storePowCaptchaRecord(challenge, checked) {
292
- if (!this.tables) {
293
- throw new ProsopoEnvError('DATABASE.DATABASE_UNDEFINED', {
294
- context: { failedFuncName: this.storePowCaptchaRecord.name },
295
- logger: this.logger,
296
- });
297
- }
305
+ async storePowCaptchaRecord(challenge, components, checked, stored = false) {
306
+ const tables = this.getTables();
298
307
  const powCaptchaRecord = {
299
308
  challenge,
309
+ ...components,
300
310
  checked,
311
+ stored
301
312
  };
302
313
  try {
303
- await this.tables.powCaptcha.create(powCaptchaRecord);
304
- this.logger.info('PowCaptcha record added successfully', { challenge, checked });
314
+ await tables.powCaptcha.create(powCaptchaRecord);
315
+ this.logger.info("PowCaptcha record added successfully", {
316
+ challenge,
317
+ checked,
318
+ stored
319
+ });
305
320
  }
306
321
  catch (error) {
307
- this.logger.error('Failed to add PowCaptcha record', { error, challenge, checked });
308
- throw new ProsopoDBError('DATABASE.CAPTCHA_UPDATE_FAILED', {
322
+ this.logger.error("Failed to add PowCaptcha record", {
323
+ error,
324
+ challenge,
325
+ checked,
326
+ });
327
+ throw new ProsopoDBError("DATABASE.CAPTCHA_UPDATE_FAILED", {
309
328
  context: { error, challenge, checked },
310
329
  logger: this.logger,
311
330
  });
@@ -313,60 +332,70 @@ export class ProsopoDatabase extends AsyncFactory {
313
332
  }
314
333
  async getPowCaptchaRecordByChallenge(challenge) {
315
334
  if (!this.tables) {
316
- throw new ProsopoEnvError('DATABASE.DATABASE_UNDEFINED', {
335
+ throw new ProsopoEnvError("DATABASE.DATABASE_UNDEFINED", {
317
336
  context: { failedFuncName: this.getPowCaptchaRecordByChallenge.name },
318
337
  logger: this.logger,
319
338
  });
320
339
  }
321
340
  try {
322
- const record = await this.tables.powCaptcha.findOne({ challenge }).lean();
341
+ const record = await this.tables.powCaptcha
342
+ .findOne({ challenge })
343
+ .lean();
323
344
  if (record) {
324
- this.logger.info('PowCaptcha record retrieved successfully', { challenge });
345
+ this.logger.info("PowCaptcha record retrieved successfully", {
346
+ challenge,
347
+ });
325
348
  return record;
326
349
  }
327
- else {
328
- this.logger.info('No PowCaptcha record found', { challenge });
329
- return null;
330
- }
350
+ this.logger.info("No PowCaptcha record found", { challenge });
351
+ return null;
331
352
  }
332
353
  catch (error) {
333
- this.logger.error('Failed to retrieve PowCaptcha record', { error, challenge });
334
- throw new ProsopoDBError('DATABASE.CAPTCHA_GET_FAILED', {
354
+ this.logger.error("Failed to retrieve PowCaptcha record", {
355
+ error,
356
+ challenge,
357
+ });
358
+ throw new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
335
359
  context: { error, challenge },
336
360
  logger: this.logger,
337
361
  });
338
362
  }
339
363
  }
340
364
  async updatePowCaptchaRecord(challenge, checked) {
341
- if (!this.tables) {
342
- throw new ProsopoEnvError('DATABASE.DATABASE_UNDEFINED', {
343
- context: { failedFuncName: this.updatePowCaptchaRecord.name },
344
- logger: this.logger,
345
- });
346
- }
365
+ const tables = this.getTables();
347
366
  try {
348
- const updateResult = await this.tables.powCaptcha.updateOne({ challenge }, { $set: { checked } });
367
+ const updateResult = await tables.powCaptcha.updateOne({ challenge }, { $set: { checked } });
349
368
  if (updateResult.matchedCount === 0) {
350
- this.logger.info('No PowCaptcha record found to update', { challenge, checked });
351
- throw new ProsopoDBError('DATABASE.CAPTCHA_GET_FAILED', {
369
+ this.logger.info("No PowCaptcha record found to update", {
370
+ challenge,
371
+ checked,
372
+ });
373
+ throw new ProsopoDBError("DATABASE.CAPTCHA_GET_FAILED", {
352
374
  context: { challenge, checked },
353
375
  logger: this.logger,
354
376
  });
355
377
  }
356
- else {
357
- this.logger.info('PowCaptcha record updated successfully', { challenge, checked });
358
- }
378
+ this.logger.info("PowCaptcha record updated successfully", {
379
+ challenge,
380
+ checked,
381
+ });
359
382
  }
360
383
  catch (error) {
361
- this.logger.error('Failed to update PowCaptcha record', { error, challenge, checked });
362
- throw new ProsopoDBError('DATABASE.CAPTCHA_UPDATE_FAILED', {
384
+ this.logger.error("Failed to update PowCaptcha record", {
385
+ error,
386
+ challenge,
387
+ checked,
388
+ });
389
+ throw new ProsopoDBError("DATABASE.CAPTCHA_UPDATE_FAILED", {
363
390
  context: { error, challenge, checked },
364
391
  logger: this.logger,
365
392
  });
366
393
  }
367
394
  }
368
395
  async getProcessedDappUserSolutions() {
369
- const docs = await this.tables?.usersolution.find({ processed: true }).lean();
396
+ const docs = await this.tables?.usersolution
397
+ .find({ processed: true })
398
+ .lean();
370
399
  return docs ? docs.map((doc) => UserSolutionSchema.parse(doc)) : [];
371
400
  }
372
401
  async getProcessedDappUserCommitments() {
@@ -388,20 +417,40 @@ export class ProsopoDatabase extends AsyncFactory {
388
417
  async markDappUserCommitmentsStored(commitmentIds) {
389
418
  await this.tables?.commitment.updateMany({ id: { $in: commitmentIds } }, { $set: { stored: true } }, { upsert: false });
390
419
  }
420
+ async getUnstoredDappUserPoWCommitments() {
421
+ const docs = await this.tables?.powCaptcha
422
+ .find({
423
+ $or: [{ stored: false }, { stored: { $exists: false } }],
424
+ })
425
+ .lean();
426
+ return docs || [];
427
+ }
428
+ async markDappUserPoWCommitmentsStored(challenges) {
429
+ await this.tables?.powCaptcha.updateMany({ challenge: { $in: challenges } }, { $set: { stored: true } }, { upsert: false });
430
+ }
391
431
  async getBatchedDappUserCommitments() {
392
432
  const docs = await this.tables?.commitment.find({ batched: true }).lean();
393
433
  return docs ? docs.map((doc) => UserCommitmentSchema.parse(doc)) : [];
394
434
  }
395
435
  async removeProcessedDappUserSolutions(commitmentIds) {
396
- return await this.tables?.usersolution.deleteMany({ processed: true, commitmentId: { $in: commitmentIds } });
436
+ return await this.tables?.usersolution.deleteMany({
437
+ processed: true,
438
+ commitmentId: { $in: commitmentIds },
439
+ });
397
440
  }
398
441
  async removeProcessedDappUserCommitments(commitmentIds) {
399
- return await this.tables?.commitment.deleteMany({ processed: true, id: { $in: commitmentIds } });
442
+ return await this.tables?.commitment.deleteMany({
443
+ processed: true,
444
+ id: { $in: commitmentIds },
445
+ });
400
446
  }
401
447
  async storeDappUserPending(userAccount, requestHash, salt, deadlineTimestamp, requestedAtBlock) {
402
448
  if (!isHex(requestHash)) {
403
- throw new ProsopoDBError('DATABASE.INVALID_HASH', {
404
- context: { failedFuncName: this.storeDappUserPending.name, requestHash },
449
+ throw new ProsopoDBError("DATABASE.INVALID_HASH", {
450
+ context: {
451
+ failedFuncName: this.storeDappUserPending.name,
452
+ requestHash,
453
+ },
405
454
  });
406
455
  }
407
456
  const pendingRecord = {
@@ -416,24 +465,25 @@ export class ProsopoDatabase extends AsyncFactory {
416
465
  }
417
466
  async getDappUserPending(requestHash) {
418
467
  if (!isHex(requestHash)) {
419
- throw new ProsopoEnvError('DATABASE.INVALID_HASH', {
468
+ throw new ProsopoEnvError("DATABASE.INVALID_HASH", {
420
469
  context: { failedFuncName: this.getDappUserPending.name, requestHash },
421
470
  });
422
471
  }
423
- const doc = await this.tables?.pending
424
- .findOne({ requestHash: requestHash })
425
- .lean();
472
+ const doc = await this.tables?.pending.findOne({ requestHash: requestHash }).lean();
426
473
  if (doc) {
427
474
  return doc;
428
475
  }
429
- throw new ProsopoEnvError('DATABASE.PENDING_RECORD_NOT_FOUND', {
476
+ throw new ProsopoEnvError("DATABASE.PENDING_RECORD_NOT_FOUND", {
430
477
  context: { failedFuncName: this.getDappUserPending.name, requestHash },
431
478
  });
432
479
  }
433
480
  async updateDappUserPendingStatus(requestHash) {
434
481
  if (!isHex(requestHash)) {
435
- throw new ProsopoEnvError('DATABASE.INVALID_HASH', {
436
- context: { failedFuncName: this.updateDappUserPendingStatus.name, requestHash },
482
+ throw new ProsopoEnvError("DATABASE.INVALID_HASH", {
483
+ context: {
484
+ failedFuncName: this.updateDappUserPendingStatus.name,
485
+ requestHash,
486
+ },
437
487
  });
438
488
  }
439
489
  await this.tables?.pending.updateOne({ requestHash: requestHash }, {
@@ -453,15 +503,17 @@ export class ProsopoDatabase extends AsyncFactory {
453
503
  if (docs) {
454
504
  return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
455
505
  }
456
- throw new ProsopoEnvError('DATABASE.CAPTCHA_GET_FAILED');
506
+ throw new ProsopoEnvError("DATABASE.CAPTCHA_GET_FAILED");
457
507
  }
458
508
  async getAllDappUserSolutions(captchaId) {
459
- const cursor = this.tables?.usersolution?.find({ captchaId: { $in: captchaId } }).lean();
509
+ const cursor = this.tables?.usersolution
510
+ ?.find({ captchaId: { $in: captchaId } })
511
+ .lean();
460
512
  const docs = await cursor;
461
513
  if (docs) {
462
514
  return docs.map(({ _id, ...keepAttrs }) => keepAttrs);
463
515
  }
464
- throw new ProsopoEnvError('DATABASE.SOLUTION_GET_FAILED');
516
+ throw new ProsopoEnvError("DATABASE.SOLUTION_GET_FAILED");
465
517
  }
466
518
  async getDatasetIdWithSolvedCaptchasOfSizeN(solvedCaptchaCount) {
467
519
  const cursor = this.tables?.solution.aggregate([
@@ -470,7 +522,7 @@ export class ProsopoDatabase extends AsyncFactory {
470
522
  },
471
523
  {
472
524
  $group: {
473
- _id: '$datasetId',
525
+ _id: "$datasetId",
474
526
  count: { $sum: 1 },
475
527
  },
476
528
  },
@@ -484,15 +536,18 @@ export class ProsopoDatabase extends AsyncFactory {
484
536
  },
485
537
  ]);
486
538
  const docs = await cursor;
487
- if (docs && docs.length) {
539
+ if (docs?.length) {
488
540
  return docs[0]._id;
489
541
  }
490
- throw new ProsopoDBError('DATABASE.DATASET_WITH_SOLUTIONS_GET_FAILED');
542
+ throw new ProsopoDBError("DATABASE.DATASET_WITH_SOLUTIONS_GET_FAILED");
491
543
  }
492
544
  async getRandomSolvedCaptchasFromSingleDataset(datasetId, size) {
493
545
  if (!isHex(datasetId)) {
494
- throw new ProsopoDBError('DATABASE.INVALID_HASH', {
495
- context: { failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name, datasetId },
546
+ throw new ProsopoDBError("DATABASE.INVALID_HASH", {
547
+ context: {
548
+ failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name,
549
+ datasetId,
550
+ },
496
551
  });
497
552
  }
498
553
  const sampleSize = size ? Math.abs(Math.trunc(size)) : 1;
@@ -508,11 +563,15 @@ export class ProsopoDatabase extends AsyncFactory {
508
563
  },
509
564
  ]);
510
565
  const docs = await cursor;
511
- if (docs && docs.length) {
566
+ if (docs?.length) {
512
567
  return docs;
513
568
  }
514
- throw new ProsopoDBError('DATABASE.SOLUTION_GET_FAILED', {
515
- context: { failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name, datasetId, size },
569
+ throw new ProsopoDBError("DATABASE.SOLUTION_GET_FAILED", {
570
+ context: {
571
+ failedFuncName: this.getRandomSolvedCaptchasFromSingleDataset.name,
572
+ datasetId,
573
+ size,
574
+ },
516
575
  });
517
576
  }
518
577
  async getDappUserSolutionById(commitmentId) {
@@ -525,12 +584,14 @@ export class ProsopoDatabase extends AsyncFactory {
525
584
  if (doc) {
526
585
  return doc;
527
586
  }
528
- throw new ProsopoDBError('DATABASE.SOLUTION_GET_FAILED', {
587
+ throw new ProsopoDBError("DATABASE.SOLUTION_GET_FAILED", {
529
588
  context: { failedFuncName: this.getCaptchaById.name, commitmentId },
530
589
  });
531
590
  }
532
591
  async getDappUserCommitmentById(commitmentId) {
533
- const commitmentCursor = this.tables?.commitment?.findOne({ id: commitmentId }).lean();
592
+ const commitmentCursor = this.tables?.commitment
593
+ ?.findOne({ id: commitmentId })
594
+ .lean();
534
595
  const doc = await commitmentCursor;
535
596
  return doc ? UserCommitmentSchema.parse(doc) : undefined;
536
597
  }
@@ -547,7 +608,9 @@ export class ProsopoDatabase extends AsyncFactory {
547
608
  .lean();
548
609
  }
549
610
  catch (err) {
550
- throw new ProsopoDBError('DATABASE.SOLUTION_APPROVE_FAILED', { context: { error: err, commitmentId } });
611
+ throw new ProsopoDBError("DATABASE.SOLUTION_APPROVE_FAILED", {
612
+ context: { error: err, commitmentId },
613
+ });
551
614
  }
552
615
  }
553
616
  async flagProcessedDappUserSolutions(captchaIds) {
@@ -557,7 +620,9 @@ export class ProsopoDatabase extends AsyncFactory {
557
620
  .lean();
558
621
  }
559
622
  catch (err) {
560
- throw new ProsopoDBError('DATABASE.SOLUTION_FLAG_FAILED', { context: { error: err, captchaIds } });
623
+ throw new ProsopoDBError("DATABASE.SOLUTION_FLAG_FAILED", {
624
+ context: { error: err, captchaIds },
625
+ });
561
626
  }
562
627
  }
563
628
  async flagProcessedDappUserCommitments(commitmentIds) {
@@ -568,7 +633,9 @@ export class ProsopoDatabase extends AsyncFactory {
568
633
  .lean();
569
634
  }
570
635
  catch (err) {
571
- throw new ProsopoDBError('DATABASE.COMMITMENT_FLAG_FAILED', { context: { error: err, commitmentIds } });
636
+ throw new ProsopoDBError("DATABASE.COMMITMENT_FLAG_FAILED", {
637
+ context: { error: err, commitmentIds },
638
+ });
572
639
  }
573
640
  }
574
641
  async flagBatchedDappUserCommitments(commitmentIds) {
@@ -579,12 +646,17 @@ export class ProsopoDatabase extends AsyncFactory {
579
646
  .lean();
580
647
  }
581
648
  catch (err) {
582
- throw new ProsopoDBError('DATABASE.COMMITMENT_FLAG_FAILED', { context: { error: err, commitmentIds } });
649
+ throw new ProsopoDBError("DATABASE.COMMITMENT_FLAG_FAILED", {
650
+ context: { error: err, commitmentIds },
651
+ });
583
652
  }
584
653
  }
585
654
  async getLastBatchCommitTime() {
586
655
  const cursor = this.tables?.scheduler
587
- ?.findOne({ processName: ScheduledTaskNames.BatchCommitment, status: ScheduledTaskStatus.Completed })
656
+ ?.findOne({
657
+ processName: ScheduledTaskNames.BatchCommitment,
658
+ status: ScheduledTaskStatus.Completed,
659
+ })
588
660
  .sort({ timestamp: -1 });
589
661
  const doc = await cursor?.lean();
590
662
  if (doc) {
@@ -601,7 +673,7 @@ export class ProsopoDatabase extends AsyncFactory {
601
673
  async getLastScheduledTaskStatus(task, status) {
602
674
  const lookup = { processName: task };
603
675
  if (status) {
604
- lookup['status'] = status;
676
+ lookup.status = status;
605
677
  }
606
678
  const cursor = await this.tables?.scheduler
607
679
  ?.findOne(lookup)