@qp-mongosh/shell-api 0.0.0-dev.5 → 0.0.0-dev.7
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/.eslintignore +2 -2
- package/.eslintrc.js +1 -1
- package/AUTHORS +15 -15
- package/LICENSE +200 -200
- package/bin/report-missing-help.ts +24 -24
- package/bin/report-supported-api.ts +14 -14
- package/lib/abstract-cursor.d.ts +33 -33
- package/lib/abstract-cursor.js +191 -191
- package/lib/aggregation-cursor.d.ts +6 -6
- package/lib/aggregation-cursor.js +19 -19
- package/lib/bulk.d.ts +43 -43
- package/lib/bulk.js +223 -223
- package/lib/change-stream-cursor.d.ts +28 -28
- package/lib/change-stream-cursor.js +111 -111
- package/lib/collection.d.ts +95 -95
- package/lib/collection.js +964 -964
- package/lib/cursor.d.ts +32 -32
- package/lib/cursor.js +215 -215
- package/lib/database.d.ts +116 -116
- package/lib/database.js +1223 -1223
- package/lib/dbquery.d.ts +8 -8
- package/lib/dbquery.js +28 -28
- package/lib/decorators.d.ts +73 -73
- package/lib/decorators.js +395 -395
- package/lib/deprecation-warning.d.ts +2 -0
- package/lib/deprecation-warning.js +19 -0
- package/lib/deprecation-warning.js.map +1 -0
- package/lib/enums.d.ts +28 -28
- package/lib/enums.js +33 -33
- package/lib/error-codes.d.ts +12 -12
- package/lib/error-codes.js +19 -19
- package/lib/explainable-cursor.d.ts +11 -11
- package/lib/explainable-cursor.js +31 -31
- package/lib/explainable.d.ts +32 -32
- package/lib/explainable.js +166 -166
- package/lib/field-level-encryption.d.ts +50 -50
- package/lib/field-level-encryption.js +176 -176
- package/lib/help.d.ts +22 -22
- package/lib/help.js +26 -26
- package/lib/helpers.d.ts +71 -71
- package/lib/helpers.js +588 -588
- package/lib/index.d.ts +16 -16
- package/lib/index.js +45 -45
- package/lib/interruptor.d.ts +19 -19
- package/lib/interruptor.js +62 -62
- package/lib/mongo-errors.d.ts +5 -5
- package/lib/mongo-errors.js +37 -37
- package/lib/mongo.d.ts +75 -75
- package/lib/mongo.js +476 -476
- package/lib/no-db.d.ts +5 -5
- package/lib/no-db.js +28 -28
- package/lib/plan-cache.d.ts +16 -16
- package/lib/plan-cache.js +70 -70
- package/lib/replica-set.d.ts +45 -45
- package/lib/replica-set.js +314 -314
- package/lib/result.d.ts +61 -61
- package/lib/result.js +104 -104
- package/lib/session.d.ts +25 -25
- package/lib/session.js +88 -88
- package/lib/shard.d.ts +42 -42
- package/lib/shard.js +414 -414
- package/lib/shell-api.d.ts +52 -52
- package/lib/shell-api.js +298 -298
- package/lib/shell-bson.d.ts +40 -40
- package/lib/shell-bson.js +159 -159
- package/lib/shell-instance-state.d.ts +77 -77
- package/lib/shell-instance-state.js +392 -392
- package/lib/shell-internal-state.d.ts +74 -0
- package/lib/shell-internal-state.js +364 -0
- package/lib/shell-internal-state.js.map +1 -0
- package/package.json +47 -47
- package/tsconfig.lint.json +8 -8
package/lib/helpers.js
CHANGED
|
@@ -1,589 +1,589 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.adjustRunCommand = exports.shouldRunAggregationImmediately = exports.isValidCollectionName = exports.isValidDatabaseName = exports.markAsExplainOutput = exports.maybeMarkAsExplainOutput = exports.processFLEOptions = exports.assertCLI = exports.setHideIndex = exports.processMapReduceOptions = exports.processRemoveOptions = exports.processFindAndModifyOptions = exports.iterate = exports.addHiddenDataProperty = exports.tsToSeconds = exports.dataFormat = exports.getConfigDB = exports.getPrintableShardStatus = exports.processDigestPassword = exports.adaptOptions = exports.assertKeysDefined = exports.assertArgsDefinedType = exports.validateExplainableVerbosity = exports.adaptAggregateOptions = void 0;
|
|
7
|
-
const errors_1 = require("@qp-mongosh/errors");
|
|
8
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
9
|
-
const error_codes_1 = require("./error-codes");
|
|
10
|
-
const service_provider_core_1 = require("@qp-mongosh/service-provider-core");
|
|
11
|
-
const enums_1 = require("./enums");
|
|
12
|
-
const util_1 = require("util");
|
|
13
|
-
function adaptAggregateOptions(options = {}) {
|
|
14
|
-
const aggOptions = { ...options };
|
|
15
|
-
const dbOptions = {};
|
|
16
|
-
let explain;
|
|
17
|
-
if ('readConcern' in aggOptions) {
|
|
18
|
-
dbOptions.readConcern = options.readConcern;
|
|
19
|
-
delete aggOptions.readConcern;
|
|
20
|
-
}
|
|
21
|
-
if ('writeConcern' in aggOptions) {
|
|
22
|
-
Object.assign(dbOptions, options.writeConcern);
|
|
23
|
-
delete aggOptions.writeConcern;
|
|
24
|
-
}
|
|
25
|
-
if ('explain' in aggOptions) {
|
|
26
|
-
explain = validateExplainableVerbosity(aggOptions.explain);
|
|
27
|
-
delete aggOptions.explain;
|
|
28
|
-
}
|
|
29
|
-
return { aggOptions, dbOptions, explain };
|
|
30
|
-
}
|
|
31
|
-
exports.adaptAggregateOptions = adaptAggregateOptions;
|
|
32
|
-
function validateExplainableVerbosity(verbosity) {
|
|
33
|
-
if (verbosity === true) {
|
|
34
|
-
verbosity = 'allPlansExecution';
|
|
35
|
-
}
|
|
36
|
-
else if (verbosity === false) {
|
|
37
|
-
verbosity = 'queryPlanner';
|
|
38
|
-
}
|
|
39
|
-
if (typeof verbosity !== 'string') {
|
|
40
|
-
throw new errors_1.MongoshInvalidInputError('verbosity must be a string', errors_1.CommonErrors.InvalidArgument);
|
|
41
|
-
}
|
|
42
|
-
return verbosity;
|
|
43
|
-
}
|
|
44
|
-
exports.validateExplainableVerbosity = validateExplainableVerbosity;
|
|
45
|
-
function getAssertCaller(caller) {
|
|
46
|
-
return caller ? ` (${caller})` : '';
|
|
47
|
-
}
|
|
48
|
-
function assertArgsDefinedType(args, expectedTypes, func) {
|
|
49
|
-
args.forEach((arg, i) => {
|
|
50
|
-
const expected = expectedTypes[i];
|
|
51
|
-
if (arg === undefined) {
|
|
52
|
-
if (expected !== true && Array.isArray(expected) && expected.includes(undefined)) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
throw new errors_1.MongoshInvalidInputError(`Missing required argument at position ${i}${getAssertCaller(func)}`, errors_1.CommonErrors.InvalidArgument);
|
|
56
|
-
}
|
|
57
|
-
else if (expected === true) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
const expectedTypesList = typeof expected === 'string' ? [expected] : expected;
|
|
61
|
-
const isExpectedTypeof = expectedTypesList.includes(typeof arg);
|
|
62
|
-
const isExpectedBson = expectedTypesList.includes(`bson:${arg === null || arg === void 0 ? void 0 : arg._bsontype}`);
|
|
63
|
-
if (!isExpectedTypeof && !isExpectedBson) {
|
|
64
|
-
const expectedMsg = expectedTypesList
|
|
65
|
-
.filter(e => e !== undefined)
|
|
66
|
-
.map(e => e === null || e === void 0 ? void 0 : e.replace(/^bson:/, ''))
|
|
67
|
-
.join(' or ');
|
|
68
|
-
throw new errors_1.MongoshInvalidInputError(`Argument at position ${i} must be of type ${expectedMsg}, got ${typeof arg} instead${getAssertCaller(func)}`, errors_1.CommonErrors.InvalidArgument);
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
exports.assertArgsDefinedType = assertArgsDefinedType;
|
|
73
|
-
function assertKeysDefined(object, keys) {
|
|
74
|
-
for (const key of keys) {
|
|
75
|
-
if (object[key] === undefined) {
|
|
76
|
-
throw new errors_1.MongoshInvalidInputError(`Missing required property: ${JSON.stringify(key)}`, errors_1.CommonErrors.InvalidArgument);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
exports.assertKeysDefined = assertKeysDefined;
|
|
81
|
-
function adaptOptions(shellToCommand, additions, shellDoc) {
|
|
82
|
-
return Object.keys(shellDoc).reduce((result, shellKey) => {
|
|
83
|
-
if (shellToCommand[shellKey] === null) {
|
|
84
|
-
return result;
|
|
85
|
-
}
|
|
86
|
-
result[shellToCommand[shellKey] || shellKey] = shellDoc[shellKey];
|
|
87
|
-
return result;
|
|
88
|
-
}, additions);
|
|
89
|
-
}
|
|
90
|
-
exports.adaptOptions = adaptOptions;
|
|
91
|
-
function processDigestPassword(username, passwordDigestor, command) {
|
|
92
|
-
if (passwordDigestor === undefined) {
|
|
93
|
-
return {};
|
|
94
|
-
}
|
|
95
|
-
if (passwordDigestor !== 'server' && passwordDigestor !== 'client') {
|
|
96
|
-
throw new errors_1.MongoshInvalidInputError(`Invalid field: passwordDigestor must be 'client' or 'server', got ${passwordDigestor}`, errors_1.CommonErrors.InvalidArgument);
|
|
97
|
-
}
|
|
98
|
-
if (passwordDigestor === 'client') {
|
|
99
|
-
if (typeof command.pwd !== 'string') {
|
|
100
|
-
throw new errors_1.MongoshInvalidInputError(`User passwords must be of type string. Was given password with type ${typeof command.pwd}`, errors_1.CommonErrors.InvalidArgument);
|
|
101
|
-
}
|
|
102
|
-
const hash = crypto_1.default.createHash('md5');
|
|
103
|
-
hash.update(`${username}:mongo:${command.pwd}`);
|
|
104
|
-
const digested = hash.digest('hex');
|
|
105
|
-
return { digestPassword: false, pwd: digested };
|
|
106
|
-
}
|
|
107
|
-
return { digestPassword: true };
|
|
108
|
-
}
|
|
109
|
-
exports.processDigestPassword = processDigestPassword;
|
|
110
|
-
async function getPrintableShardStatus(configDB, verbose) {
|
|
111
|
-
const result = {};
|
|
112
|
-
const mongosColl = configDB.getCollection('mongos');
|
|
113
|
-
const versionColl = configDB.getCollection('version');
|
|
114
|
-
const shardsColl = configDB.getCollection('shards');
|
|
115
|
-
const chunksColl = configDB.getCollection('chunks');
|
|
116
|
-
const settingsColl = configDB.getCollection('settings');
|
|
117
|
-
const changelogColl = configDB.getCollection('changelog');
|
|
118
|
-
const [version, shards, mostRecentMongos] = await Promise.all([
|
|
119
|
-
versionColl.findOne(),
|
|
120
|
-
shardsColl.find().then(cursor => cursor.sort({ _id: 1 }).toArray()),
|
|
121
|
-
mongosColl.find().then(cursor => cursor.sort({ ping: -1 }).limit(1).tryNext())
|
|
122
|
-
]);
|
|
123
|
-
if (version === null) {
|
|
124
|
-
throw new errors_1.MongoshInvalidInputError('This db does not have sharding enabled. Be sure you are connecting to a mongos from the shell and not to a mongod.', error_codes_1.ShellApiErrors.NotConnectedToMongos);
|
|
125
|
-
}
|
|
126
|
-
result.shardingVersion = version;
|
|
127
|
-
result.shards = shards;
|
|
128
|
-
const mongosActiveThresholdMs = 60000;
|
|
129
|
-
let mostRecentMongosTime = null;
|
|
130
|
-
let mongosAdjective = 'most recently active';
|
|
131
|
-
if (mostRecentMongos !== null) {
|
|
132
|
-
mostRecentMongosTime = mostRecentMongos.ping;
|
|
133
|
-
if (mostRecentMongosTime.getTime() >= Date.now() - mongosActiveThresholdMs) {
|
|
134
|
-
mongosAdjective = 'active';
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
mongosAdjective = `${mongosAdjective} mongoses`;
|
|
138
|
-
if (mostRecentMongosTime === null) {
|
|
139
|
-
result[mongosAdjective] = 'none';
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
const recentMongosQuery = {
|
|
143
|
-
ping: {
|
|
144
|
-
$gt: (() => {
|
|
145
|
-
const d = mostRecentMongosTime;
|
|
146
|
-
d.setTime(d.getTime() - mongosActiveThresholdMs);
|
|
147
|
-
return d;
|
|
148
|
-
})()
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
if (verbose) {
|
|
152
|
-
result[mongosAdjective] = await (await mongosColl
|
|
153
|
-
.find(recentMongosQuery))
|
|
154
|
-
.sort({ ping: -1 })
|
|
155
|
-
.toArray();
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
result[mongosAdjective] = (await (await mongosColl.aggregate([
|
|
159
|
-
{ $match: recentMongosQuery },
|
|
160
|
-
{ $group: { _id: '$mongoVersion', num: { $sum: 1 } } },
|
|
161
|
-
{ $sort: { num: -1 } }
|
|
162
|
-
])).toArray()).map((z) => {
|
|
163
|
-
return { [z._id]: z.num };
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
const balancerRes = {};
|
|
168
|
-
await Promise.all([
|
|
169
|
-
(async () => {
|
|
170
|
-
const autosplit = await settingsColl.findOne({ _id: 'autosplit' });
|
|
171
|
-
result.autosplit = { 'Currently enabled': autosplit === null || autosplit.enabled ? 'yes' : 'no' };
|
|
172
|
-
})(),
|
|
173
|
-
(async () => {
|
|
174
|
-
const balancerEnabled = await settingsColl.findOne({ _id: 'balancer' });
|
|
175
|
-
balancerRes['Currently enabled'] = balancerEnabled === null || !balancerEnabled.stopped ? 'yes' : 'no';
|
|
176
|
-
})(),
|
|
177
|
-
(async () => {
|
|
178
|
-
let balancerRunning = 'unknown';
|
|
179
|
-
try {
|
|
180
|
-
const balancerStatus = await configDB.adminCommand({ balancerStatus: 1 });
|
|
181
|
-
balancerRunning = balancerStatus.inBalancerRound ? 'yes' : 'no';
|
|
182
|
-
}
|
|
183
|
-
catch (err) {
|
|
184
|
-
}
|
|
185
|
-
balancerRes['Currently running'] = balancerRunning;
|
|
186
|
-
})(),
|
|
187
|
-
(async () => {
|
|
188
|
-
const settings = await settingsColl.findOne({ _id: 'balancer' });
|
|
189
|
-
if (settings !== null && settings.hasOwnProperty('activeWindow')) {
|
|
190
|
-
const balSettings = settings.activeWindow;
|
|
191
|
-
balancerRes['Balancer active window is set between'] = `${balSettings.start} and ${balSettings.stop} server local time`;
|
|
192
|
-
}
|
|
193
|
-
})(),
|
|
194
|
-
(async () => {
|
|
195
|
-
const activeLocks = await (await configDB.getCollection('locks').find({ state: { $eq: 2 } })).toArray();
|
|
196
|
-
if ((activeLocks === null || activeLocks === void 0 ? void 0 : activeLocks.length) > 0) {
|
|
197
|
-
balancerRes['Collections with active migrations'] = activeLocks.map((lock) => {
|
|
198
|
-
return `${lock._id} started at ${lock.when}`;
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
})(),
|
|
202
|
-
(async () => {
|
|
203
|
-
let versionHasActionlog = false;
|
|
204
|
-
const metaDataVersion = version.currentVersion;
|
|
205
|
-
if (metaDataVersion > 5) {
|
|
206
|
-
versionHasActionlog = true;
|
|
207
|
-
}
|
|
208
|
-
if (metaDataVersion === 5) {
|
|
209
|
-
const verArray = (await configDB.serverBuildInfo()).versionArray;
|
|
210
|
-
if (verArray[0] === 2 && verArray[1] > 6) {
|
|
211
|
-
versionHasActionlog = true;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
if (versionHasActionlog) {
|
|
215
|
-
const balErrs = await (await configDB.getCollection('actionlog').find({ what: 'balancer.round' })).sort({ time: -1 }).limit(5).toArray();
|
|
216
|
-
const actionReport = { count: 0, lastErr: '', lastTime: ' ' };
|
|
217
|
-
if (balErrs !== null) {
|
|
218
|
-
balErrs.forEach((r) => {
|
|
219
|
-
if (r.details.errorOccured) {
|
|
220
|
-
actionReport.count += 1;
|
|
221
|
-
if (actionReport.count === 1) {
|
|
222
|
-
actionReport.lastErr = r.details.errmsg;
|
|
223
|
-
actionReport.lastTime = r.time;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
balancerRes['Failed balancer rounds in last 5 attempts'] = actionReport.count;
|
|
229
|
-
if (actionReport.count > 0) {
|
|
230
|
-
balancerRes['Last reported error'] = actionReport.lastErr;
|
|
231
|
-
balancerRes['Time of Reported error'] = actionReport.lastTime;
|
|
232
|
-
}
|
|
233
|
-
const yesterday = new Date();
|
|
234
|
-
yesterday.setDate(yesterday.getDate() - 1);
|
|
235
|
-
let migrations = await (await changelogColl
|
|
236
|
-
.aggregate([
|
|
237
|
-
{
|
|
238
|
-
$match: {
|
|
239
|
-
time: { $gt: yesterday },
|
|
240
|
-
what: 'moveChunk.from',
|
|
241
|
-
'details.errmsg': { $exists: false },
|
|
242
|
-
'details.note': 'success'
|
|
243
|
-
}
|
|
244
|
-
},
|
|
245
|
-
{ $group: { _id: { msg: '$details.errmsg' }, count: { $sum: 1 } } },
|
|
246
|
-
{ $project: { _id: { $ifNull: ['$_id.msg', 'Success'] }, count: '$count' } }
|
|
247
|
-
]))
|
|
248
|
-
.toArray();
|
|
249
|
-
migrations = migrations.concat(await (await changelogColl
|
|
250
|
-
.aggregate([
|
|
251
|
-
{
|
|
252
|
-
$match: {
|
|
253
|
-
time: { $gt: yesterday },
|
|
254
|
-
what: 'moveChunk.from',
|
|
255
|
-
$or: [
|
|
256
|
-
{ 'details.errmsg': { $exists: true } },
|
|
257
|
-
{ 'details.note': { $ne: 'success' } }
|
|
258
|
-
]
|
|
259
|
-
}
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
$group: {
|
|
263
|
-
_id: { msg: '$details.errmsg', from: '$details.from', to: '$details.to' },
|
|
264
|
-
count: { $sum: 1 }
|
|
265
|
-
}
|
|
266
|
-
},
|
|
267
|
-
{
|
|
268
|
-
$project: {
|
|
269
|
-
_id: { $ifNull: ['$_id.msg', 'aborted'] },
|
|
270
|
-
from: '$_id.from',
|
|
271
|
-
to: '$_id.to',
|
|
272
|
-
count: '$count'
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
]))
|
|
276
|
-
.toArray());
|
|
277
|
-
const migrationsRes = {};
|
|
278
|
-
migrations.forEach((x) => {
|
|
279
|
-
if (x._id === 'Success') {
|
|
280
|
-
migrationsRes[x.count] = x._id;
|
|
281
|
-
}
|
|
282
|
-
else {
|
|
283
|
-
migrationsRes[x.count] = `Failed with error '${x._id}', from ${x.from} to ${x.to}`;
|
|
284
|
-
}
|
|
285
|
-
});
|
|
286
|
-
if (migrations.length === 0) {
|
|
287
|
-
balancerRes['Migration Results for the last 24 hours'] = 'No recent migrations';
|
|
288
|
-
}
|
|
289
|
-
else {
|
|
290
|
-
balancerRes['Migration Results for the last 24 hours'] = migrationsRes;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
})()
|
|
294
|
-
]);
|
|
295
|
-
result.balancer = balancerRes;
|
|
296
|
-
const dbRes = [];
|
|
297
|
-
result.databases = dbRes;
|
|
298
|
-
const databases = await (await configDB.getCollection('databases').find()).sort({ name: 1 }).toArray();
|
|
299
|
-
databases.push({ '_id': 'config', 'primary': 'config', 'partitioned': true });
|
|
300
|
-
databases.sort((a, b) => {
|
|
301
|
-
return a._id.localeCompare(b._id);
|
|
302
|
-
});
|
|
303
|
-
result.databases = await Promise.all(databases.map(async (db) => {
|
|
304
|
-
const escapeRegex = (string) => {
|
|
305
|
-
return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
306
|
-
};
|
|
307
|
-
const colls = await (await configDB.getCollection('collections')
|
|
308
|
-
.find({ _id: new RegExp('^' + escapeRegex(db._id) + '\\.') }))
|
|
309
|
-
.sort({ _id: 1 })
|
|
310
|
-
.toArray();
|
|
311
|
-
const collList = await Promise.all(colls.filter(coll => !coll.dropped).map(async (coll) => {
|
|
312
|
-
const collRes = {};
|
|
313
|
-
collRes.shardKey = coll.key;
|
|
314
|
-
collRes.unique = !!coll.unique;
|
|
315
|
-
if (typeof coll.unique !== 'boolean' && typeof coll.unique !== 'undefined') {
|
|
316
|
-
collRes.unique = [!!coll.unique, { unique: coll.unique }];
|
|
317
|
-
}
|
|
318
|
-
collRes.balancing = !coll.noBalance;
|
|
319
|
-
if (typeof coll.noBalance !== 'boolean' && typeof coll.noBalance !== 'undefined') {
|
|
320
|
-
collRes.balancing = [!coll.noBalance, { noBalance: coll.noBalance }];
|
|
321
|
-
}
|
|
322
|
-
const chunksRes = [];
|
|
323
|
-
const chunksCollMatch = coll.uuid ? { $or: [{ uuid: coll.uuid }, { ns: coll._id }] } : { ns: coll._id };
|
|
324
|
-
const chunks = await (await chunksColl.aggregate([
|
|
325
|
-
{ $match: chunksCollMatch },
|
|
326
|
-
{ $group: { _id: '$shard', cnt: { $sum: 1 } } },
|
|
327
|
-
{ $project: { _id: 0, shard: '$_id', nChunks: '$cnt' } },
|
|
328
|
-
{ $sort: { shard: 1 } }
|
|
329
|
-
])).toArray();
|
|
330
|
-
let totalChunks = 0;
|
|
331
|
-
collRes.chunkMetadata = [];
|
|
332
|
-
chunks.forEach((z) => {
|
|
333
|
-
totalChunks += z.nChunks;
|
|
334
|
-
collRes.chunkMetadata.push({ shard: z.shard, nChunks: z.nChunks });
|
|
335
|
-
});
|
|
336
|
-
if (totalChunks < 20 || verbose) {
|
|
337
|
-
for await (const chunk of (await chunksColl.find(chunksCollMatch)).sort({ min: 1 })) {
|
|
338
|
-
const c = {
|
|
339
|
-
min: chunk.min,
|
|
340
|
-
max: chunk.max,
|
|
341
|
-
'on shard': chunk.shard,
|
|
342
|
-
'last modified': chunk.lastmod
|
|
343
|
-
};
|
|
344
|
-
Object.defineProperty(c, Symbol.for('nodejs.util.inspect.custom'), {
|
|
345
|
-
value: function (depth, options) {
|
|
346
|
-
return (0, util_1.inspect)({ ...this }, { ...options, breakLength: Infinity });
|
|
347
|
-
},
|
|
348
|
-
writable: true,
|
|
349
|
-
configurable: true
|
|
350
|
-
});
|
|
351
|
-
if (chunk.jumbo)
|
|
352
|
-
c.jumbo = 'yes';
|
|
353
|
-
chunksRes.push(c);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
else {
|
|
357
|
-
chunksRes.push('too many chunks to print, use verbose if you want to force print');
|
|
358
|
-
}
|
|
359
|
-
const tagsRes = [];
|
|
360
|
-
for await (const tag of (await configDB.getCollection('tags').find(chunksCollMatch)).sort({ min: 1 })) {
|
|
361
|
-
tagsRes.push({
|
|
362
|
-
tag: tag.tag,
|
|
363
|
-
min: tag.min,
|
|
364
|
-
max: tag.max
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
collRes.chunks = chunksRes;
|
|
368
|
-
collRes.tags = tagsRes;
|
|
369
|
-
return [coll._id, collRes];
|
|
370
|
-
}));
|
|
371
|
-
return { database: db, collections: Object.fromEntries(collList) };
|
|
372
|
-
}));
|
|
373
|
-
return result;
|
|
374
|
-
}
|
|
375
|
-
exports.getPrintableShardStatus = getPrintableShardStatus;
|
|
376
|
-
async function getConfigDB(db) {
|
|
377
|
-
const helloResult = await db._maybeCachedHello();
|
|
378
|
-
if (helloResult.msg !== 'isdbgrid') {
|
|
379
|
-
await db._instanceState.printWarning('MongoshWarning: [SHAPI-10003] You are not connected to a mongos. This command may not work as expected.');
|
|
380
|
-
}
|
|
381
|
-
return db.getSiblingDB('config');
|
|
382
|
-
}
|
|
383
|
-
exports.getConfigDB = getConfigDB;
|
|
384
|
-
function dataFormat(bytes) {
|
|
385
|
-
if (bytes === null || bytes === undefined) {
|
|
386
|
-
return '0B';
|
|
387
|
-
}
|
|
388
|
-
if (bytes < 1024) {
|
|
389
|
-
return Math.floor(bytes) + 'B';
|
|
390
|
-
}
|
|
391
|
-
if (bytes < 1024 * 1024) {
|
|
392
|
-
return Math.floor(bytes / 1024) + 'KiB';
|
|
393
|
-
}
|
|
394
|
-
if (bytes < 1024 * 1024 * 1024) {
|
|
395
|
-
return Math.floor((Math.floor(bytes / 1024) / 1024) * 100) / 100 + 'MiB';
|
|
396
|
-
}
|
|
397
|
-
return Math.floor((Math.floor(bytes / (1024 * 1024)) / 1024) * 100) / 100 + 'GiB';
|
|
398
|
-
}
|
|
399
|
-
exports.dataFormat = dataFormat;
|
|
400
|
-
function tsToSeconds(x) {
|
|
401
|
-
if (x.t && x.i) {
|
|
402
|
-
return x.t;
|
|
403
|
-
}
|
|
404
|
-
return x / 4294967296;
|
|
405
|
-
}
|
|
406
|
-
exports.tsToSeconds = tsToSeconds;
|
|
407
|
-
function addHiddenDataProperty(target, key, value) {
|
|
408
|
-
Object.defineProperty(target, key, {
|
|
409
|
-
value,
|
|
410
|
-
enumerable: false,
|
|
411
|
-
writable: true,
|
|
412
|
-
configurable: true
|
|
413
|
-
});
|
|
414
|
-
return target;
|
|
415
|
-
}
|
|
416
|
-
exports.addHiddenDataProperty = addHiddenDataProperty;
|
|
417
|
-
async function iterate(results, cursor, batchSize) {
|
|
418
|
-
if (cursor.isClosed()) {
|
|
419
|
-
return results;
|
|
420
|
-
}
|
|
421
|
-
for (let i = 0; i < batchSize; i++) {
|
|
422
|
-
const doc = await cursor.tryNext();
|
|
423
|
-
if (doc === null) {
|
|
424
|
-
results.cursorHasMore = false;
|
|
425
|
-
break;
|
|
426
|
-
}
|
|
427
|
-
results.documents.push(doc);
|
|
428
|
-
}
|
|
429
|
-
return results;
|
|
430
|
-
}
|
|
431
|
-
exports.iterate = iterate;
|
|
432
|
-
function processFindAndModifyOptions(options) {
|
|
433
|
-
options = { ...options };
|
|
434
|
-
if ('returnDocument' in options) {
|
|
435
|
-
if (options.returnDocument !== 'before' && options.returnDocument !== 'after') {
|
|
436
|
-
throw new errors_1.MongoshInvalidInputError("returnDocument needs to be either 'before' or 'after'", errors_1.CommonErrors.InvalidArgument);
|
|
437
|
-
}
|
|
438
|
-
delete options.returnNewDocument;
|
|
439
|
-
delete options.returnOriginal;
|
|
440
|
-
return options;
|
|
441
|
-
}
|
|
442
|
-
if ('returnOriginal' in options) {
|
|
443
|
-
options.returnDocument = options.returnOriginal ? 'before' : 'after';
|
|
444
|
-
delete options.returnOriginal;
|
|
445
|
-
delete options.returnNewDocument;
|
|
446
|
-
return options;
|
|
447
|
-
}
|
|
448
|
-
if ('returnNewDocument' in options) {
|
|
449
|
-
options.returnDocument = options.returnNewDocument ? 'after' : 'before';
|
|
450
|
-
delete options.returnOriginal;
|
|
451
|
-
delete options.returnNewDocument;
|
|
452
|
-
return options;
|
|
453
|
-
}
|
|
454
|
-
if ('new' in options) {
|
|
455
|
-
options.returnDocument = options.new ? 'after' : 'before';
|
|
456
|
-
delete options.returnOriginal;
|
|
457
|
-
delete options.returnNewDocument;
|
|
458
|
-
return options;
|
|
459
|
-
}
|
|
460
|
-
options.returnDocument = 'before';
|
|
461
|
-
return options;
|
|
462
|
-
}
|
|
463
|
-
exports.processFindAndModifyOptions = processFindAndModifyOptions;
|
|
464
|
-
function processRemoveOptions(options) {
|
|
465
|
-
if (typeof options === 'boolean') {
|
|
466
|
-
return { justOne: options };
|
|
467
|
-
}
|
|
468
|
-
return { justOne: false, ...options };
|
|
469
|
-
}
|
|
470
|
-
exports.processRemoveOptions = processRemoveOptions;
|
|
471
|
-
function processMapReduceOptions(optionsOrOutString) {
|
|
472
|
-
if (typeof optionsOrOutString === 'string') {
|
|
473
|
-
return { out: optionsOrOutString };
|
|
474
|
-
}
|
|
475
|
-
else if (optionsOrOutString.out === undefined) {
|
|
476
|
-
throw new errors_1.MongoshInvalidInputError('Missing \'out\' option', errors_1.CommonErrors.InvalidArgument);
|
|
477
|
-
}
|
|
478
|
-
else {
|
|
479
|
-
return optionsOrOutString;
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
exports.processMapReduceOptions = processMapReduceOptions;
|
|
483
|
-
async function setHideIndex(coll, index, hidden) {
|
|
484
|
-
const cmd = typeof index === 'string' ? {
|
|
485
|
-
name: index, hidden
|
|
486
|
-
} : {
|
|
487
|
-
keyPattern: index, hidden
|
|
488
|
-
};
|
|
489
|
-
return await coll._database._runCommand({
|
|
490
|
-
collMod: coll._name,
|
|
491
|
-
index: cmd
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
|
-
exports.setHideIndex = setHideIndex;
|
|
495
|
-
function assertCLI(platform, features) {
|
|
496
|
-
if (platform !== service_provider_core_1.ReplPlatform.CLI) {
|
|
497
|
-
throw new errors_1.MongoshUnimplementedError(`${features} are not supported for current platform: ${service_provider_core_1.ReplPlatform[platform]}`, errors_1.CommonErrors.NotImplemented);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
exports.assertCLI = assertCLI;
|
|
501
|
-
function processFLEOptions(fleOptions) {
|
|
502
|
-
var _a, _b;
|
|
503
|
-
assertKeysDefined(fleOptions, ['keyVaultNamespace', 'kmsProviders']);
|
|
504
|
-
Object.keys(fleOptions).forEach(k => {
|
|
505
|
-
if (['keyVaultClient', 'keyVaultNamespace', 'kmsProviders', 'schemaMap', 'bypassAutoEncryption', 'tlsOptions'].indexOf(k) === -1) {
|
|
506
|
-
throw new errors_1.MongoshInvalidInputError(`Unrecognized FLE Client Option ${k}`);
|
|
507
|
-
}
|
|
508
|
-
});
|
|
509
|
-
const autoEncryption = {
|
|
510
|
-
keyVaultClient: (_a = fleOptions.keyVaultClient) === null || _a === void 0 ? void 0 : _a._serviceProvider.getRawClient(),
|
|
511
|
-
keyVaultNamespace: fleOptions.keyVaultNamespace
|
|
512
|
-
};
|
|
513
|
-
const localKey = (_b = fleOptions.kmsProviders.local) === null || _b === void 0 ? void 0 : _b.key;
|
|
514
|
-
if (localKey && localKey._bsontype === 'Binary') {
|
|
515
|
-
const rawBuff = localKey.value(true);
|
|
516
|
-
if (Buffer.isBuffer(rawBuff)) {
|
|
517
|
-
autoEncryption.kmsProviders = {
|
|
518
|
-
...fleOptions.kmsProviders,
|
|
519
|
-
local: {
|
|
520
|
-
key: rawBuff
|
|
521
|
-
}
|
|
522
|
-
};
|
|
523
|
-
}
|
|
524
|
-
else {
|
|
525
|
-
throw new errors_1.MongoshInvalidInputError('When specifying the key of a local KMS as BSON binary it must be constructed from a base64 encoded string');
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
else {
|
|
529
|
-
autoEncryption.kmsProviders = { ...fleOptions.kmsProviders };
|
|
530
|
-
}
|
|
531
|
-
if (fleOptions.schemaMap) {
|
|
532
|
-
autoEncryption.schemaMap = fleOptions.schemaMap;
|
|
533
|
-
}
|
|
534
|
-
if (fleOptions.bypassAutoEncryption !== undefined) {
|
|
535
|
-
autoEncryption.bypassAutoEncryption = fleOptions.bypassAutoEncryption;
|
|
536
|
-
}
|
|
537
|
-
if (fleOptions.tlsOptions !== undefined) {
|
|
538
|
-
autoEncryption.tlsOptions = fleOptions.tlsOptions;
|
|
539
|
-
}
|
|
540
|
-
return autoEncryption;
|
|
541
|
-
}
|
|
542
|
-
exports.processFLEOptions = processFLEOptions;
|
|
543
|
-
function maybeMarkAsExplainOutput(value, options) {
|
|
544
|
-
if ('explain' in options) {
|
|
545
|
-
return markAsExplainOutput(value);
|
|
546
|
-
}
|
|
547
|
-
return value;
|
|
548
|
-
}
|
|
549
|
-
exports.maybeMarkAsExplainOutput = maybeMarkAsExplainOutput;
|
|
550
|
-
function markAsExplainOutput(value) {
|
|
551
|
-
if (value !== null && typeof value === 'object') {
|
|
552
|
-
addHiddenDataProperty(value, enums_1.shellApiType, 'ExplainOutput');
|
|
553
|
-
}
|
|
554
|
-
return value;
|
|
555
|
-
}
|
|
556
|
-
exports.markAsExplainOutput = markAsExplainOutput;
|
|
557
|
-
function isValidDatabaseName(name) {
|
|
558
|
-
return !!name && !/[/\\. "\0]/.test(name);
|
|
559
|
-
}
|
|
560
|
-
exports.isValidDatabaseName = isValidDatabaseName;
|
|
561
|
-
function isValidCollectionName(name) {
|
|
562
|
-
return !!name && !/[$\0]/.test(name);
|
|
563
|
-
}
|
|
564
|
-
exports.isValidCollectionName = isValidCollectionName;
|
|
565
|
-
function shouldRunAggregationImmediately(pipeline) {
|
|
566
|
-
return pipeline.some(stage => Object.keys(stage).some(stageName => stageName === '$merge' || stageName === '$out'));
|
|
567
|
-
}
|
|
568
|
-
exports.shouldRunAggregationImmediately = shouldRunAggregationImmediately;
|
|
569
|
-
function isBSONDoubleConvertible(val) {
|
|
570
|
-
return (typeof val === 'number' && Number.isInteger(val)) || (val === null || val === void 0 ? void 0 : val._bsontype) === 'Int32';
|
|
571
|
-
}
|
|
572
|
-
function adjustRunCommand(cmd, shellBson) {
|
|
573
|
-
if (cmd.replSetResizeOplog) {
|
|
574
|
-
if ('size' in cmd && isBSONDoubleConvertible(cmd.size)) {
|
|
575
|
-
return adjustRunCommand({ ...cmd, size: new shellBson.Double(+cmd.size) }, shellBson);
|
|
576
|
-
}
|
|
577
|
-
if ('minRetentionHours' in cmd && isBSONDoubleConvertible(cmd.minRetentionHours)) {
|
|
578
|
-
return adjustRunCommand({ ...cmd, minRetentionHours: new shellBson.Double(+cmd.minRetentionHours) }, shellBson);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
if (cmd.profile) {
|
|
582
|
-
if ('sampleRate' in cmd && isBSONDoubleConvertible(cmd.sampleRate)) {
|
|
583
|
-
return adjustRunCommand({ ...cmd, sampleRate: new shellBson.Double(+cmd.sampleRate) }, shellBson);
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
return cmd;
|
|
587
|
-
}
|
|
588
|
-
exports.adjustRunCommand = adjustRunCommand;
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.adjustRunCommand = exports.shouldRunAggregationImmediately = exports.isValidCollectionName = exports.isValidDatabaseName = exports.markAsExplainOutput = exports.maybeMarkAsExplainOutput = exports.processFLEOptions = exports.assertCLI = exports.setHideIndex = exports.processMapReduceOptions = exports.processRemoveOptions = exports.processFindAndModifyOptions = exports.iterate = exports.addHiddenDataProperty = exports.tsToSeconds = exports.dataFormat = exports.getConfigDB = exports.getPrintableShardStatus = exports.processDigestPassword = exports.adaptOptions = exports.assertKeysDefined = exports.assertArgsDefinedType = exports.validateExplainableVerbosity = exports.adaptAggregateOptions = void 0;
|
|
7
|
+
const errors_1 = require("@qp-mongosh/errors");
|
|
8
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
9
|
+
const error_codes_1 = require("./error-codes");
|
|
10
|
+
const service_provider_core_1 = require("@qp-mongosh/service-provider-core");
|
|
11
|
+
const enums_1 = require("./enums");
|
|
12
|
+
const util_1 = require("util");
|
|
13
|
+
function adaptAggregateOptions(options = {}) {
|
|
14
|
+
const aggOptions = { ...options };
|
|
15
|
+
const dbOptions = {};
|
|
16
|
+
let explain;
|
|
17
|
+
if ('readConcern' in aggOptions) {
|
|
18
|
+
dbOptions.readConcern = options.readConcern;
|
|
19
|
+
delete aggOptions.readConcern;
|
|
20
|
+
}
|
|
21
|
+
if ('writeConcern' in aggOptions) {
|
|
22
|
+
Object.assign(dbOptions, options.writeConcern);
|
|
23
|
+
delete aggOptions.writeConcern;
|
|
24
|
+
}
|
|
25
|
+
if ('explain' in aggOptions) {
|
|
26
|
+
explain = validateExplainableVerbosity(aggOptions.explain);
|
|
27
|
+
delete aggOptions.explain;
|
|
28
|
+
}
|
|
29
|
+
return { aggOptions, dbOptions, explain };
|
|
30
|
+
}
|
|
31
|
+
exports.adaptAggregateOptions = adaptAggregateOptions;
|
|
32
|
+
function validateExplainableVerbosity(verbosity) {
|
|
33
|
+
if (verbosity === true) {
|
|
34
|
+
verbosity = 'allPlansExecution';
|
|
35
|
+
}
|
|
36
|
+
else if (verbosity === false) {
|
|
37
|
+
verbosity = 'queryPlanner';
|
|
38
|
+
}
|
|
39
|
+
if (typeof verbosity !== 'string') {
|
|
40
|
+
throw new errors_1.MongoshInvalidInputError('verbosity must be a string', errors_1.CommonErrors.InvalidArgument);
|
|
41
|
+
}
|
|
42
|
+
return verbosity;
|
|
43
|
+
}
|
|
44
|
+
exports.validateExplainableVerbosity = validateExplainableVerbosity;
|
|
45
|
+
function getAssertCaller(caller) {
|
|
46
|
+
return caller ? ` (${caller})` : '';
|
|
47
|
+
}
|
|
48
|
+
function assertArgsDefinedType(args, expectedTypes, func) {
|
|
49
|
+
args.forEach((arg, i) => {
|
|
50
|
+
const expected = expectedTypes[i];
|
|
51
|
+
if (arg === undefined) {
|
|
52
|
+
if (expected !== true && Array.isArray(expected) && expected.includes(undefined)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
throw new errors_1.MongoshInvalidInputError(`Missing required argument at position ${i}${getAssertCaller(func)}`, errors_1.CommonErrors.InvalidArgument);
|
|
56
|
+
}
|
|
57
|
+
else if (expected === true) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const expectedTypesList = typeof expected === 'string' ? [expected] : expected;
|
|
61
|
+
const isExpectedTypeof = expectedTypesList.includes(typeof arg);
|
|
62
|
+
const isExpectedBson = expectedTypesList.includes(`bson:${arg === null || arg === void 0 ? void 0 : arg._bsontype}`);
|
|
63
|
+
if (!isExpectedTypeof && !isExpectedBson) {
|
|
64
|
+
const expectedMsg = expectedTypesList
|
|
65
|
+
.filter(e => e !== undefined)
|
|
66
|
+
.map(e => e === null || e === void 0 ? void 0 : e.replace(/^bson:/, ''))
|
|
67
|
+
.join(' or ');
|
|
68
|
+
throw new errors_1.MongoshInvalidInputError(`Argument at position ${i} must be of type ${expectedMsg}, got ${typeof arg} instead${getAssertCaller(func)}`, errors_1.CommonErrors.InvalidArgument);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
exports.assertArgsDefinedType = assertArgsDefinedType;
|
|
73
|
+
function assertKeysDefined(object, keys) {
|
|
74
|
+
for (const key of keys) {
|
|
75
|
+
if (object[key] === undefined) {
|
|
76
|
+
throw new errors_1.MongoshInvalidInputError(`Missing required property: ${JSON.stringify(key)}`, errors_1.CommonErrors.InvalidArgument);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.assertKeysDefined = assertKeysDefined;
|
|
81
|
+
function adaptOptions(shellToCommand, additions, shellDoc) {
|
|
82
|
+
return Object.keys(shellDoc).reduce((result, shellKey) => {
|
|
83
|
+
if (shellToCommand[shellKey] === null) {
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
result[shellToCommand[shellKey] || shellKey] = shellDoc[shellKey];
|
|
87
|
+
return result;
|
|
88
|
+
}, additions);
|
|
89
|
+
}
|
|
90
|
+
exports.adaptOptions = adaptOptions;
|
|
91
|
+
function processDigestPassword(username, passwordDigestor, command) {
|
|
92
|
+
if (passwordDigestor === undefined) {
|
|
93
|
+
return {};
|
|
94
|
+
}
|
|
95
|
+
if (passwordDigestor !== 'server' && passwordDigestor !== 'client') {
|
|
96
|
+
throw new errors_1.MongoshInvalidInputError(`Invalid field: passwordDigestor must be 'client' or 'server', got ${passwordDigestor}`, errors_1.CommonErrors.InvalidArgument);
|
|
97
|
+
}
|
|
98
|
+
if (passwordDigestor === 'client') {
|
|
99
|
+
if (typeof command.pwd !== 'string') {
|
|
100
|
+
throw new errors_1.MongoshInvalidInputError(`User passwords must be of type string. Was given password with type ${typeof command.pwd}`, errors_1.CommonErrors.InvalidArgument);
|
|
101
|
+
}
|
|
102
|
+
const hash = crypto_1.default.createHash('md5');
|
|
103
|
+
hash.update(`${username}:mongo:${command.pwd}`);
|
|
104
|
+
const digested = hash.digest('hex');
|
|
105
|
+
return { digestPassword: false, pwd: digested };
|
|
106
|
+
}
|
|
107
|
+
return { digestPassword: true };
|
|
108
|
+
}
|
|
109
|
+
exports.processDigestPassword = processDigestPassword;
|
|
110
|
+
async function getPrintableShardStatus(configDB, verbose) {
|
|
111
|
+
const result = {};
|
|
112
|
+
const mongosColl = configDB.getCollection('mongos');
|
|
113
|
+
const versionColl = configDB.getCollection('version');
|
|
114
|
+
const shardsColl = configDB.getCollection('shards');
|
|
115
|
+
const chunksColl = configDB.getCollection('chunks');
|
|
116
|
+
const settingsColl = configDB.getCollection('settings');
|
|
117
|
+
const changelogColl = configDB.getCollection('changelog');
|
|
118
|
+
const [version, shards, mostRecentMongos] = await Promise.all([
|
|
119
|
+
versionColl.findOne(),
|
|
120
|
+
shardsColl.find().then(cursor => cursor.sort({ _id: 1 }).toArray()),
|
|
121
|
+
mongosColl.find().then(cursor => cursor.sort({ ping: -1 }).limit(1).tryNext())
|
|
122
|
+
]);
|
|
123
|
+
if (version === null) {
|
|
124
|
+
throw new errors_1.MongoshInvalidInputError('This db does not have sharding enabled. Be sure you are connecting to a mongos from the shell and not to a mongod.', error_codes_1.ShellApiErrors.NotConnectedToMongos);
|
|
125
|
+
}
|
|
126
|
+
result.shardingVersion = version;
|
|
127
|
+
result.shards = shards;
|
|
128
|
+
const mongosActiveThresholdMs = 60000;
|
|
129
|
+
let mostRecentMongosTime = null;
|
|
130
|
+
let mongosAdjective = 'most recently active';
|
|
131
|
+
if (mostRecentMongos !== null) {
|
|
132
|
+
mostRecentMongosTime = mostRecentMongos.ping;
|
|
133
|
+
if (mostRecentMongosTime.getTime() >= Date.now() - mongosActiveThresholdMs) {
|
|
134
|
+
mongosAdjective = 'active';
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
mongosAdjective = `${mongosAdjective} mongoses`;
|
|
138
|
+
if (mostRecentMongosTime === null) {
|
|
139
|
+
result[mongosAdjective] = 'none';
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const recentMongosQuery = {
|
|
143
|
+
ping: {
|
|
144
|
+
$gt: (() => {
|
|
145
|
+
const d = mostRecentMongosTime;
|
|
146
|
+
d.setTime(d.getTime() - mongosActiveThresholdMs);
|
|
147
|
+
return d;
|
|
148
|
+
})()
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
if (verbose) {
|
|
152
|
+
result[mongosAdjective] = await (await mongosColl
|
|
153
|
+
.find(recentMongosQuery))
|
|
154
|
+
.sort({ ping: -1 })
|
|
155
|
+
.toArray();
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
result[mongosAdjective] = (await (await mongosColl.aggregate([
|
|
159
|
+
{ $match: recentMongosQuery },
|
|
160
|
+
{ $group: { _id: '$mongoVersion', num: { $sum: 1 } } },
|
|
161
|
+
{ $sort: { num: -1 } }
|
|
162
|
+
])).toArray()).map((z) => {
|
|
163
|
+
return { [z._id]: z.num };
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const balancerRes = {};
|
|
168
|
+
await Promise.all([
|
|
169
|
+
(async () => {
|
|
170
|
+
const autosplit = await settingsColl.findOne({ _id: 'autosplit' });
|
|
171
|
+
result.autosplit = { 'Currently enabled': autosplit === null || autosplit.enabled ? 'yes' : 'no' };
|
|
172
|
+
})(),
|
|
173
|
+
(async () => {
|
|
174
|
+
const balancerEnabled = await settingsColl.findOne({ _id: 'balancer' });
|
|
175
|
+
balancerRes['Currently enabled'] = balancerEnabled === null || !balancerEnabled.stopped ? 'yes' : 'no';
|
|
176
|
+
})(),
|
|
177
|
+
(async () => {
|
|
178
|
+
let balancerRunning = 'unknown';
|
|
179
|
+
try {
|
|
180
|
+
const balancerStatus = await configDB.adminCommand({ balancerStatus: 1 });
|
|
181
|
+
balancerRunning = balancerStatus.inBalancerRound ? 'yes' : 'no';
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
}
|
|
185
|
+
balancerRes['Currently running'] = balancerRunning;
|
|
186
|
+
})(),
|
|
187
|
+
(async () => {
|
|
188
|
+
const settings = await settingsColl.findOne({ _id: 'balancer' });
|
|
189
|
+
if (settings !== null && settings.hasOwnProperty('activeWindow')) {
|
|
190
|
+
const balSettings = settings.activeWindow;
|
|
191
|
+
balancerRes['Balancer active window is set between'] = `${balSettings.start} and ${balSettings.stop} server local time`;
|
|
192
|
+
}
|
|
193
|
+
})(),
|
|
194
|
+
(async () => {
|
|
195
|
+
const activeLocks = await (await configDB.getCollection('locks').find({ state: { $eq: 2 } })).toArray();
|
|
196
|
+
if ((activeLocks === null || activeLocks === void 0 ? void 0 : activeLocks.length) > 0) {
|
|
197
|
+
balancerRes['Collections with active migrations'] = activeLocks.map((lock) => {
|
|
198
|
+
return `${lock._id} started at ${lock.when}`;
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
})(),
|
|
202
|
+
(async () => {
|
|
203
|
+
let versionHasActionlog = false;
|
|
204
|
+
const metaDataVersion = version.currentVersion;
|
|
205
|
+
if (metaDataVersion > 5) {
|
|
206
|
+
versionHasActionlog = true;
|
|
207
|
+
}
|
|
208
|
+
if (metaDataVersion === 5) {
|
|
209
|
+
const verArray = (await configDB.serverBuildInfo()).versionArray;
|
|
210
|
+
if (verArray[0] === 2 && verArray[1] > 6) {
|
|
211
|
+
versionHasActionlog = true;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (versionHasActionlog) {
|
|
215
|
+
const balErrs = await (await configDB.getCollection('actionlog').find({ what: 'balancer.round' })).sort({ time: -1 }).limit(5).toArray();
|
|
216
|
+
const actionReport = { count: 0, lastErr: '', lastTime: ' ' };
|
|
217
|
+
if (balErrs !== null) {
|
|
218
|
+
balErrs.forEach((r) => {
|
|
219
|
+
if (r.details.errorOccured) {
|
|
220
|
+
actionReport.count += 1;
|
|
221
|
+
if (actionReport.count === 1) {
|
|
222
|
+
actionReport.lastErr = r.details.errmsg;
|
|
223
|
+
actionReport.lastTime = r.time;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
balancerRes['Failed balancer rounds in last 5 attempts'] = actionReport.count;
|
|
229
|
+
if (actionReport.count > 0) {
|
|
230
|
+
balancerRes['Last reported error'] = actionReport.lastErr;
|
|
231
|
+
balancerRes['Time of Reported error'] = actionReport.lastTime;
|
|
232
|
+
}
|
|
233
|
+
const yesterday = new Date();
|
|
234
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
235
|
+
let migrations = await (await changelogColl
|
|
236
|
+
.aggregate([
|
|
237
|
+
{
|
|
238
|
+
$match: {
|
|
239
|
+
time: { $gt: yesterday },
|
|
240
|
+
what: 'moveChunk.from',
|
|
241
|
+
'details.errmsg': { $exists: false },
|
|
242
|
+
'details.note': 'success'
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
{ $group: { _id: { msg: '$details.errmsg' }, count: { $sum: 1 } } },
|
|
246
|
+
{ $project: { _id: { $ifNull: ['$_id.msg', 'Success'] }, count: '$count' } }
|
|
247
|
+
]))
|
|
248
|
+
.toArray();
|
|
249
|
+
migrations = migrations.concat(await (await changelogColl
|
|
250
|
+
.aggregate([
|
|
251
|
+
{
|
|
252
|
+
$match: {
|
|
253
|
+
time: { $gt: yesterday },
|
|
254
|
+
what: 'moveChunk.from',
|
|
255
|
+
$or: [
|
|
256
|
+
{ 'details.errmsg': { $exists: true } },
|
|
257
|
+
{ 'details.note': { $ne: 'success' } }
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
$group: {
|
|
263
|
+
_id: { msg: '$details.errmsg', from: '$details.from', to: '$details.to' },
|
|
264
|
+
count: { $sum: 1 }
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
$project: {
|
|
269
|
+
_id: { $ifNull: ['$_id.msg', 'aborted'] },
|
|
270
|
+
from: '$_id.from',
|
|
271
|
+
to: '$_id.to',
|
|
272
|
+
count: '$count'
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
]))
|
|
276
|
+
.toArray());
|
|
277
|
+
const migrationsRes = {};
|
|
278
|
+
migrations.forEach((x) => {
|
|
279
|
+
if (x._id === 'Success') {
|
|
280
|
+
migrationsRes[x.count] = x._id;
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
migrationsRes[x.count] = `Failed with error '${x._id}', from ${x.from} to ${x.to}`;
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
if (migrations.length === 0) {
|
|
287
|
+
balancerRes['Migration Results for the last 24 hours'] = 'No recent migrations';
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
balancerRes['Migration Results for the last 24 hours'] = migrationsRes;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
})()
|
|
294
|
+
]);
|
|
295
|
+
result.balancer = balancerRes;
|
|
296
|
+
const dbRes = [];
|
|
297
|
+
result.databases = dbRes;
|
|
298
|
+
const databases = await (await configDB.getCollection('databases').find()).sort({ name: 1 }).toArray();
|
|
299
|
+
databases.push({ '_id': 'config', 'primary': 'config', 'partitioned': true });
|
|
300
|
+
databases.sort((a, b) => {
|
|
301
|
+
return a._id.localeCompare(b._id);
|
|
302
|
+
});
|
|
303
|
+
result.databases = await Promise.all(databases.map(async (db) => {
|
|
304
|
+
const escapeRegex = (string) => {
|
|
305
|
+
return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
306
|
+
};
|
|
307
|
+
const colls = await (await configDB.getCollection('collections')
|
|
308
|
+
.find({ _id: new RegExp('^' + escapeRegex(db._id) + '\\.') }))
|
|
309
|
+
.sort({ _id: 1 })
|
|
310
|
+
.toArray();
|
|
311
|
+
const collList = await Promise.all(colls.filter(coll => !coll.dropped).map(async (coll) => {
|
|
312
|
+
const collRes = {};
|
|
313
|
+
collRes.shardKey = coll.key;
|
|
314
|
+
collRes.unique = !!coll.unique;
|
|
315
|
+
if (typeof coll.unique !== 'boolean' && typeof coll.unique !== 'undefined') {
|
|
316
|
+
collRes.unique = [!!coll.unique, { unique: coll.unique }];
|
|
317
|
+
}
|
|
318
|
+
collRes.balancing = !coll.noBalance;
|
|
319
|
+
if (typeof coll.noBalance !== 'boolean' && typeof coll.noBalance !== 'undefined') {
|
|
320
|
+
collRes.balancing = [!coll.noBalance, { noBalance: coll.noBalance }];
|
|
321
|
+
}
|
|
322
|
+
const chunksRes = [];
|
|
323
|
+
const chunksCollMatch = coll.uuid ? { $or: [{ uuid: coll.uuid }, { ns: coll._id }] } : { ns: coll._id };
|
|
324
|
+
const chunks = await (await chunksColl.aggregate([
|
|
325
|
+
{ $match: chunksCollMatch },
|
|
326
|
+
{ $group: { _id: '$shard', cnt: { $sum: 1 } } },
|
|
327
|
+
{ $project: { _id: 0, shard: '$_id', nChunks: '$cnt' } },
|
|
328
|
+
{ $sort: { shard: 1 } }
|
|
329
|
+
])).toArray();
|
|
330
|
+
let totalChunks = 0;
|
|
331
|
+
collRes.chunkMetadata = [];
|
|
332
|
+
chunks.forEach((z) => {
|
|
333
|
+
totalChunks += z.nChunks;
|
|
334
|
+
collRes.chunkMetadata.push({ shard: z.shard, nChunks: z.nChunks });
|
|
335
|
+
});
|
|
336
|
+
if (totalChunks < 20 || verbose) {
|
|
337
|
+
for await (const chunk of (await chunksColl.find(chunksCollMatch)).sort({ min: 1 })) {
|
|
338
|
+
const c = {
|
|
339
|
+
min: chunk.min,
|
|
340
|
+
max: chunk.max,
|
|
341
|
+
'on shard': chunk.shard,
|
|
342
|
+
'last modified': chunk.lastmod
|
|
343
|
+
};
|
|
344
|
+
Object.defineProperty(c, Symbol.for('nodejs.util.inspect.custom'), {
|
|
345
|
+
value: function (depth, options) {
|
|
346
|
+
return (0, util_1.inspect)({ ...this }, { ...options, breakLength: Infinity });
|
|
347
|
+
},
|
|
348
|
+
writable: true,
|
|
349
|
+
configurable: true
|
|
350
|
+
});
|
|
351
|
+
if (chunk.jumbo)
|
|
352
|
+
c.jumbo = 'yes';
|
|
353
|
+
chunksRes.push(c);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
chunksRes.push('too many chunks to print, use verbose if you want to force print');
|
|
358
|
+
}
|
|
359
|
+
const tagsRes = [];
|
|
360
|
+
for await (const tag of (await configDB.getCollection('tags').find(chunksCollMatch)).sort({ min: 1 })) {
|
|
361
|
+
tagsRes.push({
|
|
362
|
+
tag: tag.tag,
|
|
363
|
+
min: tag.min,
|
|
364
|
+
max: tag.max
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
collRes.chunks = chunksRes;
|
|
368
|
+
collRes.tags = tagsRes;
|
|
369
|
+
return [coll._id, collRes];
|
|
370
|
+
}));
|
|
371
|
+
return { database: db, collections: Object.fromEntries(collList) };
|
|
372
|
+
}));
|
|
373
|
+
return result;
|
|
374
|
+
}
|
|
375
|
+
exports.getPrintableShardStatus = getPrintableShardStatus;
|
|
376
|
+
async function getConfigDB(db) {
|
|
377
|
+
const helloResult = await db._maybeCachedHello();
|
|
378
|
+
if (helloResult.msg !== 'isdbgrid') {
|
|
379
|
+
await db._instanceState.printWarning('MongoshWarning: [SHAPI-10003] You are not connected to a mongos. This command may not work as expected.');
|
|
380
|
+
}
|
|
381
|
+
return db.getSiblingDB('config');
|
|
382
|
+
}
|
|
383
|
+
exports.getConfigDB = getConfigDB;
|
|
384
|
+
function dataFormat(bytes) {
|
|
385
|
+
if (bytes === null || bytes === undefined) {
|
|
386
|
+
return '0B';
|
|
387
|
+
}
|
|
388
|
+
if (bytes < 1024) {
|
|
389
|
+
return Math.floor(bytes) + 'B';
|
|
390
|
+
}
|
|
391
|
+
if (bytes < 1024 * 1024) {
|
|
392
|
+
return Math.floor(bytes / 1024) + 'KiB';
|
|
393
|
+
}
|
|
394
|
+
if (bytes < 1024 * 1024 * 1024) {
|
|
395
|
+
return Math.floor((Math.floor(bytes / 1024) / 1024) * 100) / 100 + 'MiB';
|
|
396
|
+
}
|
|
397
|
+
return Math.floor((Math.floor(bytes / (1024 * 1024)) / 1024) * 100) / 100 + 'GiB';
|
|
398
|
+
}
|
|
399
|
+
exports.dataFormat = dataFormat;
|
|
400
|
+
function tsToSeconds(x) {
|
|
401
|
+
if (x.t && x.i) {
|
|
402
|
+
return x.t;
|
|
403
|
+
}
|
|
404
|
+
return x / 4294967296;
|
|
405
|
+
}
|
|
406
|
+
exports.tsToSeconds = tsToSeconds;
|
|
407
|
+
function addHiddenDataProperty(target, key, value) {
|
|
408
|
+
Object.defineProperty(target, key, {
|
|
409
|
+
value,
|
|
410
|
+
enumerable: false,
|
|
411
|
+
writable: true,
|
|
412
|
+
configurable: true
|
|
413
|
+
});
|
|
414
|
+
return target;
|
|
415
|
+
}
|
|
416
|
+
exports.addHiddenDataProperty = addHiddenDataProperty;
|
|
417
|
+
async function iterate(results, cursor, batchSize) {
|
|
418
|
+
if (cursor.isClosed()) {
|
|
419
|
+
return results;
|
|
420
|
+
}
|
|
421
|
+
for (let i = 0; i < batchSize; i++) {
|
|
422
|
+
const doc = await cursor.tryNext();
|
|
423
|
+
if (doc === null) {
|
|
424
|
+
results.cursorHasMore = false;
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
results.documents.push(doc);
|
|
428
|
+
}
|
|
429
|
+
return results;
|
|
430
|
+
}
|
|
431
|
+
exports.iterate = iterate;
|
|
432
|
+
function processFindAndModifyOptions(options) {
|
|
433
|
+
options = { ...options };
|
|
434
|
+
if ('returnDocument' in options) {
|
|
435
|
+
if (options.returnDocument !== 'before' && options.returnDocument !== 'after') {
|
|
436
|
+
throw new errors_1.MongoshInvalidInputError("returnDocument needs to be either 'before' or 'after'", errors_1.CommonErrors.InvalidArgument);
|
|
437
|
+
}
|
|
438
|
+
delete options.returnNewDocument;
|
|
439
|
+
delete options.returnOriginal;
|
|
440
|
+
return options;
|
|
441
|
+
}
|
|
442
|
+
if ('returnOriginal' in options) {
|
|
443
|
+
options.returnDocument = options.returnOriginal ? 'before' : 'after';
|
|
444
|
+
delete options.returnOriginal;
|
|
445
|
+
delete options.returnNewDocument;
|
|
446
|
+
return options;
|
|
447
|
+
}
|
|
448
|
+
if ('returnNewDocument' in options) {
|
|
449
|
+
options.returnDocument = options.returnNewDocument ? 'after' : 'before';
|
|
450
|
+
delete options.returnOriginal;
|
|
451
|
+
delete options.returnNewDocument;
|
|
452
|
+
return options;
|
|
453
|
+
}
|
|
454
|
+
if ('new' in options) {
|
|
455
|
+
options.returnDocument = options.new ? 'after' : 'before';
|
|
456
|
+
delete options.returnOriginal;
|
|
457
|
+
delete options.returnNewDocument;
|
|
458
|
+
return options;
|
|
459
|
+
}
|
|
460
|
+
options.returnDocument = 'before';
|
|
461
|
+
return options;
|
|
462
|
+
}
|
|
463
|
+
exports.processFindAndModifyOptions = processFindAndModifyOptions;
|
|
464
|
+
function processRemoveOptions(options) {
|
|
465
|
+
if (typeof options === 'boolean') {
|
|
466
|
+
return { justOne: options };
|
|
467
|
+
}
|
|
468
|
+
return { justOne: false, ...options };
|
|
469
|
+
}
|
|
470
|
+
exports.processRemoveOptions = processRemoveOptions;
|
|
471
|
+
function processMapReduceOptions(optionsOrOutString) {
|
|
472
|
+
if (typeof optionsOrOutString === 'string') {
|
|
473
|
+
return { out: optionsOrOutString };
|
|
474
|
+
}
|
|
475
|
+
else if (optionsOrOutString.out === undefined) {
|
|
476
|
+
throw new errors_1.MongoshInvalidInputError('Missing \'out\' option', errors_1.CommonErrors.InvalidArgument);
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
return optionsOrOutString;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
exports.processMapReduceOptions = processMapReduceOptions;
|
|
483
|
+
async function setHideIndex(coll, index, hidden) {
|
|
484
|
+
const cmd = typeof index === 'string' ? {
|
|
485
|
+
name: index, hidden
|
|
486
|
+
} : {
|
|
487
|
+
keyPattern: index, hidden
|
|
488
|
+
};
|
|
489
|
+
return await coll._database._runCommand({
|
|
490
|
+
collMod: coll._name,
|
|
491
|
+
index: cmd
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
exports.setHideIndex = setHideIndex;
|
|
495
|
+
function assertCLI(platform, features) {
|
|
496
|
+
if (platform !== service_provider_core_1.ReplPlatform.CLI) {
|
|
497
|
+
throw new errors_1.MongoshUnimplementedError(`${features} are not supported for current platform: ${service_provider_core_1.ReplPlatform[platform]}`, errors_1.CommonErrors.NotImplemented);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
exports.assertCLI = assertCLI;
|
|
501
|
+
function processFLEOptions(fleOptions) {
|
|
502
|
+
var _a, _b;
|
|
503
|
+
assertKeysDefined(fleOptions, ['keyVaultNamespace', 'kmsProviders']);
|
|
504
|
+
Object.keys(fleOptions).forEach(k => {
|
|
505
|
+
if (['keyVaultClient', 'keyVaultNamespace', 'kmsProviders', 'schemaMap', 'bypassAutoEncryption', 'tlsOptions'].indexOf(k) === -1) {
|
|
506
|
+
throw new errors_1.MongoshInvalidInputError(`Unrecognized FLE Client Option ${k}`);
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
const autoEncryption = {
|
|
510
|
+
keyVaultClient: (_a = fleOptions.keyVaultClient) === null || _a === void 0 ? void 0 : _a._serviceProvider.getRawClient(),
|
|
511
|
+
keyVaultNamespace: fleOptions.keyVaultNamespace
|
|
512
|
+
};
|
|
513
|
+
const localKey = (_b = fleOptions.kmsProviders.local) === null || _b === void 0 ? void 0 : _b.key;
|
|
514
|
+
if (localKey && localKey._bsontype === 'Binary') {
|
|
515
|
+
const rawBuff = localKey.value(true);
|
|
516
|
+
if (Buffer.isBuffer(rawBuff)) {
|
|
517
|
+
autoEncryption.kmsProviders = {
|
|
518
|
+
...fleOptions.kmsProviders,
|
|
519
|
+
local: {
|
|
520
|
+
key: rawBuff
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
|
+
throw new errors_1.MongoshInvalidInputError('When specifying the key of a local KMS as BSON binary it must be constructed from a base64 encoded string');
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
autoEncryption.kmsProviders = { ...fleOptions.kmsProviders };
|
|
530
|
+
}
|
|
531
|
+
if (fleOptions.schemaMap) {
|
|
532
|
+
autoEncryption.schemaMap = fleOptions.schemaMap;
|
|
533
|
+
}
|
|
534
|
+
if (fleOptions.bypassAutoEncryption !== undefined) {
|
|
535
|
+
autoEncryption.bypassAutoEncryption = fleOptions.bypassAutoEncryption;
|
|
536
|
+
}
|
|
537
|
+
if (fleOptions.tlsOptions !== undefined) {
|
|
538
|
+
autoEncryption.tlsOptions = fleOptions.tlsOptions;
|
|
539
|
+
}
|
|
540
|
+
return autoEncryption;
|
|
541
|
+
}
|
|
542
|
+
exports.processFLEOptions = processFLEOptions;
|
|
543
|
+
function maybeMarkAsExplainOutput(value, options) {
|
|
544
|
+
if ('explain' in options) {
|
|
545
|
+
return markAsExplainOutput(value);
|
|
546
|
+
}
|
|
547
|
+
return value;
|
|
548
|
+
}
|
|
549
|
+
exports.maybeMarkAsExplainOutput = maybeMarkAsExplainOutput;
|
|
550
|
+
function markAsExplainOutput(value) {
|
|
551
|
+
if (value !== null && typeof value === 'object') {
|
|
552
|
+
addHiddenDataProperty(value, enums_1.shellApiType, 'ExplainOutput');
|
|
553
|
+
}
|
|
554
|
+
return value;
|
|
555
|
+
}
|
|
556
|
+
exports.markAsExplainOutput = markAsExplainOutput;
|
|
557
|
+
function isValidDatabaseName(name) {
|
|
558
|
+
return !!name && !/[/\\. "\0]/.test(name);
|
|
559
|
+
}
|
|
560
|
+
exports.isValidDatabaseName = isValidDatabaseName;
|
|
561
|
+
function isValidCollectionName(name) {
|
|
562
|
+
return !!name && !/[$\0]/.test(name);
|
|
563
|
+
}
|
|
564
|
+
exports.isValidCollectionName = isValidCollectionName;
|
|
565
|
+
function shouldRunAggregationImmediately(pipeline) {
|
|
566
|
+
return pipeline.some(stage => Object.keys(stage).some(stageName => stageName === '$merge' || stageName === '$out'));
|
|
567
|
+
}
|
|
568
|
+
exports.shouldRunAggregationImmediately = shouldRunAggregationImmediately;
|
|
569
|
+
function isBSONDoubleConvertible(val) {
|
|
570
|
+
return (typeof val === 'number' && Number.isInteger(val)) || (val === null || val === void 0 ? void 0 : val._bsontype) === 'Int32';
|
|
571
|
+
}
|
|
572
|
+
function adjustRunCommand(cmd, shellBson) {
|
|
573
|
+
if (cmd.replSetResizeOplog) {
|
|
574
|
+
if ('size' in cmd && isBSONDoubleConvertible(cmd.size)) {
|
|
575
|
+
return adjustRunCommand({ ...cmd, size: new shellBson.Double(+cmd.size) }, shellBson);
|
|
576
|
+
}
|
|
577
|
+
if ('minRetentionHours' in cmd && isBSONDoubleConvertible(cmd.minRetentionHours)) {
|
|
578
|
+
return adjustRunCommand({ ...cmd, minRetentionHours: new shellBson.Double(+cmd.minRetentionHours) }, shellBson);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
if (cmd.profile) {
|
|
582
|
+
if ('sampleRate' in cmd && isBSONDoubleConvertible(cmd.sampleRate)) {
|
|
583
|
+
return adjustRunCommand({ ...cmd, sampleRate: new shellBson.Double(+cmd.sampleRate) }, shellBson);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
return cmd;
|
|
587
|
+
}
|
|
588
|
+
exports.adjustRunCommand = adjustRunCommand;
|
|
589
589
|
//# sourceMappingURL=helpers.js.map
|