@prosopo/database 3.15.19 → 3.15.21

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 (38) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +20 -17
  2. package/.turbo/turbo-build$colon$tsc.log +16 -16
  3. package/.turbo/turbo-build.log +21 -18
  4. package/CHANGELOG.md +24 -0
  5. package/dist/_virtual/_rolldown/runtime.js +3 -0
  6. package/dist/base/index.js +1 -4
  7. package/dist/base/mongo.js +133 -137
  8. package/dist/base/mongoMemory.js +21 -21
  9. package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
  10. package/dist/cjs/base/index.cjs +4 -6
  11. package/dist/cjs/base/mongo.cjs +140 -143
  12. package/dist/cjs/base/mongoMemory.cjs +22 -22
  13. package/dist/cjs/databases/captcha.cjs +220 -256
  14. package/dist/cjs/databases/centralDbStreamer.cjs +148 -170
  15. package/dist/cjs/databases/client.cjs +46 -62
  16. package/dist/cjs/databases/index.cjs +19 -19
  17. package/dist/cjs/databases/provider.cjs +1827 -2251
  18. package/dist/cjs/index.cjs +25 -23
  19. package/dist/cjs/mongooseOptions.cjs +59 -58
  20. package/dist/cjs/redisCache.cjs +432 -474
  21. package/dist/databases/captcha.d.ts.map +1 -1
  22. package/dist/databases/captcha.js +217 -253
  23. package/dist/databases/captcha.js.map +1 -1
  24. package/dist/databases/centralDbStreamer.js +147 -169
  25. package/dist/databases/client.js +44 -60
  26. package/dist/databases/index.js +10 -14
  27. package/dist/databases/provider.d.ts +4 -4
  28. package/dist/databases/provider.d.ts.map +1 -1
  29. package/dist/databases/provider.js +1823 -2247
  30. package/dist/databases/provider.js.map +1 -1
  31. package/dist/index.js +9 -18
  32. package/dist/mongooseOptions.js +59 -59
  33. package/dist/redisCache.js +432 -474
  34. package/dist/tests/integration/saveCaptchasSessionUpsert.integration.test.d.ts +2 -0
  35. package/dist/tests/integration/saveCaptchasSessionUpsert.integration.test.d.ts.map +1 -0
  36. package/dist/tests/integration/saveCaptchasSessionUpsert.integration.test.js +64 -0
  37. package/dist/tests/integration/saveCaptchasSessionUpsert.integration.test.js.map +1 -0
  38. package/package.json +14 -14
@@ -1,171 +1,149 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const logger = require("@prosopo/logger");
4
- const captcha = require("./captcha.cjs");
5
- class CentralDbStreamer {
6
- constructor(mongoCaptchaUri, logger$1) {
7
- this.lastFailureTime = 0;
8
- this.logger = logger$1 || logger.getLogger("info", "CentralDbStreamer");
9
- this.db = new captcha.CaptchaDatabase(
10
- mongoCaptchaUri,
11
- void 0,
12
- void 0,
13
- this.logger
14
- );
15
- }
16
- static {
17
- this.RECONNECT_COOLDOWN_MS = 5e3;
18
- }
19
- ensureConnected() {
20
- if (this.connectPromise && !this.db.connected) {
21
- this.connectPromise = void 0;
22
- }
23
- if (!this.connectPromise) {
24
- const elapsed = Date.now() - this.lastFailureTime;
25
- if (elapsed < CentralDbStreamer.RECONNECT_COOLDOWN_MS) {
26
- return Promise.reject(
27
- new Error("CentralDbStreamer reconnect cooldown")
28
- );
29
- }
30
- this.connectPromise = this.db.connect().catch((err) => {
31
- this.logger.error(() => ({
32
- err,
33
- msg: "CentralDbStreamer failed to connect"
34
- }));
35
- this.lastFailureTime = Date.now();
36
- this.connectPromise = void 0;
37
- throw err;
38
- });
39
- }
40
- return this.connectPromise;
41
- }
42
- getRecordTimestamp(record) {
43
- return record.lastUpdatedTimestamp ?? record.createdAt ?? record.requestedAtTimestamp ?? /* @__PURE__ */ new Date();
44
- }
45
- /**
46
- * Stream a PoW captcha record (create or update) to the central DB.
47
- * Fire-and-forget: errors are logged, never thrown.
48
- */
49
- streamPowRecord(record, markStored) {
50
- const timestamp = this.getRecordTimestamp(record);
51
- this.ensureConnected().then(() => {
52
- const { _id, ...safeDoc } = record;
53
- return this.db.tables.powcaptcha.updateOne(
54
- { challenge: safeDoc.challenge },
55
- { $set: safeDoc },
56
- { upsert: true }
57
- );
58
- }).then(() => markStored?.(timestamp)).catch((err) => {
59
- this.logger.error(() => ({
60
- err,
61
- msg: "Failed to stream PoW record to central DB"
62
- }));
63
- });
64
- }
65
- /**
66
- * Stream a partial PoW update by fetching the full record first, then upserting.
67
- */
68
- streamPowUpdate(getFullRecord, markStored) {
69
- getFullRecord().then((record) => {
70
- if (record) {
71
- this.streamPowRecord(record, markStored);
72
- }
73
- }).catch((err) => {
74
- this.logger.error(() => ({
75
- err,
76
- msg: "Failed to fetch PoW record for central DB streaming"
77
- }));
78
- });
79
- }
80
- /**
81
- * Stream an image captcha commitment record to the central DB.
82
- * Fire-and-forget: errors are logged, never thrown.
83
- */
84
- streamImageRecord(record, markStored) {
85
- const timestamp = this.getRecordTimestamp(record);
86
- this.ensureConnected().then(() => {
87
- const { _id, ...safeDoc } = record;
88
- return this.db.tables.commitment.updateOne(
89
- { id: safeDoc.id },
90
- { $set: safeDoc },
91
- { upsert: true }
92
- );
93
- }).then(() => markStored?.(timestamp)).catch((err) => {
94
- this.logger.error(() => ({
95
- err,
96
- msg: "Failed to stream image record to central DB"
97
- }));
98
- });
99
- }
100
- /**
101
- * Stream an image captcha update by fetching the full record first.
102
- */
103
- streamImageUpdate(getFullRecord, markStored) {
104
- getFullRecord().then((record) => {
105
- if (record) {
106
- this.streamImageRecord(record, markStored);
107
- }
108
- }).catch((err) => {
109
- this.logger.error(() => ({
110
- err,
111
- msg: "Failed to fetch image record for central DB streaming"
112
- }));
113
- });
114
- }
115
- /**
116
- * Stream a puzzle captcha record (create or update) to the central DB.
117
- * Fire-and-forget: errors are logged, never thrown.
118
- */
119
- streamPuzzleRecord(record, markStored) {
120
- const timestamp = this.getRecordTimestamp(record);
121
- this.ensureConnected().then(() => {
122
- const { _id, ...safeDoc } = record;
123
- return this.db.tables.puzzlecaptcha.updateOne(
124
- { challenge: safeDoc.challenge },
125
- { $set: safeDoc },
126
- { upsert: true }
127
- );
128
- }).then(() => markStored?.(timestamp)).catch((err) => {
129
- this.logger.error(() => ({
130
- err,
131
- msg: "Failed to stream puzzle record to central DB"
132
- }));
133
- });
134
- }
135
- /**
136
- * Stream a partial puzzle update by fetching the full record first, then upserting.
137
- */
138
- streamPuzzleUpdate(getFullRecord, markStored) {
139
- getFullRecord().then((record) => {
140
- if (record) {
141
- this.streamPuzzleRecord(record, markStored);
142
- }
143
- }).catch((err) => {
144
- this.logger.error(() => ({
145
- err,
146
- msg: "Failed to fetch puzzle record for central DB streaming"
147
- }));
148
- });
149
- }
150
- /**
151
- * Stream a session record to the central DB.
152
- * Fire-and-forget: errors are logged, never thrown.
153
- */
154
- streamSessionRecord(record, markStored) {
155
- const timestamp = this.getRecordTimestamp(record);
156
- this.ensureConnected().then(() => {
157
- const { _id, ...safeDoc } = record;
158
- return this.db.tables.session.updateOne(
159
- { sessionId: safeDoc.sessionId },
160
- { $set: safeDoc },
161
- { upsert: true }
162
- );
163
- }).then(() => markStored?.(timestamp)).catch((err) => {
164
- this.logger.error(() => ({
165
- err,
166
- msg: "Failed to stream session record to central DB"
167
- }));
168
- });
169
- }
170
- }
1
+ const require_captcha = require("./captcha.cjs");
2
+ let _prosopo_logger = require("@prosopo/logger");
3
+ //#region src/databases/centralDbStreamer.ts
4
+ /**
5
+ * Fire-and-forget streamer that sends captcha records to a central database
6
+ * in real-time. Errors are logged but never thrown, so local operations
7
+ * are never blocked or disrupted.
8
+ *
9
+ * Unlike the batch `saveCaptchas()` method on CaptchaDatabase, this maintains
10
+ * a persistent connection and upserts individual records as they arrive.
11
+ *
12
+ * After a successful central write, the provided `markStored` callback is
13
+ * called with the record's `lastUpdatedTimestamp` so the batch cron can
14
+ * determine whether the stored version is still current.
15
+ */
16
+ var CentralDbStreamer = class CentralDbStreamer {
17
+ static {
18
+ this.RECONNECT_COOLDOWN_MS = 5e3;
19
+ }
20
+ constructor(mongoCaptchaUri, logger) {
21
+ this.lastFailureTime = 0;
22
+ this.logger = logger || (0, _prosopo_logger.getLogger)("info", "CentralDbStreamer");
23
+ this.db = new require_captcha.CaptchaDatabase(mongoCaptchaUri, void 0, void 0, this.logger);
24
+ }
25
+ ensureConnected() {
26
+ if (this.connectPromise && !this.db.connected) this.connectPromise = void 0;
27
+ if (!this.connectPromise) {
28
+ if (Date.now() - this.lastFailureTime < CentralDbStreamer.RECONNECT_COOLDOWN_MS) return Promise.reject(/* @__PURE__ */ new Error("CentralDbStreamer reconnect cooldown"));
29
+ this.connectPromise = this.db.connect().catch((err) => {
30
+ this.logger.error(() => ({
31
+ err,
32
+ msg: "CentralDbStreamer failed to connect"
33
+ }));
34
+ this.lastFailureTime = Date.now();
35
+ this.connectPromise = void 0;
36
+ throw err;
37
+ });
38
+ }
39
+ return this.connectPromise;
40
+ }
41
+ getRecordTimestamp(record) {
42
+ return record.lastUpdatedTimestamp ?? record.createdAt ?? record.requestedAtTimestamp ?? /* @__PURE__ */ new Date();
43
+ }
44
+ /**
45
+ * Stream a PoW captcha record (create or update) to the central DB.
46
+ * Fire-and-forget: errors are logged, never thrown.
47
+ */
48
+ streamPowRecord(record, markStored) {
49
+ const timestamp = this.getRecordTimestamp(record);
50
+ this.ensureConnected().then(() => {
51
+ const { _id, ...safeDoc } = record;
52
+ return this.db.tables.powcaptcha.updateOne({ challenge: safeDoc.challenge }, { $set: safeDoc }, { upsert: true });
53
+ }).then(() => markStored?.(timestamp)).catch((err) => {
54
+ this.logger.error(() => ({
55
+ err,
56
+ msg: "Failed to stream PoW record to central DB"
57
+ }));
58
+ });
59
+ }
60
+ /**
61
+ * Stream a partial PoW update by fetching the full record first, then upserting.
62
+ */
63
+ streamPowUpdate(getFullRecord, markStored) {
64
+ getFullRecord().then((record) => {
65
+ if (record) this.streamPowRecord(record, markStored);
66
+ }).catch((err) => {
67
+ this.logger.error(() => ({
68
+ err,
69
+ msg: "Failed to fetch PoW record for central DB streaming"
70
+ }));
71
+ });
72
+ }
73
+ /**
74
+ * Stream an image captcha commitment record to the central DB.
75
+ * Fire-and-forget: errors are logged, never thrown.
76
+ */
77
+ streamImageRecord(record, markStored) {
78
+ const timestamp = this.getRecordTimestamp(record);
79
+ this.ensureConnected().then(() => {
80
+ const { _id, ...safeDoc } = record;
81
+ return this.db.tables.commitment.updateOne({ id: safeDoc.id }, { $set: safeDoc }, { upsert: true });
82
+ }).then(() => markStored?.(timestamp)).catch((err) => {
83
+ this.logger.error(() => ({
84
+ err,
85
+ msg: "Failed to stream image record to central DB"
86
+ }));
87
+ });
88
+ }
89
+ /**
90
+ * Stream an image captcha update by fetching the full record first.
91
+ */
92
+ streamImageUpdate(getFullRecord, markStored) {
93
+ getFullRecord().then((record) => {
94
+ if (record) this.streamImageRecord(record, markStored);
95
+ }).catch((err) => {
96
+ this.logger.error(() => ({
97
+ err,
98
+ msg: "Failed to fetch image record for central DB streaming"
99
+ }));
100
+ });
101
+ }
102
+ /**
103
+ * Stream a puzzle captcha record (create or update) to the central DB.
104
+ * Fire-and-forget: errors are logged, never thrown.
105
+ */
106
+ streamPuzzleRecord(record, markStored) {
107
+ const timestamp = this.getRecordTimestamp(record);
108
+ this.ensureConnected().then(() => {
109
+ const { _id, ...safeDoc } = record;
110
+ return this.db.tables.puzzlecaptcha.updateOne({ challenge: safeDoc.challenge }, { $set: safeDoc }, { upsert: true });
111
+ }).then(() => markStored?.(timestamp)).catch((err) => {
112
+ this.logger.error(() => ({
113
+ err,
114
+ msg: "Failed to stream puzzle record to central DB"
115
+ }));
116
+ });
117
+ }
118
+ /**
119
+ * Stream a partial puzzle update by fetching the full record first, then upserting.
120
+ */
121
+ streamPuzzleUpdate(getFullRecord, markStored) {
122
+ getFullRecord().then((record) => {
123
+ if (record) this.streamPuzzleRecord(record, markStored);
124
+ }).catch((err) => {
125
+ this.logger.error(() => ({
126
+ err,
127
+ msg: "Failed to fetch puzzle record for central DB streaming"
128
+ }));
129
+ });
130
+ }
131
+ /**
132
+ * Stream a session record to the central DB.
133
+ * Fire-and-forget: errors are logged, never thrown.
134
+ */
135
+ streamSessionRecord(record, markStored) {
136
+ const timestamp = this.getRecordTimestamp(record);
137
+ this.ensureConnected().then(() => {
138
+ const { _id, ...safeDoc } = record;
139
+ return this.db.tables.session.updateOne({ sessionId: safeDoc.sessionId }, { $set: safeDoc }, { upsert: true });
140
+ }).then(() => markStored?.(timestamp)).catch((err) => {
141
+ this.logger.error(() => ({
142
+ err,
143
+ msg: "Failed to stream session record to central DB"
144
+ }));
145
+ });
146
+ }
147
+ };
148
+ //#endregion
171
149
  exports.CentralDbStreamer = CentralDbStreamer;
@@ -1,63 +1,47 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const common = require("@prosopo/common");
4
- const typesDatabase = require("@prosopo/types-database");
5
- require("../base/index.cjs");
6
- const mongo = require("../base/mongo.cjs");
7
- const CLIENT_TABLES = [
8
- {
9
- collectionName: typesDatabase.TableNames.accounts,
10
- modelName: "Account",
11
- schema: typesDatabase.AccountSchema
12
- }
13
- ];
14
- class ClientDatabase extends mongo.MongoDatabase {
15
- constructor(url, dbname, authSource, logger) {
16
- super(url, dbname, authSource, logger);
17
- this.tables = {};
18
- }
19
- async connect() {
20
- await super.connect();
21
- CLIENT_TABLES.map(({ collectionName, modelName, schema }) => {
22
- if (this.connection) {
23
- this.tables[collectionName] = this.connection.model(modelName, schema);
24
- }
25
- });
26
- }
27
- getTables() {
28
- if (!this.tables) {
29
- throw new common.ProsopoDBError("DATABASE.TABLES_UNDEFINED", {
30
- context: { failedFuncName: this.getTables.name },
31
- logger: this.logger
32
- });
33
- }
34
- return this.tables;
35
- }
36
- async getUpdatedClients(updatedAtTimestamp) {
37
- await this.connect();
38
- const newClientRecords = await this.tables.accounts.find(
39
- {
40
- $or: [
41
- { "sites.updatedAt": { $gt: updatedAtTimestamp } },
42
- { "sites.updatedAt": { $exists: false } }
43
- ],
44
- "users.status": "active"
45
- },
46
- { "sites.siteKey": 1, "sites.settings": 1, "sites.tier": 1 }
47
- ).lean().then(
48
- (records) => records.map(
49
- (record) => ({
50
- account: record.sites.siteKey,
51
- // Rename "sites.siteKey" to "account"
52
- settings: record.sites.settings,
53
- // Rename "sites.settings" to "settings"
54
- tier: record.tier
55
- // Keep "tier" as is
56
- })
57
- )
58
- );
59
- await this.close();
60
- return newClientRecords;
61
- }
62
- }
1
+ const require_mongo = require("../base/mongo.cjs");
2
+ let _prosopo_common = require("@prosopo/common");
3
+ let _prosopo_types_database = require("@prosopo/types-database");
4
+ //#region src/databases/client.ts
5
+ var CLIENT_TABLES = [{
6
+ collectionName: _prosopo_types_database.TableNames.accounts,
7
+ modelName: "Account",
8
+ schema: _prosopo_types_database.AccountSchema
9
+ }];
10
+ var ClientDatabase = class extends require_mongo.MongoDatabase {
11
+ constructor(url, dbname, authSource, logger) {
12
+ super(url, dbname, authSource, logger);
13
+ this.tables = {};
14
+ }
15
+ async connect() {
16
+ await super.connect();
17
+ CLIENT_TABLES.map(({ collectionName, modelName, schema }) => {
18
+ if (this.connection) this.tables[collectionName] = this.connection.model(modelName, schema);
19
+ });
20
+ }
21
+ getTables() {
22
+ if (!this.tables) throw new _prosopo_common.ProsopoDBError("DATABASE.TABLES_UNDEFINED", {
23
+ context: { failedFuncName: this.getTables.name },
24
+ logger: this.logger
25
+ });
26
+ return this.tables;
27
+ }
28
+ async getUpdatedClients(updatedAtTimestamp) {
29
+ await this.connect();
30
+ const newClientRecords = await this.tables.accounts.find({
31
+ $or: [{ "sites.updatedAt": { $gt: updatedAtTimestamp } }, { "sites.updatedAt": { $exists: false } }],
32
+ "users.status": "active"
33
+ }, {
34
+ "sites.siteKey": 1,
35
+ "sites.settings": 1,
36
+ "sites.tier": 1
37
+ }).lean().then((records) => records.map((record) => ({
38
+ account: record.sites.siteKey,
39
+ settings: record.sites.settings,
40
+ tier: record.tier
41
+ })));
42
+ await this.close();
43
+ return newClientRecords;
44
+ }
45
+ };
46
+ //#endregion
63
47
  exports.ClientDatabase = ClientDatabase;
@@ -1,21 +1,21 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const types = require("@prosopo/types");
4
- const mongo = require("../base/mongo.cjs");
5
- const mongoMemory = require("../base/mongoMemory.cjs");
6
- const captcha = require("./captcha.cjs");
7
- const client = require("./client.cjs");
8
- const provider = require("./provider.cjs");
9
- const centralDbStreamer = require("./centralDbStreamer.cjs");
10
- const Databases = {
11
- [types.DatabaseTypes.Values.mongo]: mongo.MongoDatabase,
12
- [types.DatabaseTypes.Values.provider]: provider.ProviderDatabase,
13
- [types.DatabaseTypes.Values.client]: client.ClientDatabase,
14
- [types.DatabaseTypes.Values.captcha]: captcha.CaptchaDatabase,
15
- [types.DatabaseTypes.Values.mongoMemory]: mongoMemory.MongoMemoryDatabase
1
+ const require_mongo = require("../base/mongo.cjs");
2
+ const require_mongoMemory = require("../base/mongoMemory.cjs");
3
+ const require_captcha = require("./captcha.cjs");
4
+ const require_client = require("./client.cjs");
5
+ const require_provider = require("./provider.cjs");
6
+ const require_centralDbStreamer = require("./centralDbStreamer.cjs");
7
+ let _prosopo_types = require("@prosopo/types");
8
+ //#region src/databases/index.ts
9
+ var Databases = {
10
+ [_prosopo_types.DatabaseTypes.Values.mongo]: require_mongo.MongoDatabase,
11
+ [_prosopo_types.DatabaseTypes.Values.provider]: require_provider.ProviderDatabase,
12
+ [_prosopo_types.DatabaseTypes.Values.client]: require_client.ClientDatabase,
13
+ [_prosopo_types.DatabaseTypes.Values.captcha]: require_captcha.CaptchaDatabase,
14
+ [_prosopo_types.DatabaseTypes.Values.mongoMemory]: require_mongoMemory.MongoMemoryDatabase
16
15
  };
17
- exports.CaptchaDatabase = captcha.CaptchaDatabase;
18
- exports.ClientDatabase = client.ClientDatabase;
19
- exports.ProviderDatabase = provider.ProviderDatabase;
20
- exports.CentralDbStreamer = centralDbStreamer.CentralDbStreamer;
16
+ //#endregion
17
+ exports.CaptchaDatabase = require_captcha.CaptchaDatabase;
18
+ exports.CentralDbStreamer = require_centralDbStreamer.CentralDbStreamer;
19
+ exports.ClientDatabase = require_client.ClientDatabase;
21
20
  exports.Databases = Databases;
21
+ exports.ProviderDatabase = require_provider.ProviderDatabase;