@prosopo/env 3.6.19 → 3.6.20
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.
- package/.turbo/turbo-build$colon$cjs.log +11 -9
- package/.turbo/turbo-build$colon$tsc.log +20 -20
- package/.turbo/turbo-build.log +13 -10
- package/CHANGELOG.md +15 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -0
- package/dist/cjs/env.cjs +151 -203
- package/dist/cjs/index.cjs +5 -6
- package/dist/cjs/provider.cjs +35 -39
- package/dist/env.js +146 -199
- package/dist/index.js +2 -5
- package/dist/provider.js +32 -37
- package/dist/tests/env.maintenance.unit.test.js +38 -26
- package/dist/tests/env.maintenance.unit.test.js.map +1 -1
- package/package.json +12 -12
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/env@3.6.
|
|
2
|
+
> @prosopo/env@3.6.20 build:cjs
|
|
3
3
|
> NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV
|
|
4
4
|
|
|
5
5
|
ViteCommonJSConfig: .
|
|
@@ -41,13 +41,15 @@ ViteCommonJSConfig: .
|
|
|
41
41
|
'@prosopo/keyring'
|
|
42
42
|
]
|
|
43
43
|
}
|
|
44
|
-
[
|
|
44
|
+
[33mThe plugin "vite-tsconfig-paths" is detected. Vite now supports tsconfig paths resolution natively via the [1mresolve.tsconfigPaths[22m option. You can remove the plugin and set [1mresolve.tsconfigPaths: true[22m in your Vite config instead.[39m
|
|
45
|
+
[36mvite v8.1.5 [32mbuilding ssr environment for production...[36m[39m
|
|
45
46
|
Bundle build started
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
[32m✓[39m 3 modules transformed.
|
|
47
|
+
[2K
|
|
48
|
+
✓ 4 modules transformed.
|
|
49
49
|
rendering chunks...
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
computing gzip size...
|
|
51
|
+
dist/cjs/index.cjs 0.34 kB │ gzip: 0.18 kB
|
|
52
|
+
dist/cjs/provider.cjs 1.27 kB │ gzip: 0.56 kB
|
|
53
|
+
dist/cjs/env.cjs 5.73 kB │ gzip: 1.79 kB
|
|
54
|
+
|
|
55
|
+
[32m✓ built in 38ms[39m
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/env@3.6.
|
|
2
|
+
> @prosopo/env@3.6.20 build:tsc
|
|
3
3
|
> tsc --build --verbose
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
8:59:53 PM - Projects in this build:
|
|
6
6
|
* ../../dev/config/tsconfig.json
|
|
7
7
|
* ../locale/tsconfig.json
|
|
8
8
|
* ../util/tsconfig.json
|
|
@@ -21,39 +21,39 @@
|
|
|
21
21
|
* ../types-env/tsconfig.json
|
|
22
22
|
* tsconfig.json
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
8:59:54 PM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/webpack/webpack.config.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
8:59:54 PM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
8:59:54 PM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
8:59:54 PM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/index.ts' is older than output '../logger/tsconfig.tsbuildinfo'
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
8:59:54 PM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/tsconfig.tsbuildinfo'
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
8:59:54 PM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/provider/api.ts' is older than output '../types/tsconfig.tsbuildinfo'
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
8:59:54 PM - Project '../common/tsconfig.json' is up to date because newest input '../common/src/tests/utils/batches.unit.test.ts' is older than output '../common/tsconfig.tsbuildinfo'
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
8:59:54 PM - Project '../ipinfo/tsconfig.json' is up to date because newest input '../ipinfo/src/IpInfoService.ts' is older than output '../ipinfo/tsconfig.tsbuildinfo'
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
8:59:54 PM - Project '../api-route/tsconfig.json' is up to date because newest input '../api-route/src/apiRoutes.ts' is older than output '../api-route/tsconfig.tsbuildinfo'
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
8:59:54 PM - Project '../redis-client/tsconfig.json' is up to date because newest input '../redis-client/src/index.ts' is older than output '../redis-client/tsconfig.tsbuildinfo'
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
8:59:54 PM - Project '../api/tsconfig.json' is up to date because newest input '../api/src/index.ts' is older than output '../api/tsconfig.tsbuildinfo'
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
8:59:54 PM - Project '../user-access-policy/tsconfig.json' is up to date because newest input '../user-access-policy/src/ruleRecord.ts' is older than output '../user-access-policy/tsconfig.tsbuildinfo'
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
8:59:54 PM - Project '../types-database/tsconfig.json' is up to date because newest input '../types-database/src/types/bannedDomain.ts' is older than output '../types-database/tsconfig.tsbuildinfo'
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
8:59:54 PM - Project '../database/tsconfig.json' is up to date because newest input '../database/src/tests/mongoGlobalSetup.ts' is older than output '../database/tsconfig.tsbuildinfo'
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
8:59:54 PM - Project '../keyring/tsconfig.json' is up to date because newest input '../keyring/src/keyring/keyring.ts' is older than output '../keyring/tsconfig.tsbuildinfo'
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
8:59:54 PM - Project '../types-env/tsconfig.json' is up to date because newest input '../types-env/src/index.ts' is older than output '../types-env/tsconfig.tsbuildinfo'
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
8:59:54 PM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
8:59:54 PM - Building project '/home/runner/work/captcha/captcha/packages/env/tsconfig.json'...
|
|
59
59
|
|
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/env@3.6.
|
|
2
|
+
> @prosopo/env@3.6.20 build
|
|
3
3
|
> npm run build:cross-env -- --mode ${NODE_ENV:-development}
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @prosopo/env@3.6.
|
|
6
|
+
> @prosopo/env@3.6.20 build:cross-env
|
|
7
7
|
> vite build --config vite.esm.config.ts --mode production
|
|
8
8
|
|
|
9
9
|
ViteEsmConfig: .
|
|
@@ -45,13 +45,16 @@ ViteEsmConfig: .
|
|
|
45
45
|
'@prosopo/keyring'
|
|
46
46
|
]
|
|
47
47
|
}
|
|
48
|
-
[
|
|
48
|
+
[33mThe plugin "vite-tsconfig-paths" is detected. Vite now supports tsconfig paths resolution natively via the [1mresolve.tsconfigPaths[22m option. You can remove the plugin and set [1mresolve.tsconfigPaths: true[22m in your Vite config instead.[39m
|
|
49
|
+
[36mvite v8.1.5 [32mbuilding ssr environment for production...[36m[39m
|
|
49
50
|
Bundle build started
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
[32m✓[39m 3 modules transformed.
|
|
51
|
+
[2K
|
|
52
|
+
✓ 4 modules transformed.
|
|
53
53
|
rendering chunks...
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
computing gzip size...
|
|
55
|
+
dist/_virtual/_rolldown/runtime.js 0.04 kB │ gzip: 0.06 kB
|
|
56
|
+
dist/index.js 0.21 kB │ gzip: 0.13 kB
|
|
57
|
+
dist/provider.js 1.17 kB │ gzip: 0.53 kB
|
|
58
|
+
dist/env.js 5.44 kB │ gzip: 1.75 kB
|
|
59
|
+
|
|
60
|
+
[32m✓ built in 54ms[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @prosopo/env
|
|
2
2
|
|
|
3
|
+
## 3.6.20
|
|
4
|
+
### Patch Changes
|
|
5
|
+
|
|
6
|
+
- e14fce6: chore(deps): bump vite to 6.4.3 and mongoose to 8.24.1, and adjust types for the mongoose 8.24 Document/ObjectId changes
|
|
7
|
+
- Updated dependencies [103318c]
|
|
8
|
+
- Updated dependencies [270a8d8]
|
|
9
|
+
- Updated dependencies [e14fce6]
|
|
10
|
+
- @prosopo/types@4.10.0
|
|
11
|
+
- @prosopo/ipinfo@0.3.0
|
|
12
|
+
- @prosopo/common@3.1.48
|
|
13
|
+
- @prosopo/database@3.15.20
|
|
14
|
+
- @prosopo/keyring@2.9.61
|
|
15
|
+
- @prosopo/types-env@2.10.17
|
|
16
|
+
- @prosopo/logger@2.0.4
|
|
17
|
+
|
|
3
18
|
## 3.6.19
|
|
4
19
|
### Patch Changes
|
|
5
20
|
|
package/dist/cjs/env.cjs
CHANGED
|
@@ -1,205 +1,153 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
},
|
|
153
|
-
redis: {
|
|
154
|
-
url: this.config.redisConnection.url,
|
|
155
|
-
password: this.config.redisConnection.password
|
|
156
|
-
},
|
|
157
|
-
logger: this.logger
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
async importDatabase() {
|
|
161
|
-
try {
|
|
162
|
-
const db = this.buildDatabase();
|
|
163
|
-
if (db) {
|
|
164
|
-
this.db = db;
|
|
165
|
-
await this.db.connect();
|
|
166
|
-
}
|
|
167
|
-
} catch (error) {
|
|
168
|
-
throw new common.ProsopoEnvError("DATABASE.DATABASE_IMPORT_FAILED", {
|
|
169
|
-
context: {
|
|
170
|
-
error,
|
|
171
|
-
environment: this.config.database ? this.config.database[this.defaultEnvironment] ? this.config.database[this.defaultEnvironment]?.type : void 0 : void 0
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
// Create the DB handle and kick off the connection WITHOUT awaiting it, so
|
|
177
|
-
// startup is never gated on the DB socket. Used in maintenance mode: the
|
|
178
|
-
// captcha request path never touches the DB (it short-circuits), but the
|
|
179
|
-
// admin endpoints do, so the handle must exist. A failed connection is
|
|
180
|
-
// logged rather than thrown — admin queries will surface the error (or
|
|
181
|
-
// succeed once the socket recovers) when they actually run.
|
|
182
|
-
connectDatabaseInBackground() {
|
|
183
|
-
try {
|
|
184
|
-
const db = this.buildDatabase();
|
|
185
|
-
if (!db) {
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
this.db = db;
|
|
189
|
-
db.connect().catch((error) => {
|
|
190
|
-
this.logger.warn(() => ({
|
|
191
|
-
msg: "Background DB connection failed in maintenance mode; admin endpoints will retry on demand",
|
|
192
|
-
data: { error }
|
|
193
|
-
}));
|
|
194
|
-
});
|
|
195
|
-
} catch (error) {
|
|
196
|
-
this.logger.warn(() => ({
|
|
197
|
-
msg: "Failed to create DB handle in maintenance mode; admin endpoints will be unavailable until restart",
|
|
198
|
-
data: { error }
|
|
199
|
-
}));
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
const isMaintenanceMode = () => process.env.MAINTENANCE_MODE?.toLowerCase() === "true";
|
|
1
|
+
let _prosopo_common = require("@prosopo/common");
|
|
2
|
+
let _prosopo_database = require("@prosopo/database");
|
|
3
|
+
let _prosopo_ipinfo = require("@prosopo/ipinfo");
|
|
4
|
+
let _prosopo_keyring = require("@prosopo/keyring");
|
|
5
|
+
let _prosopo_logger = require("@prosopo/logger");
|
|
6
|
+
let _prosopo_util_crypto = require("@prosopo/util-crypto");
|
|
7
|
+
//#region src/env.ts
|
|
8
|
+
var Environment = class {
|
|
9
|
+
constructor(config, pair, authAccount) {
|
|
10
|
+
this.ready = false;
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.defaultEnvironment = this.config.defaultEnvironment;
|
|
13
|
+
this.pair = pair || (0, _prosopo_keyring.getPair)(config.account.secret);
|
|
14
|
+
this.authAccount = authAccount;
|
|
15
|
+
this.logger = (0, _prosopo_logger.getLogger)((0, _prosopo_logger.parseLogLevel)(this.config.logLevel), "ProsopoEnvironment");
|
|
16
|
+
this.keyring = new _prosopo_keyring.Keyring({ type: "sr25519" });
|
|
17
|
+
if (this.pair) this.keyring.addPair(this.pair);
|
|
18
|
+
this.envId = (0, _prosopo_util_crypto.randomAsHex)(32).slice(0, 32);
|
|
19
|
+
this.ipInfoService = new _prosopo_ipinfo.IpInfoService({
|
|
20
|
+
maxmindCityDbPath: this.config.maxmindCityDbPath ?? this.config.maxmindDbPath,
|
|
21
|
+
maxmindAsnDbPath: this.config.maxmindAsnDbPath,
|
|
22
|
+
ipapiUrl: this.config.ipApi?.baseUrl,
|
|
23
|
+
ipapiKey: this.config.ipApi?.apiKey,
|
|
24
|
+
logger: this.logger
|
|
25
|
+
});
|
|
26
|
+
this.logger.info(() => ({
|
|
27
|
+
msg: "Environment initialized",
|
|
28
|
+
data: {
|
|
29
|
+
envId: this.envId,
|
|
30
|
+
defaultEnvironment: this.defaultEnvironment,
|
|
31
|
+
logLevel: this.config.logLevel,
|
|
32
|
+
maxmindDbPath: this.config.maxmindDbPath || "not configured"
|
|
33
|
+
}
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
async getSigner() {
|
|
37
|
+
if (!this.pair) throw new _prosopo_common.ProsopoEnvError("CONTRACT.SIGNER_UNDEFINED", { context: { failedFuncName: this.getSigner.name } });
|
|
38
|
+
try {
|
|
39
|
+
this.pair = this.keyring.addPair(this.pair);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
throw new _prosopo_common.ProsopoEnvError("CONTRACT.SIGNER_UNDEFINED", { context: {
|
|
42
|
+
failedFuncName: this.getSigner.name,
|
|
43
|
+
error
|
|
44
|
+
} });
|
|
45
|
+
}
|
|
46
|
+
return this.pair;
|
|
47
|
+
}
|
|
48
|
+
getDb() {
|
|
49
|
+
if (this.db === void 0) throw new _prosopo_common.ProsopoEnvError(/* @__PURE__ */ new Error("db not setup! Please call isReady() first"));
|
|
50
|
+
return this.db;
|
|
51
|
+
}
|
|
52
|
+
getAssetsResolver() {
|
|
53
|
+
if (this.assetsResolver === void 0) throw new _prosopo_common.ProsopoEnvError(/* @__PURE__ */ new Error("assetsResolver not setup! Please call isReady() first"));
|
|
54
|
+
return this.assetsResolver;
|
|
55
|
+
}
|
|
56
|
+
getPair() {
|
|
57
|
+
if (this.pair === void 0) throw new _prosopo_common.ProsopoEnvError(/* @__PURE__ */ new Error("pair not setup! Please call isReady() first"));
|
|
58
|
+
return this.pair;
|
|
59
|
+
}
|
|
60
|
+
async isReady() {
|
|
61
|
+
if (this.ready) {
|
|
62
|
+
this.logger.debug(() => ({ msg: "Environment is already ready" }));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
if (this.pair && this.config.account.password && this.pair.isLocked) this.pair.unlock(this.config.account.password);
|
|
67
|
+
await this.getSigner();
|
|
68
|
+
const maintenanceMode = isMaintenanceMode();
|
|
69
|
+
if (maintenanceMode) {
|
|
70
|
+
this.logger.warn(() => ({ msg: "MAINTENANCE_MODE=true — connecting to DB in the background so admin endpoints stay available; captcha path short-circuits" }));
|
|
71
|
+
if (!this.db) this.connectDatabaseInBackground();
|
|
72
|
+
} else if (!this.db) await this.importDatabase();
|
|
73
|
+
else if (this.db && !this.db.connected) {
|
|
74
|
+
this.logger.warn(() => ({ msg: `Database connection is not ready (state: ${this.db?.connection?.readyState}), reconnecting...` }));
|
|
75
|
+
await this.db.connect();
|
|
76
|
+
this.logger.info(() => ({ msg: "Connected to db" }));
|
|
77
|
+
}
|
|
78
|
+
if (!maintenanceMode && this.db && !this.datasetId) try {
|
|
79
|
+
this.datasetId = await this.db.getMostRecentDatasetId();
|
|
80
|
+
if (this.datasetId) this.logger.info(() => ({
|
|
81
|
+
msg: "Default dataset ID set",
|
|
82
|
+
data: { datasetId: this.datasetId }
|
|
83
|
+
}));
|
|
84
|
+
else this.logger.warn(() => ({ msg: "No datasets found in database. Image captchas will not work until a dataset is uploaded." }));
|
|
85
|
+
} catch (err) {
|
|
86
|
+
this.logger.warn(() => ({
|
|
87
|
+
msg: "Failed to get most recent dataset ID",
|
|
88
|
+
data: { error: err }
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
await this.ipInfoService.initialize();
|
|
92
|
+
this.ready = true;
|
|
93
|
+
} catch (err) {
|
|
94
|
+
throw new _prosopo_common.ProsopoEnvError("GENERAL.ENVIRONMENT_NOT_READY", {
|
|
95
|
+
context: { error: err },
|
|
96
|
+
logger: this.logger
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
buildDatabase() {
|
|
101
|
+
if (!this.config.database) return;
|
|
102
|
+
const dbConfig = this.config.database[this.defaultEnvironment];
|
|
103
|
+
if (!dbConfig) return;
|
|
104
|
+
return new _prosopo_database.ProviderDatabase({
|
|
105
|
+
mongo: {
|
|
106
|
+
url: dbConfig.endpoint,
|
|
107
|
+
dbname: dbConfig.dbname,
|
|
108
|
+
authSource: dbConfig.authSource
|
|
109
|
+
},
|
|
110
|
+
redis: {
|
|
111
|
+
url: this.config.redisConnection.url,
|
|
112
|
+
password: this.config.redisConnection.password
|
|
113
|
+
},
|
|
114
|
+
logger: this.logger
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
async importDatabase() {
|
|
118
|
+
try {
|
|
119
|
+
const db = this.buildDatabase();
|
|
120
|
+
if (db) {
|
|
121
|
+
this.db = db;
|
|
122
|
+
await this.db.connect();
|
|
123
|
+
}
|
|
124
|
+
} catch (error) {
|
|
125
|
+
throw new _prosopo_common.ProsopoEnvError("DATABASE.DATABASE_IMPORT_FAILED", { context: {
|
|
126
|
+
error,
|
|
127
|
+
environment: this.config.database ? this.config.database[this.defaultEnvironment] ? this.config.database[this.defaultEnvironment]?.type : void 0 : void 0
|
|
128
|
+
} });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
connectDatabaseInBackground() {
|
|
132
|
+
try {
|
|
133
|
+
const db = this.buildDatabase();
|
|
134
|
+
if (!db) return;
|
|
135
|
+
this.db = db;
|
|
136
|
+
db.connect().catch((error) => {
|
|
137
|
+
this.logger.warn(() => ({
|
|
138
|
+
msg: "Background DB connection failed in maintenance mode; admin endpoints will retry on demand",
|
|
139
|
+
data: { error }
|
|
140
|
+
}));
|
|
141
|
+
});
|
|
142
|
+
} catch (error) {
|
|
143
|
+
this.logger.warn(() => ({
|
|
144
|
+
msg: "Failed to create DB handle in maintenance mode; admin endpoints will be unavailable until restart",
|
|
145
|
+
data: { error }
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
var isMaintenanceMode = () => process.env.MAINTENANCE_MODE?.toLowerCase() === "true";
|
|
151
|
+
//#endregion
|
|
204
152
|
exports.Environment = Environment;
|
|
205
153
|
exports.isMaintenanceMode = isMaintenanceMode;
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
exports.Environment =
|
|
6
|
-
exports.
|
|
7
|
-
exports.
|
|
2
|
+
const require_env = require("./env.cjs");
|
|
3
|
+
const require_provider = require("./provider.cjs");
|
|
4
|
+
exports.Environment = require_env.Environment;
|
|
5
|
+
exports.ProviderEnvironment = require_provider.ProviderEnvironment;
|
|
6
|
+
exports.isMaintenanceMode = require_env.isMaintenanceMode;
|
package/dist/cjs/provider.cjs
CHANGED
|
@@ -1,40 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}));
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
1
|
+
const require_env = require("./env.cjs");
|
|
2
|
+
let _prosopo_database = require("@prosopo/database");
|
|
3
|
+
let _prosopo_types = require("@prosopo/types");
|
|
4
|
+
//#region src/provider.ts
|
|
5
|
+
var ProviderEnvironment = class extends require_env.Environment {
|
|
6
|
+
cleanup() {
|
|
7
|
+
if (!(this.db?.connected ?? false) || require_env.isMaintenanceMode()) {
|
|
8
|
+
this.logger.warn(() => ({ msg: "Skipping startup cleanup — DB not connected (maintenance mode or boot-time DB failure)" }));
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
this.db?.cleanupScheduledTaskStatus(_prosopo_types.ScheduledTaskStatus.Running).catch((err) => {
|
|
12
|
+
this.logger.error(() => ({
|
|
13
|
+
msg: "Failed to cleanup running scheduled tasks",
|
|
14
|
+
err,
|
|
15
|
+
data: { failedFuncName: this.cleanup.name }
|
|
16
|
+
}));
|
|
17
|
+
});
|
|
18
|
+
try {
|
|
19
|
+
const redisConnection = this.getDb().getRedisConnection();
|
|
20
|
+
new _prosopo_database.RedisWriteQueue(redisConnection, this.logger).clearAllSessionRecords().catch((err) => {
|
|
21
|
+
this.logger.error(() => ({
|
|
22
|
+
msg: "Failed to clear Redis session records at startup",
|
|
23
|
+
err,
|
|
24
|
+
data: { failedFuncName: this.cleanup.name }
|
|
25
|
+
}));
|
|
26
|
+
});
|
|
27
|
+
} catch (err) {
|
|
28
|
+
this.logger.warn(() => ({
|
|
29
|
+
msg: "Skipped Redis session cleanup — no Redis connection",
|
|
30
|
+
err
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
//#endregion
|
|
40
36
|
exports.ProviderEnvironment = ProviderEnvironment;
|
package/dist/env.js
CHANGED
|
@@ -1,205 +1,152 @@
|
|
|
1
1
|
import { ProsopoEnvError } from "@prosopo/common";
|
|
2
2
|
import { ProviderDatabase } from "@prosopo/database";
|
|
3
3
|
import { IpInfoService } from "@prosopo/ipinfo";
|
|
4
|
-
import {
|
|
4
|
+
import { Keyring, getPair } from "@prosopo/keyring";
|
|
5
5
|
import { getLogger, parseLogLevel } from "@prosopo/logger";
|
|
6
6
|
import { randomAsHex } from "@prosopo/util-crypto";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
authSource: dbConfig.authSource
|
|
150
|
-
},
|
|
151
|
-
redis: {
|
|
152
|
-
url: this.config.redisConnection.url,
|
|
153
|
-
password: this.config.redisConnection.password
|
|
154
|
-
},
|
|
155
|
-
logger: this.logger
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
async importDatabase() {
|
|
159
|
-
try {
|
|
160
|
-
const db = this.buildDatabase();
|
|
161
|
-
if (db) {
|
|
162
|
-
this.db = db;
|
|
163
|
-
await this.db.connect();
|
|
164
|
-
}
|
|
165
|
-
} catch (error) {
|
|
166
|
-
throw new ProsopoEnvError("DATABASE.DATABASE_IMPORT_FAILED", {
|
|
167
|
-
context: {
|
|
168
|
-
error,
|
|
169
|
-
environment: this.config.database ? this.config.database[this.defaultEnvironment] ? this.config.database[this.defaultEnvironment]?.type : void 0 : void 0
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
// Create the DB handle and kick off the connection WITHOUT awaiting it, so
|
|
175
|
-
// startup is never gated on the DB socket. Used in maintenance mode: the
|
|
176
|
-
// captcha request path never touches the DB (it short-circuits), but the
|
|
177
|
-
// admin endpoints do, so the handle must exist. A failed connection is
|
|
178
|
-
// logged rather than thrown — admin queries will surface the error (or
|
|
179
|
-
// succeed once the socket recovers) when they actually run.
|
|
180
|
-
connectDatabaseInBackground() {
|
|
181
|
-
try {
|
|
182
|
-
const db = this.buildDatabase();
|
|
183
|
-
if (!db) {
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
this.db = db;
|
|
187
|
-
db.connect().catch((error) => {
|
|
188
|
-
this.logger.warn(() => ({
|
|
189
|
-
msg: "Background DB connection failed in maintenance mode; admin endpoints will retry on demand",
|
|
190
|
-
data: { error }
|
|
191
|
-
}));
|
|
192
|
-
});
|
|
193
|
-
} catch (error) {
|
|
194
|
-
this.logger.warn(() => ({
|
|
195
|
-
msg: "Failed to create DB handle in maintenance mode; admin endpoints will be unavailable until restart",
|
|
196
|
-
data: { error }
|
|
197
|
-
}));
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
const isMaintenanceMode = () => process.env.MAINTENANCE_MODE?.toLowerCase() === "true";
|
|
202
|
-
export {
|
|
203
|
-
Environment,
|
|
204
|
-
isMaintenanceMode
|
|
7
|
+
//#region src/env.ts
|
|
8
|
+
var Environment = class {
|
|
9
|
+
constructor(config, pair, authAccount) {
|
|
10
|
+
this.ready = false;
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.defaultEnvironment = this.config.defaultEnvironment;
|
|
13
|
+
this.pair = pair || getPair(config.account.secret);
|
|
14
|
+
this.authAccount = authAccount;
|
|
15
|
+
this.logger = getLogger(parseLogLevel(this.config.logLevel), "ProsopoEnvironment");
|
|
16
|
+
this.keyring = new Keyring({ type: "sr25519" });
|
|
17
|
+
if (this.pair) this.keyring.addPair(this.pair);
|
|
18
|
+
this.envId = randomAsHex(32).slice(0, 32);
|
|
19
|
+
this.ipInfoService = new IpInfoService({
|
|
20
|
+
maxmindCityDbPath: this.config.maxmindCityDbPath ?? this.config.maxmindDbPath,
|
|
21
|
+
maxmindAsnDbPath: this.config.maxmindAsnDbPath,
|
|
22
|
+
ipapiUrl: this.config.ipApi?.baseUrl,
|
|
23
|
+
ipapiKey: this.config.ipApi?.apiKey,
|
|
24
|
+
logger: this.logger
|
|
25
|
+
});
|
|
26
|
+
this.logger.info(() => ({
|
|
27
|
+
msg: "Environment initialized",
|
|
28
|
+
data: {
|
|
29
|
+
envId: this.envId,
|
|
30
|
+
defaultEnvironment: this.defaultEnvironment,
|
|
31
|
+
logLevel: this.config.logLevel,
|
|
32
|
+
maxmindDbPath: this.config.maxmindDbPath || "not configured"
|
|
33
|
+
}
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
async getSigner() {
|
|
37
|
+
if (!this.pair) throw new ProsopoEnvError("CONTRACT.SIGNER_UNDEFINED", { context: { failedFuncName: this.getSigner.name } });
|
|
38
|
+
try {
|
|
39
|
+
this.pair = this.keyring.addPair(this.pair);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
throw new ProsopoEnvError("CONTRACT.SIGNER_UNDEFINED", { context: {
|
|
42
|
+
failedFuncName: this.getSigner.name,
|
|
43
|
+
error
|
|
44
|
+
} });
|
|
45
|
+
}
|
|
46
|
+
return this.pair;
|
|
47
|
+
}
|
|
48
|
+
getDb() {
|
|
49
|
+
if (this.db === void 0) throw new ProsopoEnvError(/* @__PURE__ */ new Error("db not setup! Please call isReady() first"));
|
|
50
|
+
return this.db;
|
|
51
|
+
}
|
|
52
|
+
getAssetsResolver() {
|
|
53
|
+
if (this.assetsResolver === void 0) throw new ProsopoEnvError(/* @__PURE__ */ new Error("assetsResolver not setup! Please call isReady() first"));
|
|
54
|
+
return this.assetsResolver;
|
|
55
|
+
}
|
|
56
|
+
getPair() {
|
|
57
|
+
if (this.pair === void 0) throw new ProsopoEnvError(/* @__PURE__ */ new Error("pair not setup! Please call isReady() first"));
|
|
58
|
+
return this.pair;
|
|
59
|
+
}
|
|
60
|
+
async isReady() {
|
|
61
|
+
if (this.ready) {
|
|
62
|
+
this.logger.debug(() => ({ msg: "Environment is already ready" }));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
if (this.pair && this.config.account.password && this.pair.isLocked) this.pair.unlock(this.config.account.password);
|
|
67
|
+
await this.getSigner();
|
|
68
|
+
const maintenanceMode = isMaintenanceMode();
|
|
69
|
+
if (maintenanceMode) {
|
|
70
|
+
this.logger.warn(() => ({ msg: "MAINTENANCE_MODE=true — connecting to DB in the background so admin endpoints stay available; captcha path short-circuits" }));
|
|
71
|
+
if (!this.db) this.connectDatabaseInBackground();
|
|
72
|
+
} else if (!this.db) await this.importDatabase();
|
|
73
|
+
else if (this.db && !this.db.connected) {
|
|
74
|
+
this.logger.warn(() => ({ msg: `Database connection is not ready (state: ${this.db?.connection?.readyState}), reconnecting...` }));
|
|
75
|
+
await this.db.connect();
|
|
76
|
+
this.logger.info(() => ({ msg: "Connected to db" }));
|
|
77
|
+
}
|
|
78
|
+
if (!maintenanceMode && this.db && !this.datasetId) try {
|
|
79
|
+
this.datasetId = await this.db.getMostRecentDatasetId();
|
|
80
|
+
if (this.datasetId) this.logger.info(() => ({
|
|
81
|
+
msg: "Default dataset ID set",
|
|
82
|
+
data: { datasetId: this.datasetId }
|
|
83
|
+
}));
|
|
84
|
+
else this.logger.warn(() => ({ msg: "No datasets found in database. Image captchas will not work until a dataset is uploaded." }));
|
|
85
|
+
} catch (err) {
|
|
86
|
+
this.logger.warn(() => ({
|
|
87
|
+
msg: "Failed to get most recent dataset ID",
|
|
88
|
+
data: { error: err }
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
await this.ipInfoService.initialize();
|
|
92
|
+
this.ready = true;
|
|
93
|
+
} catch (err) {
|
|
94
|
+
throw new ProsopoEnvError("GENERAL.ENVIRONMENT_NOT_READY", {
|
|
95
|
+
context: { error: err },
|
|
96
|
+
logger: this.logger
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
buildDatabase() {
|
|
101
|
+
if (!this.config.database) return;
|
|
102
|
+
const dbConfig = this.config.database[this.defaultEnvironment];
|
|
103
|
+
if (!dbConfig) return;
|
|
104
|
+
return new ProviderDatabase({
|
|
105
|
+
mongo: {
|
|
106
|
+
url: dbConfig.endpoint,
|
|
107
|
+
dbname: dbConfig.dbname,
|
|
108
|
+
authSource: dbConfig.authSource
|
|
109
|
+
},
|
|
110
|
+
redis: {
|
|
111
|
+
url: this.config.redisConnection.url,
|
|
112
|
+
password: this.config.redisConnection.password
|
|
113
|
+
},
|
|
114
|
+
logger: this.logger
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
async importDatabase() {
|
|
118
|
+
try {
|
|
119
|
+
const db = this.buildDatabase();
|
|
120
|
+
if (db) {
|
|
121
|
+
this.db = db;
|
|
122
|
+
await this.db.connect();
|
|
123
|
+
}
|
|
124
|
+
} catch (error) {
|
|
125
|
+
throw new ProsopoEnvError("DATABASE.DATABASE_IMPORT_FAILED", { context: {
|
|
126
|
+
error,
|
|
127
|
+
environment: this.config.database ? this.config.database[this.defaultEnvironment] ? this.config.database[this.defaultEnvironment]?.type : void 0 : void 0
|
|
128
|
+
} });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
connectDatabaseInBackground() {
|
|
132
|
+
try {
|
|
133
|
+
const db = this.buildDatabase();
|
|
134
|
+
if (!db) return;
|
|
135
|
+
this.db = db;
|
|
136
|
+
db.connect().catch((error) => {
|
|
137
|
+
this.logger.warn(() => ({
|
|
138
|
+
msg: "Background DB connection failed in maintenance mode; admin endpoints will retry on demand",
|
|
139
|
+
data: { error }
|
|
140
|
+
}));
|
|
141
|
+
});
|
|
142
|
+
} catch (error) {
|
|
143
|
+
this.logger.warn(() => ({
|
|
144
|
+
msg: "Failed to create DB handle in maintenance mode; admin endpoints will be unavailable until restart",
|
|
145
|
+
data: { error }
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
205
149
|
};
|
|
150
|
+
var isMaintenanceMode = () => process.env.MAINTENANCE_MODE?.toLowerCase() === "true";
|
|
151
|
+
//#endregion
|
|
152
|
+
export { Environment, isMaintenanceMode };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
+
import "./_virtual/_rolldown/runtime.js";
|
|
1
2
|
import { Environment, isMaintenanceMode } from "./env.js";
|
|
2
3
|
import { ProviderEnvironment } from "./provider.js";
|
|
3
|
-
export {
|
|
4
|
-
Environment,
|
|
5
|
-
ProviderEnvironment,
|
|
6
|
-
isMaintenanceMode
|
|
7
|
-
};
|
|
4
|
+
export { Environment, ProviderEnvironment, isMaintenanceMode };
|
package/dist/provider.js
CHANGED
|
@@ -1,40 +1,35 @@
|
|
|
1
|
+
import { Environment, isMaintenanceMode } from "./env.js";
|
|
1
2
|
import { RedisWriteQueue } from "@prosopo/database";
|
|
2
3
|
import { ScheduledTaskStatus } from "@prosopo/types";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
msg: "Skipped Redis session cleanup — no Redis connection",
|
|
33
|
-
err
|
|
34
|
-
}));
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
export {
|
|
39
|
-
ProviderEnvironment
|
|
4
|
+
//#region src/provider.ts
|
|
5
|
+
var ProviderEnvironment = class extends Environment {
|
|
6
|
+
cleanup() {
|
|
7
|
+
if (!(this.db?.connected ?? false) || isMaintenanceMode()) {
|
|
8
|
+
this.logger.warn(() => ({ msg: "Skipping startup cleanup — DB not connected (maintenance mode or boot-time DB failure)" }));
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
this.db?.cleanupScheduledTaskStatus(ScheduledTaskStatus.Running).catch((err) => {
|
|
12
|
+
this.logger.error(() => ({
|
|
13
|
+
msg: "Failed to cleanup running scheduled tasks",
|
|
14
|
+
err,
|
|
15
|
+
data: { failedFuncName: this.cleanup.name }
|
|
16
|
+
}));
|
|
17
|
+
});
|
|
18
|
+
try {
|
|
19
|
+
new RedisWriteQueue(this.getDb().getRedisConnection(), this.logger).clearAllSessionRecords().catch((err) => {
|
|
20
|
+
this.logger.error(() => ({
|
|
21
|
+
msg: "Failed to clear Redis session records at startup",
|
|
22
|
+
err,
|
|
23
|
+
data: { failedFuncName: this.cleanup.name }
|
|
24
|
+
}));
|
|
25
|
+
});
|
|
26
|
+
} catch (err) {
|
|
27
|
+
this.logger.warn(() => ({
|
|
28
|
+
msg: "Skipped Redis session cleanup — no Redis connection",
|
|
29
|
+
err
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
40
33
|
};
|
|
34
|
+
//#endregion
|
|
35
|
+
export { ProviderEnvironment };
|
|
@@ -7,14 +7,18 @@ vi.mock("@prosopo/database", () => ({
|
|
|
7
7
|
ProviderDatabase: mockProviderDatabase,
|
|
8
8
|
}));
|
|
9
9
|
vi.mock("@prosopo/ipinfo", () => ({
|
|
10
|
-
IpInfoService: vi.fn().mockImplementation(()
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
IpInfoService: vi.fn().mockImplementation(function () {
|
|
11
|
+
return {
|
|
12
|
+
initialize: mockIpInfoInit,
|
|
13
|
+
};
|
|
14
|
+
}),
|
|
13
15
|
}));
|
|
14
16
|
vi.mock("@prosopo/keyring", () => ({
|
|
15
|
-
Keyring: vi.fn().mockImplementation(()
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
Keyring: vi.fn().mockImplementation(function () {
|
|
18
|
+
return {
|
|
19
|
+
addPair: vi.fn((p) => p),
|
|
20
|
+
};
|
|
21
|
+
}),
|
|
18
22
|
getPair: vi.fn(() => ({
|
|
19
23
|
address: "addr",
|
|
20
24
|
isLocked: false,
|
|
@@ -63,11 +67,13 @@ describe("Environment.isReady — maintenance mode startup tolerance", () => {
|
|
|
63
67
|
process.env.MAINTENANCE_MODE = undefined;
|
|
64
68
|
});
|
|
65
69
|
it("throws when DB connect fails and maintenance mode is off", async () => {
|
|
66
|
-
mockProviderDatabase.mockImplementation(()
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
mockProviderDatabase.mockImplementation(function () {
|
|
71
|
+
return {
|
|
72
|
+
connect: vi.fn().mockRejectedValue(new Error("ECONNREFUSED")),
|
|
73
|
+
connected: false,
|
|
74
|
+
connection: { readyState: 0 },
|
|
75
|
+
};
|
|
76
|
+
});
|
|
71
77
|
const env = buildEnv();
|
|
72
78
|
await expect(env.isReady()).rejects.toMatchObject({
|
|
73
79
|
translationKey: "GENERAL.ENVIRONMENT_NOT_READY",
|
|
@@ -76,11 +82,13 @@ describe("Environment.isReady — maintenance mode startup tolerance", () => {
|
|
|
76
82
|
it("creates the DB handle and connects in the background when maintenance mode is on", async () => {
|
|
77
83
|
process.env.MAINTENANCE_MODE = "true";
|
|
78
84
|
const connect = vi.fn().mockResolvedValue(undefined);
|
|
79
|
-
mockProviderDatabase.mockImplementation(()
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
mockProviderDatabase.mockImplementation(function () {
|
|
86
|
+
return {
|
|
87
|
+
connect,
|
|
88
|
+
connected: false,
|
|
89
|
+
connection: { readyState: 0 },
|
|
90
|
+
};
|
|
91
|
+
});
|
|
84
92
|
const env = buildEnv();
|
|
85
93
|
await env.isReady();
|
|
86
94
|
expect(env.ready).toBe(true);
|
|
@@ -92,11 +100,13 @@ describe("Environment.isReady — maintenance mode startup tolerance", () => {
|
|
|
92
100
|
it("does not gate boot when the background DB connect fails in maintenance mode", async () => {
|
|
93
101
|
process.env.MAINTENANCE_MODE = "true";
|
|
94
102
|
const connect = vi.fn().mockRejectedValue(new Error("ECONNREFUSED"));
|
|
95
|
-
mockProviderDatabase.mockImplementation(()
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
103
|
+
mockProviderDatabase.mockImplementation(function () {
|
|
104
|
+
return {
|
|
105
|
+
connect,
|
|
106
|
+
connected: false,
|
|
107
|
+
connection: { readyState: 0 },
|
|
108
|
+
};
|
|
109
|
+
});
|
|
100
110
|
const env = buildEnv();
|
|
101
111
|
await expect(env.isReady()).resolves.toBeUndefined();
|
|
102
112
|
expect(env.ready).toBe(true);
|
|
@@ -107,11 +117,13 @@ describe("Environment.isReady — maintenance mode startup tolerance", () => {
|
|
|
107
117
|
});
|
|
108
118
|
it("still completes the normal connect path when Mongo is up", async () => {
|
|
109
119
|
const connect = vi.fn().mockResolvedValue(undefined);
|
|
110
|
-
mockProviderDatabase.mockImplementation(()
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
120
|
+
mockProviderDatabase.mockImplementation(function () {
|
|
121
|
+
return {
|
|
122
|
+
connect,
|
|
123
|
+
connected: true,
|
|
124
|
+
connection: { readyState: 1 },
|
|
125
|
+
};
|
|
126
|
+
});
|
|
115
127
|
const env = buildEnv();
|
|
116
128
|
await env.isReady();
|
|
117
129
|
expect(env.ready).toBe(true);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.maintenance.unit.test.js","sourceRoot":"","sources":["../../src/tests/env.maintenance.unit.test.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEzE,MAAM,EAAE,oBAAoB,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAClE,oBAAoB,EAAE,EAAE,CAAC,EAAE,EAAE;IAC7B,cAAc,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;CACpD,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,CAAC;IACnC,gBAAgB,EAAE,oBAAoB;CACtC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"env.maintenance.unit.test.js","sourceRoot":"","sources":["../../src/tests/env.maintenance.unit.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prosopo/env",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.20",
|
|
4
4
|
"description": "Path env prosopo environment",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -26,27 +26,27 @@
|
|
|
26
26
|
"typecheck": "tsc --project tsconfig.types.json"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@prosopo/ipinfo": "0.
|
|
30
|
-
"@prosopo/common": "3.1.
|
|
31
|
-
"@prosopo/logger": "2.0.
|
|
32
|
-
"@prosopo/database": "3.15.
|
|
33
|
-
"@prosopo/keyring": "2.9.
|
|
34
|
-
"@prosopo/types": "4.
|
|
35
|
-
"@prosopo/types-env": "2.10.
|
|
29
|
+
"@prosopo/ipinfo": "0.3.0",
|
|
30
|
+
"@prosopo/common": "3.1.48",
|
|
31
|
+
"@prosopo/logger": "2.0.4",
|
|
32
|
+
"@prosopo/database": "3.15.20",
|
|
33
|
+
"@prosopo/keyring": "2.9.61",
|
|
34
|
+
"@prosopo/types": "4.10.0",
|
|
35
|
+
"@prosopo/types-env": "2.10.17",
|
|
36
36
|
"@prosopo/util-crypto": "13.5.30"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@prosopo/config": "3.3.
|
|
39
|
+
"@prosopo/config": "3.3.5",
|
|
40
40
|
"@types/node": "22.10.2",
|
|
41
|
-
"@vitest/coverage-v8": "
|
|
41
|
+
"@vitest/coverage-v8": "4.1.10",
|
|
42
42
|
"concurrently": "9.0.1",
|
|
43
43
|
"del-cli": "6.0.0",
|
|
44
44
|
"npm-run-all": "4.1.5",
|
|
45
45
|
"tslib": "2.7.0",
|
|
46
46
|
"tsx": "4.20.3",
|
|
47
47
|
"typescript": "5.6.2",
|
|
48
|
-
"vite": "
|
|
49
|
-
"vitest": "
|
|
48
|
+
"vite": "8.1.5",
|
|
49
|
+
"vitest": "4.1.10"
|
|
50
50
|
},
|
|
51
51
|
"author": "Prosopo",
|
|
52
52
|
"license": "Apache-2.0",
|