@mongosh/service-provider-core 1.3.1 → 1.5.0

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/AUTHORS CHANGED
@@ -9,3 +9,4 @@ Sergey Petushkov <petushkov.sergey@gmail.com>
9
9
  Michael Rose <michael_rose@gmx.de>
10
10
  github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
11
11
  Alena Khineika <alena.khineika@gmail.com>
12
+ Leonardo Rossi <leonardo.rossi@gmail.com>
package/lib/index.d.ts CHANGED
@@ -2,8 +2,6 @@ import './textencoder-polyfill';
2
2
  import ServiceProvider, { ServiceProviderCore } from './service-provider';
3
3
  import getConnectInfo, { ConnectInfo } from './connect-info';
4
4
  import { ReplPlatform } from './platform';
5
- import CliOptions from './cli-options';
6
- import generateUri from './uri-generator';
7
5
  declare const DEFAULT_DB = "test";
8
6
  import { ObjectId, DBRef, MaxKey, MinKey, Timestamp, BSONSymbol, Code, Decimal128, Int32, Long, Binary, calculateObjectSize, Double, EJSON, BSONRegExp } from 'bson';
9
7
  import { bsonStringifiers } from './printable-bson';
@@ -28,4 +26,4 @@ declare const bson: {
28
26
  EJSON: typeof EJSON;
29
27
  BSONRegExp: typeof BSONRegExp;
30
28
  };
31
- export { ServiceProvider, ShellAuthOptions, getConnectInfo, ReplPlatform, CliOptions, generateUri, DEFAULT_DB, ServiceProviderCore, bson, bsonStringifiers, ConnectInfo };
29
+ export { ServiceProvider, ShellAuthOptions, getConnectInfo, ReplPlatform, DEFAULT_DB, ServiceProviderCore, bson, bsonStringifiers, ConnectInfo };
package/lib/index.js CHANGED
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
17
17
  return (mod && mod.__esModule) ? mod : { "default": mod };
18
18
  };
19
19
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.bsonStringifiers = exports.bson = exports.ServiceProviderCore = exports.DEFAULT_DB = exports.generateUri = exports.ReplPlatform = exports.getConnectInfo = void 0;
20
+ exports.bsonStringifiers = exports.bson = exports.ServiceProviderCore = exports.DEFAULT_DB = exports.ReplPlatform = exports.getConnectInfo = void 0;
21
21
  require("./textencoder-polyfill");
22
22
  const service_provider_1 = require("./service-provider");
23
23
  Object.defineProperty(exports, "ServiceProviderCore", { enumerable: true, get: function () { return service_provider_1.ServiceProviderCore; } });
@@ -25,8 +25,6 @@ const connect_info_1 = __importDefault(require("./connect-info"));
25
25
  exports.getConnectInfo = connect_info_1.default;
26
26
  const platform_1 = require("./platform");
27
27
  Object.defineProperty(exports, "ReplPlatform", { enumerable: true, get: function () { return platform_1.ReplPlatform; } });
28
- const uri_generator_1 = __importDefault(require("./uri-generator"));
29
- exports.generateUri = uri_generator_1.default;
30
28
  const DEFAULT_DB = 'test';
31
29
  exports.DEFAULT_DB = DEFAULT_DB;
32
30
  const bson_1 = require("bson");
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,kCAAgC;AAChC,yDAA0E;AAwDxE,oGAxDwB,sCAAmB,OAwDxB;AAvDrB,kEAA6D;AAkD3D,yBAlDK,sBAAc,CAkDL;AAjDhB,yCAA0C;AAkDxC,6FAlDO,uBAAY,OAkDP;AAhDd,oEAA0C;AAkDxC,sBAlDK,uBAAW,CAkDL;AAjDb,MAAM,UAAU,GAAG,MAAM,CAAC;AAkDxB,gCAAU;AAjDZ,+BAiBc;AACd,qDAAoD;AAkClD,iGAlCO,iCAAgB,OAkCP;AAhClB,wDAAsC;AACtC,kDAAgC;AAEhC,MAAM,IAAI,GAAG;IACX,QAAQ,EAAR,eAAQ;IACR,KAAK,EAAL,YAAK;IACL,MAAM,EAAN,aAAM;IACN,MAAM,EAAN,aAAM;IACN,SAAS,EAAT,gBAAS;IACT,UAAU,EAAV,iBAAU;IACV,IAAI,EAAJ,WAAI;IACJ,UAAU,EAAV,iBAAU;IACV,KAAK,EAAL,YAAK;IACL,IAAI,EAAJ,WAAI;IACJ,MAAM,EAAN,aAAM;IACN,GAAG,EAAH,UAAG;IACH,mBAAmB,EAAnB,0BAAmB;IACnB,MAAM,EAAN,aAAM;IACN,KAAK,EAAL,YAAK;IACL,UAAU,EAAV,iBAAU;CACX,CAAC;AAWA,oBAAI"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,kCAAgC;AAChC,yDAA0E;AAoDxE,oGApDwB,sCAAmB,OAoDxB;AAnDrB,kEAA6D;AAgD3D,yBAhDK,sBAAc,CAgDL;AA/ChB,yCAA0C;AAgDxC,6FAhDO,uBAAY,OAgDP;AA/Cd,MAAM,UAAU,GAAG,MAAM,CAAC;AAgDxB,gCAAU;AA/CZ,+BAiBc;AACd,qDAAoD;AAgClD,iGAhCO,iCAAgB,OAgCP;AA9BlB,wDAAsC;AACtC,kDAAgC;AAEhC,MAAM,IAAI,GAAG;IACX,QAAQ,EAAR,eAAQ;IACR,KAAK,EAAL,YAAK;IACL,MAAM,EAAN,aAAM;IACN,MAAM,EAAN,aAAM;IACN,SAAS,EAAT,gBAAS;IACT,UAAU,EAAV,iBAAU;IACV,IAAI,EAAJ,WAAI;IACJ,UAAU,EAAV,iBAAU;IACV,KAAK,EAAL,YAAK;IACL,IAAI,EAAJ,WAAI;IACJ,MAAM,EAAN,aAAM;IACN,GAAG,EAAH,UAAG;IACH,mBAAmB,EAAnB,0BAAmB;IACnB,MAAM,EAAN,aAAM;IACN,KAAK,EAAL,YAAK;IACL,UAAU,EAAV,iBAAU;CACX,CAAC;AASA,oBAAI"}
package/lib/readable.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Document, AggregateOptions, CountOptions, CountDocumentsOptions, DistinctOptions, EstimatedDocumentCountOptions, FindOptions, ListCollectionsOptions, CollStatsOptions, ListIndexesOptions, AggregationCursor, FindCursor, DbOptions, ReadPreferenceFromOptions, ReadPreferenceLike } from './all-transport-types';
1
+ import type { Document, AggregateOptions, CountOptions, CountDocumentsOptions, DistinctOptions, EstimatedDocumentCountOptions, FindOptions, ListCollectionsOptions, ListIndexesOptions, AggregationCursor, FindCursor, DbOptions, ReadPreferenceFromOptions, ReadPreferenceLike } from './all-transport-types';
2
2
  import { ChangeStream, ChangeStreamOptions } from './all-transport-types';
3
3
  export default interface Readable {
4
4
  aggregate(database: string, collection: string, pipeline: Document[], options?: AggregateOptions, dbOptions?: DbOptions): AggregationCursor;
@@ -9,10 +9,8 @@ export default interface Readable {
9
9
  estimatedDocumentCount(database: string, collection: string, options?: EstimatedDocumentCountOptions, dbOptions?: DbOptions): Promise<number>;
10
10
  find(database: string, collection: string, filter?: Document, options?: FindOptions, dbOptions?: DbOptions): FindCursor;
11
11
  getTopology(): any;
12
- isCapped(database: string, collection: string, dbOptions?: DbOptions): Promise<boolean>;
13
12
  getIndexes(database: string, collection: string, options: ListIndexesOptions, dbOptions?: DbOptions): Promise<Document[]>;
14
13
  listCollections(database: string, filter?: Document, options?: ListCollectionsOptions, dbOptions?: DbOptions): Promise<Document[]>;
15
14
  readPreferenceFromOptions(options?: Omit<ReadPreferenceFromOptions, 'session'>): ReadPreferenceLike | undefined;
16
- stats(database: string, collection: string, options?: CollStatsOptions, dbOptions?: DbOptions): Promise<Document>;
17
15
  watch(pipeline: Document[], options: ChangeStreamOptions, dbOptions?: DbOptions, db?: string, coll?: string): ChangeStream<Document>;
18
16
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mongosh/service-provider-core",
3
- "version": "1.3.1",
3
+ "version": "1.5.0",
4
4
  "description": "MongoDB Shell Core Service Provider Package",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -24,21 +24,27 @@
24
24
  "access": "public"
25
25
  },
26
26
  "engines": {
27
- "node": ">=12.4.0"
27
+ "node": ">=14.15.1"
28
28
  },
29
29
  "mongosh": {
30
- "unitTestsOnly": true
30
+ "unitTestsOnly": true,
31
+ "ciRequiredOptionalDependencies": {
32
+ "mongodb-client-encryption": [
33
+ "darwin",
34
+ "linux",
35
+ "win32"
36
+ ]
37
+ }
31
38
  },
32
39
  "dependencies": {
33
- "@mongosh/errors": "1.3.1",
34
- "@mongosh/i18n": "1.3.1",
35
- "bson": "^4.6.1",
36
- "mongodb": "^4.4.0",
40
+ "@mongosh/errors": "1.5.0",
41
+ "bson": "^4.6.2",
42
+ "mongodb": "^4.6.0",
37
43
  "mongodb-build-info": "^1.2.0",
38
- "mongodb-connection-string-url": "^2.3.2"
44
+ "mongodb-client-encryption": "^2.2.0-alpha.1"
39
45
  },
40
46
  "optionalDependencies": {
41
- "mongodb-client-encryption": "^2.0.0"
47
+ "mongodb-client-encryption": "^2.2.0-alpha.1"
42
48
  },
43
49
  "dependency-check": {
44
50
  "entries": [
@@ -51,5 +57,5 @@
51
57
  "encoding"
52
58
  ]
53
59
  },
54
- "gitHead": "29a1453899120580f7ee669ec5952810b86d11b7"
60
+ "gitHead": "78a16fa4cbd0c5d98ca8131aa2896be5845aa919"
55
61
  }
package/src/index.ts CHANGED
@@ -2,8 +2,6 @@ import './textencoder-polyfill'; // for mongodb-connection-string-url in the jav
2
2
  import ServiceProvider, { ServiceProviderCore } from './service-provider';
3
3
  import getConnectInfo, { ConnectInfo } from './connect-info';
4
4
  import { ReplPlatform } from './platform';
5
- import CliOptions from './cli-options';
6
- import generateUri from './uri-generator';
7
5
  const DEFAULT_DB = 'test';
8
6
  import {
9
7
  ObjectId,
@@ -52,8 +50,6 @@ export {
52
50
  ShellAuthOptions,
53
51
  getConnectInfo,
54
52
  ReplPlatform,
55
- CliOptions,
56
- generateUri,
57
53
  DEFAULT_DB,
58
54
  ServiceProviderCore,
59
55
  bson,
package/src/readable.ts CHANGED
@@ -7,7 +7,6 @@ import type {
7
7
  EstimatedDocumentCountOptions,
8
8
  FindOptions,
9
9
  ListCollectionsOptions,
10
- CollStatsOptions,
11
10
  ListIndexesOptions,
12
11
  AggregationCursor,
13
12
  FindCursor,
@@ -154,20 +153,6 @@ export default interface Readable {
154
153
  */
155
154
  getTopology(): any;
156
155
 
157
- /**
158
- * Is the collection capped?
159
- *
160
- * @param {String} database - The database name.
161
- * @param {String} collection - The collection name.
162
- * @param {DbOptions} dbOptions - The database options
163
- *
164
- * @returns {Promise} The promise of the result.
165
- */
166
- isCapped(
167
- database: string,
168
- collection: string,
169
- dbOptions?: DbOptions): Promise<boolean>;
170
-
171
156
  /**
172
157
  * Returns an array that holds a list of documents that identify and
173
158
  * describe the existing indexes on the collection.
@@ -206,23 +191,6 @@ export default interface Readable {
206
191
  */
207
192
  readPreferenceFromOptions(options?: Omit<ReadPreferenceFromOptions, 'session'>): ReadPreferenceLike | undefined;
208
193
 
209
- /**
210
- * Get all the collection statistics.
211
- *
212
- * @param {String} database - The db name.
213
- * @param {String} collection - The collection name.
214
- * @param {Object} options - The count options.
215
- * @param {DbOptions} dbOptions - The database options
216
- *
217
- * @return {Promise} returns Promise
218
- */
219
- stats(
220
- database: string,
221
- collection: string,
222
- options?: CollStatsOptions,
223
- dbOptions?: DbOptions
224
- ): Promise<Document>;
225
-
226
194
  /**
227
195
  * Start a change stream cursor on either the client, db, or collection.
228
196
  * @param pipeline
@@ -1,43 +0,0 @@
1
- export default interface CliOptions {
2
- connectionSpecifier?: string;
3
- fileNames?: string[];
4
- apiDeprecationErrors?: boolean;
5
- apiStrict?: boolean;
6
- apiVersion?: string;
7
- authenticationDatabase?: string;
8
- authenticationMechanism?: string;
9
- awsAccessKeyId?: string;
10
- awsIamSessionToken?: string;
11
- awsSecretAccessKey?: string;
12
- awsSessionToken?: string;
13
- db?: string;
14
- eval?: string;
15
- gssapiServiceName?: string;
16
- sspiHostnameCanonicalization?: string;
17
- sspiRealmOverride?: string;
18
- help?: boolean;
19
- host?: string;
20
- ipv6?: boolean;
21
- keyVaultNamespace?: string;
22
- kmsURL?: string;
23
- nodb?: boolean;
24
- norc?: boolean;
25
- password?: string;
26
- port?: string;
27
- quiet?: boolean;
28
- retryWrites?: boolean;
29
- shell?: boolean;
30
- tls?: boolean;
31
- tlsAllowInvalidCertificates?: boolean;
32
- tlsAllowInvalidHostnames?: boolean;
33
- tlsCAFile?: string;
34
- tlsCertificateKeyFile?: string;
35
- tlsCertificateKeyFilePassword?: string;
36
- tlsCertificateSelector?: string;
37
- tlsCRLFile?: string;
38
- tlsDisabledProtocols?: boolean;
39
- tlsFIPSMode?: boolean;
40
- username?: string;
41
- verbose?: boolean;
42
- version?: boolean;
43
- }
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=cli-options.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli-options.js","sourceRoot":"","sources":["../src/cli-options.ts"],"names":[],"mappings":""}
@@ -1,8 +0,0 @@
1
- import CliOptions from './cli-options';
2
- declare enum Scheme {
3
- Mongo = "mongodb://",
4
- MongoSrv = "mongodb+srv://"
5
- }
6
- declare function generateUri(options: CliOptions): string;
7
- export default generateUri;
8
- export { Scheme };
@@ -1,176 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.Scheme = void 0;
30
- const errors_1 = require("@mongosh/errors");
31
- const i18n_1 = __importDefault(require("@mongosh/i18n"));
32
- const mongodb_connection_string_url_1 = __importStar(require("mongodb-connection-string-url"));
33
- const index_1 = require("./index");
34
- var Scheme;
35
- (function (Scheme) {
36
- Scheme["Mongo"] = "mongodb://";
37
- Scheme["MongoSrv"] = "mongodb+srv://";
38
- })(Scheme || (Scheme = {}));
39
- exports.Scheme = Scheme;
40
- const DEFAULT_HOST = '127.0.0.1';
41
- const DEFAULT_PORT = '27017';
42
- const CONFLICT = 'cli-repl.uri-generator.no-host-port';
43
- const INVALID_HOST = 'cli-repl.uri-generator.invalid-host';
44
- const HOST_LIST_PORT_MISMATCH = 'cli-repl.uri-generator.host-list-port-mismatch';
45
- const DIVERGING_SERVICE_NAME = 'cli-repl.uri-generator.diverging-service-name';
46
- const GSSAPI_SERVICE_NAME_UNSUPPORTED = 'cli-repl.uri-generator.gssapi-service-name-unsupported';
47
- function validateConflicts(options, connectionString) {
48
- if (options.host || options.port) {
49
- throw new errors_1.MongoshInvalidInputError(i18n_1.default.__(CONFLICT), errors_1.CommonErrors.InvalidArgument);
50
- }
51
- if (options.gssapiServiceName && (connectionString === null || connectionString === void 0 ? void 0 : connectionString.searchParams.has('authMechanismProperties'))) {
52
- const authProperties = new mongodb_connection_string_url_1.CommaAndColonSeparatedRecord(connectionString.searchParams.get('authMechanismProperties'));
53
- const serviceName = authProperties.get('SERVICE_NAME');
54
- if (serviceName !== undefined && options.gssapiServiceName !== serviceName) {
55
- throw new errors_1.MongoshInvalidInputError(i18n_1.default.__(DIVERGING_SERVICE_NAME), errors_1.CommonErrors.InvalidArgument);
56
- }
57
- }
58
- if (connectionString === null || connectionString === void 0 ? void 0 : connectionString.searchParams.has('gssapiServiceName')) {
59
- throw new errors_1.MongoshInvalidInputError(i18n_1.default.__(GSSAPI_SERVICE_NAME_UNSUPPORTED), errors_1.CommonErrors.InvalidArgument);
60
- }
61
- }
62
- function validateHost(host) {
63
- const invalidCharacter = host.match(/[^a-zA-Z0-9.:\[\]_-]/);
64
- if (invalidCharacter) {
65
- throw new errors_1.MongoshInvalidInputError(i18n_1.default.__(INVALID_HOST) + ': ' + invalidCharacter[0], errors_1.CommonErrors.InvalidArgument);
66
- }
67
- }
68
- function validateHostSeedList(hosts, fixedPort) {
69
- const trimmedHosts = hosts.split(',').map(h => h.trim()).filter(h => !!h);
70
- const hostList = [];
71
- trimmedHosts.forEach(h => {
72
- const [host, port] = h.split(':');
73
- if (fixedPort && port !== undefined && port !== fixedPort) {
74
- throw new errors_1.MongoshInvalidInputError(i18n_1.default.__(HOST_LIST_PORT_MISMATCH), errors_1.CommonErrors.InvalidArgument);
75
- }
76
- hostList.push(`${host}${(port || fixedPort) ? ':' + (port || fixedPort) : ''}`);
77
- });
78
- return hostList;
79
- }
80
- function generateHost(options) {
81
- if (options.host) {
82
- validateHost(options.host);
83
- if (options.host.includes(':')) {
84
- return options.host.split(':')[0];
85
- }
86
- return options.host;
87
- }
88
- return DEFAULT_HOST;
89
- }
90
- function generatePort(options) {
91
- if (options.host && options.host.includes(':')) {
92
- validateHost(options.host);
93
- const port = options.host.split(':')[1];
94
- if (!options.port || options.port === port) {
95
- return port;
96
- }
97
- throw new errors_1.MongoshInvalidInputError(i18n_1.default.__(CONFLICT), errors_1.CommonErrors.InvalidArgument);
98
- }
99
- return options.port ? options.port : DEFAULT_PORT;
100
- }
101
- function generateUri(options) {
102
- if (options.nodb) {
103
- return '';
104
- }
105
- const connectionString = generateUriNormalized(options);
106
- if (connectionString.hosts.every(host => ['localhost', '127.0.0.1'].includes(host.split(':')[0]))) {
107
- const params = connectionString.searchParams;
108
- if (!params.has('serverSelectionTimeoutMS')) {
109
- params.set('serverSelectionTimeoutMS', '2000');
110
- }
111
- }
112
- return connectionString.toString();
113
- }
114
- function generateUriNormalized(options) {
115
- var _a, _b, _c;
116
- const uri = options.connectionSpecifier;
117
- const replSetHostMatch = ((_a = options.host) !== null && _a !== void 0 ? _a : '').match(/^(?<replSetName>[^/]+)\/(?<hosts>([A-Za-z0-9._-]+(:\d+)?,?)+)$/);
118
- if (replSetHostMatch) {
119
- const { replSetName, hosts } = replSetHostMatch.groups;
120
- const connectionString = new mongodb_connection_string_url_1.default(`${Scheme.Mongo}replacemeHost/${encodeURIComponent(uri || '')}`);
121
- connectionString.hosts = validateHostSeedList(hosts, options.port);
122
- connectionString.searchParams.set('replicaSet', replSetName);
123
- return addShellConnectionStringParameters(connectionString);
124
- }
125
- const seedList = ((_b = options.host) !== null && _b !== void 0 ? _b : '').match(/^(?<hosts>([A-Za-z0-9._-]+(:\d+)?,?)+)$/);
126
- if (seedList && ((_c = options.host) === null || _c === void 0 ? void 0 : _c.includes(','))) {
127
- const { hosts } = seedList.groups;
128
- const connectionString = new mongodb_connection_string_url_1.default(`${Scheme.Mongo}replacemeHost/${encodeURIComponent(uri || '')}`);
129
- connectionString.hosts = validateHostSeedList(hosts, options.port);
130
- return addShellConnectionStringParameters(connectionString);
131
- }
132
- if (!uri) {
133
- return new mongodb_connection_string_url_1.default(`${Scheme.Mongo}${generateHost(options)}:${generatePort(options)}/?directConnection=true`);
134
- }
135
- if (uri.startsWith(Scheme.MongoSrv)) {
136
- const connectionString = new mongodb_connection_string_url_1.default(uri);
137
- validateConflicts(options, connectionString);
138
- return connectionString;
139
- }
140
- else if (uri.startsWith(Scheme.Mongo)) {
141
- const connectionString = new mongodb_connection_string_url_1.default(uri);
142
- validateConflicts(options, connectionString);
143
- return addShellConnectionStringParameters(connectionString);
144
- }
145
- const uriMatch = /^([A-Za-z0-9][A-Za-z0-9._-]+):?(\d+)?(?:\/(\S*))?$/gi;
146
- let parts = uriMatch.exec(uri);
147
- if (parts === null) {
148
- if (/[/\\. "$]/.test(uri)) {
149
- throw new errors_1.MongoshInvalidInputError(`Invalid URI: ${uri}`, errors_1.CommonErrors.InvalidArgument);
150
- }
151
- else {
152
- parts = [uri, uri];
153
- }
154
- }
155
- let host = parts === null || parts === void 0 ? void 0 : parts[1];
156
- const port = parts === null || parts === void 0 ? void 0 : parts[2];
157
- let dbAndQueryString = parts === null || parts === void 0 ? void 0 : parts[3];
158
- if (!port && !dbAndQueryString && host.indexOf('.') < 0) {
159
- dbAndQueryString = host;
160
- host = undefined;
161
- }
162
- if (host || port) {
163
- validateConflicts(options);
164
- }
165
- return addShellConnectionStringParameters(new mongodb_connection_string_url_1.default(`${Scheme.Mongo}${host || generateHost(options)}:${port || generatePort(options)}/${encodeURIComponent(dbAndQueryString || index_1.DEFAULT_DB)}`));
166
- }
167
- function addShellConnectionStringParameters(uri) {
168
- uri = uri.clone();
169
- const params = uri.searchParams;
170
- if (!params.has('replicaSet') && !params.has('directConnection') && !params.has('loadBalanced') && uri.hosts.length === 1) {
171
- params.set('directConnection', 'true');
172
- }
173
- return uri;
174
- }
175
- exports.default = generateUri;
176
- //# sourceMappingURL=uri-generator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"uri-generator.js","sourceRoot":"","sources":["../src/uri-generator.ts"],"names":[],"mappings":"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"}
@@ -1,49 +0,0 @@
1
- /**
2
- * Valid options that can be parsed from the command line.
3
- */
4
- export default interface CliOptions {
5
- // Positional arguments:
6
- connectionSpecifier?: string;
7
- fileNames?: string[];
8
-
9
- // Non-positional arguments:
10
- apiDeprecationErrors?: boolean;
11
- apiStrict?: boolean;
12
- apiVersion?: string;
13
- authenticationDatabase?: string;
14
- authenticationMechanism?: string;
15
- awsAccessKeyId?: string;
16
- awsIamSessionToken?: string;
17
- awsSecretAccessKey?: string;
18
- awsSessionToken?: string;
19
- db?: string;
20
- eval?: string;
21
- gssapiServiceName?: string;
22
- sspiHostnameCanonicalization?: string;
23
- sspiRealmOverride?: string;
24
- help?: boolean;
25
- host?: string;
26
- ipv6?: boolean;
27
- keyVaultNamespace?: string;
28
- kmsURL?: string;
29
- nodb?: boolean;
30
- norc?: boolean;
31
- password?: string;
32
- port?: string;
33
- quiet?: boolean;
34
- retryWrites?: boolean;
35
- shell?: boolean;
36
- tls?: boolean;
37
- tlsAllowInvalidCertificates?: boolean;
38
- tlsAllowInvalidHostnames?: boolean;
39
- tlsCAFile?: string;
40
- tlsCertificateKeyFile?: string;
41
- tlsCertificateKeyFilePassword?: string;
42
- tlsCertificateSelector?: string;
43
- tlsCRLFile?: string;
44
- tlsDisabledProtocols?: boolean;
45
- tlsFIPSMode?: boolean;
46
- username?: string;
47
- verbose?: boolean;
48
- version?: boolean;
49
- }
@@ -1,481 +0,0 @@
1
- import { CommonErrors, MongoshInvalidInputError } from '@mongosh/errors';
2
- import { expect } from 'chai';
3
- import CliOptions from './cli-options';
4
- import generateUri from './uri-generator';
5
-
6
- describe('uri-generator.generate-uri', () => {
7
- context('when no arguments are provided', () => {
8
- const options = { connectionSpecifier: undefined };
9
-
10
- it('returns the default uri', () => {
11
- expect(generateUri(options)).to.equal('mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000');
12
- });
13
- });
14
-
15
- context('when no URI is provided', () => {
16
- it('handles host', () => {
17
- expect(generateUri({ connectionSpecifier: undefined, host: 'localhost' })).to.equal('mongodb://localhost:27017/?directConnection=true&serverSelectionTimeoutMS=2000');
18
- });
19
- it('handles port', () => {
20
- expect(generateUri({ connectionSpecifier: undefined, port: '27018' })).to.equal('mongodb://127.0.0.1:27018/?directConnection=true&serverSelectionTimeoutMS=2000');
21
- });
22
- it('handles both host and port', () => {
23
- expect(generateUri({ connectionSpecifier: undefined, host: 'localhost', port: '27018' })).to.equal('mongodb://localhost:27018/?directConnection=true&serverSelectionTimeoutMS=2000');
24
- });
25
- it('handles host with port included', () => {
26
- expect(generateUri({ connectionSpecifier: undefined, host: 'localhost:27018' })).to.equal('mongodb://localhost:27018/?directConnection=true&serverSelectionTimeoutMS=2000');
27
- });
28
- it('handles host with an underscore', () => {
29
- expect(generateUri({ connectionSpecifier: undefined, host: 'some_host' })).to.equal('mongodb://some_host:27017/?directConnection=true');
30
- });
31
- it('throws if host has port AND port set to other value', () => {
32
- try {
33
- generateUri({ connectionSpecifier: undefined, host: 'localhost:27018', port: '27019' });
34
- expect.fail('expected error');
35
- } catch (e: any) {
36
- expect(e).to.be.instanceOf(MongoshInvalidInputError);
37
- expect(e.code).to.equal(CommonErrors.InvalidArgument);
38
- }
39
- });
40
- it('handles host has port AND port set to equal value', () => {
41
- expect(generateUri({ connectionSpecifier: undefined, host: 'localhost:27018', port: '27018' })).to.equal('mongodb://localhost:27018/?directConnection=true&serverSelectionTimeoutMS=2000');
42
- });
43
- });
44
-
45
- context('when a full URI is provided', () => {
46
- context('when no additional options are provided', () => {
47
- const options = { connectionSpecifier: 'mongodb://192.0.0.1:27018/foo' };
48
-
49
- it('returns the uri', () => {
50
- expect(generateUri(options)).to.equal('mongodb://192.0.0.1:27018/foo?directConnection=true');
51
- });
52
- });
53
-
54
- context('when additional options are provided', () => {
55
- context('when providing host with URI', () => {
56
- const uri = 'mongodb://192.0.0.1:27018/foo';
57
- const options = { connectionSpecifier: uri, host: '127.0.0.1' };
58
-
59
- it('throws an exception', () => {
60
- try {
61
- generateUri(options);
62
- expect.fail('expected error');
63
- } catch (e: any) {
64
- expect(e).to.be.instanceOf(MongoshInvalidInputError);
65
- expect(e.code).to.equal(CommonErrors.InvalidArgument);
66
- }
67
- });
68
- });
69
-
70
- context('when providing port with URI', () => {
71
- const uri = 'mongodb://192.0.0.1:27018/foo';
72
- const options = { connectionSpecifier: uri, port: '27018' };
73
-
74
- it('throws an exception', () => {
75
- try {
76
- generateUri(options);
77
- expect.fail('expected error');
78
- } catch (e: any) {
79
- expect(e.name).to.equal('MongoshInvalidInputError');
80
- expect(e.code).to.equal(CommonErrors.InvalidArgument);
81
- }
82
- });
83
- });
84
-
85
- context('when providing gssapiServiceName', () => {
86
- context('and the URI does not include SERVICE_NAME in authMechanismProperties', () => {
87
- const uri = 'mongodb+srv://some.host/foo';
88
- const options: CliOptions = { connectionSpecifier: uri, gssapiServiceName: 'alternate' };
89
-
90
- it('does not throw an error', () => {
91
- expect(generateUri(options)).to.equal('mongodb+srv://some.host/foo');
92
- });
93
- });
94
-
95
- context('and the URI includes SERVICE_NAME in authMechanismProperties', () => {
96
- const uri = 'mongodb+srv://some.host/foo?authMechanismProperties=SERVICE_NAME:whatever';
97
- const options: CliOptions = { connectionSpecifier: uri, gssapiServiceName: 'alternate' };
98
-
99
- it('throws an error', () => {
100
- try {
101
- generateUri(options);
102
- } catch (e: any) {
103
- expect(e.name).to.equal('MongoshInvalidInputError');
104
- expect(e.code).to.equal(CommonErrors.InvalidArgument);
105
- expect(e.message).to.contain('--gssapiServiceName parameter or the SERVICE_NAME');
106
- return;
107
- }
108
- expect.fail('expected error');
109
- });
110
- });
111
- });
112
- });
113
-
114
- context('when providing a URI with query parameters', () => {
115
- context('that do not conflict with directConnection', () => {
116
- const uri = 'mongodb://192.0.0.1:27018?readPreference=primary';
117
- const options = { connectionSpecifier: uri };
118
- it('still includes directConnection', () => {
119
- expect(generateUri(options)).to.equal('mongodb://192.0.0.1:27018/?readPreference=primary&directConnection=true');
120
- });
121
- });
122
-
123
- context('including replicaSet', () => {
124
- const uri = 'mongodb://192.0.0.1:27018/db?replicaSet=replicaset';
125
- const options = { connectionSpecifier: uri };
126
- it('does not add the directConnection parameter', () => {
127
- expect(generateUri(options)).to.equal(uri);
128
- });
129
- });
130
-
131
- context('including loadBalanced', () => {
132
- const uri = 'mongodb://192.0.0.1:27018/db?loadBalanced=true';
133
- const options = { connectionSpecifier: uri };
134
- it('does not add the directConnection parameter', () => {
135
- expect(generateUri(options)).to.equal(uri);
136
- });
137
- });
138
-
139
- context('including explicit directConnection', () => {
140
- const uri = 'mongodb://192.0.0.1:27018/db?directConnection=false';
141
- const options = { connectionSpecifier: uri };
142
- it('does not change the directConnection parameter', () => {
143
- expect(generateUri(options)).to.equal(uri);
144
- });
145
- });
146
- });
147
-
148
- context('when providing a URI with SRV record', () => {
149
- const uri = 'mongodb+srv://somehost/?readPreference=primary';
150
- const options = { connectionSpecifier: uri };
151
- it('no directConnection is added', () => {
152
- expect(generateUri(options)).to.equal(uri);
153
- });
154
- });
155
-
156
- context('when providing a URI with multiple seeds', () => {
157
- const uri = 'mongodb://192.42.42.42:27017,192.0.0.1:27018/db?readPreference=primary';
158
- const options = { connectionSpecifier: uri };
159
- it('no directConnection is added', () => {
160
- expect(generateUri(options)).to.equal(uri);
161
- });
162
- });
163
-
164
- context('when providing a URI with the legacy gssapiServiceName query parameter', () => {
165
- const uri = 'mongodb://192.42.42.42:27017,192.0.0.1:27018/db?gssapiServiceName=primary';
166
- const options = { connectionSpecifier: uri };
167
-
168
- it('throws an error', () => {
169
- try {
170
- generateUri(options);
171
- } catch (e: any) {
172
- expect(e.name).to.equal('MongoshInvalidInputError');
173
- expect(e.code).to.equal(CommonErrors.InvalidArgument);
174
- expect(e.message).to.contain('gssapiServiceName query parameter is not supported');
175
- return;
176
- }
177
- expect.fail('expected error');
178
- });
179
- });
180
- });
181
-
182
- context('when a URI is provided without a scheme', () => {
183
- context('when providing host', () => {
184
- const uri = '192.0.0.1';
185
- const options = { connectionSpecifier: uri };
186
-
187
- it('returns the uri with the scheme', () => {
188
- expect(generateUri(options)).to.equal(`mongodb://${uri}:27017/test?directConnection=true`);
189
- });
190
- });
191
-
192
- context('when providing host:port', () => {
193
- const uri = '192.0.0.1:27018';
194
- const options = { connectionSpecifier: uri };
195
-
196
- it('returns the uri with the scheme', () => {
197
- expect(generateUri(options)).to.equal(`mongodb://${uri}/test?directConnection=true`);
198
- });
199
- });
200
-
201
- context('when proving host + port option', () => {
202
- const uri = '192.0.0.1';
203
- const options = { connectionSpecifier: uri, port: '27018' };
204
-
205
- it('throws an exception', () => {
206
- try {
207
- generateUri(options);
208
- expect.fail('expected error');
209
- } catch (e: any) {
210
- expect(e).to.be.instanceOf(MongoshInvalidInputError);
211
- expect(e.code).to.equal(CommonErrors.InvalidArgument);
212
- }
213
- });
214
- });
215
-
216
- context('when no additional options are provided without db', () => {
217
- const uri = '192.0.0.1:27018';
218
- const options = { connectionSpecifier: uri };
219
-
220
- it('returns the uri with the scheme', () => {
221
- expect(generateUri(options)).to.equal(`mongodb://${uri}/test?directConnection=true`);
222
- });
223
- });
224
-
225
- context('when no additional options are provided with empty db', () => {
226
- const uri = '192.0.0.1:27018/';
227
- const options = { connectionSpecifier: uri };
228
-
229
- it('returns the uri with the scheme', () => {
230
- expect(generateUri(options)).to.equal(`mongodb://${uri}test?directConnection=true`);
231
- });
232
- });
233
-
234
- context('when no additional options are provided with db', () => {
235
- const uri = '192.0.0.1:27018/foo';
236
- const options = { connectionSpecifier: uri };
237
-
238
- it('returns the uri with the scheme', () => {
239
- expect(generateUri(options)).to.equal(`mongodb://${uri}?directConnection=true`);
240
- });
241
- });
242
-
243
- context('when no additional options are provided with db with special characters', () => {
244
- const uri = '192.0.0.1:27018/föö-:?%ab💙,\'_.c';
245
- const options = { connectionSpecifier: uri };
246
-
247
- it('returns the uri with the scheme', () => {
248
- expect(generateUri(options)).to.equal('mongodb://192.0.0.1:27018/f%C3%B6%C3%B6-%3A%3F%25ab%F0%9F%92%99%2C\'_.c?directConnection=true');
249
- });
250
- });
251
-
252
- context('when the db part does not start with a slash', () => {
253
- const uri = '192.0.0.1:27018?foo=bar';
254
- const options = { connectionSpecifier: uri };
255
-
256
- it('throws an exception', () => {
257
- try {
258
- generateUri(options);
259
- expect.fail('expected error');
260
- } catch (e: any) {
261
- expect(e).to.be.instanceOf(MongoshInvalidInputError);
262
- expect(e.code).to.equal(CommonErrors.InvalidArgument);
263
- }
264
- });
265
- });
266
-
267
- context('when additional options are provided', () => {
268
- context('when providing host with URI', () => {
269
- const uri = '192.0.0.1:27018/foo';
270
- const options = { connectionSpecifier: uri, host: '127.0.0.1' };
271
-
272
- it('throws an exception', () => {
273
- try {
274
- generateUri(options);
275
- expect.fail('expected error');
276
- } catch (e: any) {
277
- expect(e).to.be.instanceOf(MongoshInvalidInputError);
278
- expect(e.code).to.equal(CommonErrors.InvalidArgument);
279
- }
280
- });
281
- });
282
-
283
- context('when providing host with db', () => {
284
- const uri = 'foo';
285
- const options = { connectionSpecifier: uri, host: '127.0.0.2' };
286
-
287
- it('uses the provided host with default port', () => {
288
- expect(generateUri(options)).to.equal('mongodb://127.0.0.2:27017/foo?directConnection=true');
289
- });
290
- });
291
-
292
- context('when providing port with URI', () => {
293
- const uri = '192.0.0.1:27018/foo';
294
- const options = { connectionSpecifier: uri, port: '27018' };
295
-
296
- it('throws an exception', () => {
297
- try {
298
- generateUri(options);
299
- expect.fail('expected error');
300
- } catch (e: any) {
301
- expect(e).to.be.instanceOf(MongoshInvalidInputError);
302
- expect(e.code).to.equal(CommonErrors.InvalidArgument);
303
- }
304
- });
305
- });
306
-
307
- context('when providing port with db', () => {
308
- const uri = 'foo';
309
- const options = { connectionSpecifier: uri, port: '27018' };
310
-
311
- it('uses the provided host with default port', () => {
312
- expect(generateUri(options)).to.equal('mongodb://127.0.0.1:27018/foo?directConnection=true&serverSelectionTimeoutMS=2000');
313
- });
314
- });
315
-
316
- context('when providing port with only a host URI', () => {
317
- const uri = '127.0.0.2/foo';
318
- const options = { connectionSpecifier: uri, port: '27018' };
319
-
320
- it('throws an exception', () => {
321
- try {
322
- generateUri(options);
323
- expect.fail('expected error');
324
- } catch (e: any) {
325
- expect(e).to.be.instanceOf(MongoshInvalidInputError);
326
- expect(e.code).to.equal(CommonErrors.InvalidArgument);
327
- }
328
- });
329
- });
330
-
331
- context('when providing nodb', () => {
332
- const uri = 'mongodb://127.0.0.2/foo';
333
- const options = { connectionSpecifier: uri, nodb: true };
334
-
335
- it('returns an empty string', () => {
336
- expect(generateUri(options)).to.equal('');
337
- });
338
- });
339
-
340
- context('when providing explicit serverSelectionTimeoutMS', () => {
341
- const uri = 'mongodb://127.0.0.2/foo?serverSelectionTimeoutMS=10';
342
- const options = { connectionSpecifier: uri };
343
-
344
- it('does not override the existing value', () => {
345
- expect(generateUri(options)).to.equal('mongodb://127.0.0.2/foo?serverSelectionTimeoutMS=10&directConnection=true');
346
- });
347
- });
348
-
349
- context('when providing explicit serverSelectionTimeoutMS (different case)', () => {
350
- const uri = 'mongodb://127.0.0.2/foo?SERVERSELECTIONTIMEOUTMS=10';
351
- const options = { connectionSpecifier: uri };
352
-
353
- it('does not override the existing value', () => {
354
- expect(generateUri(options)).to.equal('mongodb://127.0.0.2/foo?SERVERSELECTIONTIMEOUTMS=10&directConnection=true');
355
- });
356
- });
357
- });
358
-
359
- context('when providing a URI with query parameters', () => {
360
- context('that do not conflict with directConnection', () => {
361
- const uri = 'mongodb://192.0.0.1:27018/?readPreference=primary';
362
- const options = { connectionSpecifier: uri };
363
- it('still includes directConnection', () => {
364
- expect(generateUri(options)).to.equal('mongodb://192.0.0.1:27018/?readPreference=primary&directConnection=true');
365
- });
366
- });
367
-
368
- context('including replicaSet', () => {
369
- const uri = 'mongodb://192.0.0.1:27018/db?replicaSet=replicaset';
370
- const options = { connectionSpecifier: uri };
371
- it('does not add the directConnection parameter', () => {
372
- expect(generateUri(options)).to.equal(uri);
373
- });
374
- });
375
-
376
- context('including explicit directConnection', () => {
377
- const uri = 'mongodb://192.0.0.1:27018/?directConnection=false';
378
- const options = { connectionSpecifier: uri };
379
- it('does not change the directConnection parameter', () => {
380
- expect(generateUri(options)).to.equal('mongodb://192.0.0.1:27018/?directConnection=false');
381
- });
382
- });
383
- });
384
- });
385
-
386
-
387
- context('when an invalid URI is provided', () => {
388
- const uri = '/x';
389
- const options = { connectionSpecifier: uri };
390
-
391
- it('returns the uri', () => {
392
- try {
393
- generateUri(options);
394
- } catch (e: any) {
395
- expect(e.message).to.contain('Invalid URI: /x');
396
- expect(e).to.be.instanceOf(MongoshInvalidInputError);
397
- expect(e.code).to.equal(CommonErrors.InvalidArgument);
398
- return;
399
- }
400
- expect.fail('expected error');
401
- });
402
- });
403
-
404
- context('when the --host option contains invalid characters', () => {
405
- const options = { host: 'a$b,c' };
406
-
407
- it('returns the uri', () => {
408
- try {
409
- generateUri(options);
410
- } catch (e: any) {
411
- expect(e.message).to.contain('The --host argument contains an invalid character: $');
412
- expect(e).to.be.instanceOf(MongoshInvalidInputError);
413
- expect(e.code).to.equal(CommonErrors.InvalidArgument);
414
- return;
415
- }
416
- expect.fail('expected error');
417
- });
418
- });
419
-
420
- context('when the --host option contains a seed list', () => {
421
- context('without a replica set', () => {
422
- it('returns a URI for the hosts and ports specified in --host', () => {
423
- const options = { host: 'host1:123,host2,host3:456,' };
424
- expect(generateUri(options)).to.equal('mongodb://host1:123,host2,host3:456/');
425
- });
426
-
427
- it('returns a URI for the hosts and ports specified in --host and database name', () => {
428
- const options = {
429
- host: 'host1:123,host_2,host3:456,',
430
- connectionSpecifier: 'admin'
431
- };
432
- expect(generateUri(options)).to.equal('mongodb://host1:123,host_2,host3:456/admin');
433
- });
434
-
435
- it('returns a URI for the hosts in --host and fixed --port', () => {
436
- const options = {
437
- host: 'host1:1234,host_2',
438
- port: '1234',
439
- connectionSpecifier: 'admin'
440
- };
441
- expect(generateUri(options)).to.equal('mongodb://host1:1234,host_2:1234/admin');
442
- });
443
-
444
- it('throws an error if seed list in --host contains port mismatches from fixed --port', () => {
445
- const options = {
446
- host: 'host1,host_2:123',
447
- port: '1234',
448
- connectionSpecifier: 'admin'
449
- };
450
- expect(() => generateUri(options)).to.throw('The host list contains different ports than provided by --port');
451
- });
452
- });
453
-
454
- context('with a replica set', () => {
455
- it('returns a URI for the hosts and ports specified in --host', () => {
456
- const options = { host: 'replsetname/host1:123,host2,host3:456,' };
457
- expect(generateUri(options)).to.equal('mongodb://host1:123,host2,host3:456/?replicaSet=replsetname');
458
- });
459
-
460
- it('returns a URI for the hosts and ports specified in --host and database name', () => {
461
- const options = { host: 'replsetname/host1:123,host2,host3:456', connectionSpecifier: 'admin' };
462
- expect(generateUri(options)).to.equal('mongodb://host1:123,host2,host3:456/admin?replicaSet=replsetname');
463
- });
464
-
465
- it('returns a URI for the hosts and ports specified in --host and database name with escaped chars', () => {
466
- const options = { host: 'replsetname/host1:123,host2,host3:456', connectionSpecifier: 'admin?foo=bar' };
467
- expect(generateUri(options)).to.equal('mongodb://host1:123,host2,host3:456/admin%3Ffoo%3Dbar?replicaSet=replsetname');
468
- });
469
-
470
- it('returns a URI for the hosts specified in --host and explicit --port', () => {
471
- const options = { host: 'replsetname/host1:123,host2,', port: '123' };
472
- expect(generateUri(options)).to.equal('mongodb://host1:123,host2:123/?replicaSet=replsetname');
473
- });
474
-
475
- it('throws an error if the hosts contain ports that mismatch from --port', () => {
476
- const options = { host: 'replsetname/host1:1234,host2,', port: '123' };
477
- expect(() => generateUri(options)).to.throw('The host list contains different ports than provided by --port');
478
- });
479
- });
480
- });
481
- });
@@ -1,265 +0,0 @@
1
- /* eslint complexity: 0*/
2
-
3
- import { CommonErrors, MongoshInvalidInputError } from '@mongosh/errors';
4
- import i18n from '@mongosh/i18n';
5
- import CliOptions from './cli-options';
6
- import ConnectionString, { CommaAndColonSeparatedRecord } from 'mongodb-connection-string-url';
7
- import { DEFAULT_DB } from './index';
8
-
9
- /**
10
- * URI schemes.
11
- */
12
- enum Scheme {
13
- Mongo = 'mongodb://',
14
- MongoSrv = 'mongodb+srv://'
15
- }
16
-
17
- /**
18
- * The default host.
19
- */
20
- const DEFAULT_HOST = '127.0.0.1';
21
-
22
- /**
23
- * The default port.
24
- */
25
- const DEFAULT_PORT = '27017';
26
-
27
- /**
28
- * Conflicting host/port message.
29
- */
30
- const CONFLICT = 'cli-repl.uri-generator.no-host-port';
31
-
32
- /**
33
- * Invalid host message.
34
- */
35
- const INVALID_HOST = 'cli-repl.uri-generator.invalid-host';
36
-
37
- /**
38
- * Host seed list contains a port that mismatches an explicit --port.
39
- */
40
- const HOST_LIST_PORT_MISMATCH = 'cli-repl.uri-generator.host-list-port-mismatch';
41
-
42
- /**
43
- * Diverging gssapiServiceName and SERVICE_NAME mechanism property
44
- */
45
- const DIVERGING_SERVICE_NAME = 'cli-repl.uri-generator.diverging-service-name';
46
-
47
- /**
48
- * Usage of unsupported gssapiServiceName query parameter
49
- */
50
- const GSSAPI_SERVICE_NAME_UNSUPPORTED = 'cli-repl.uri-generator.gssapi-service-name-unsupported';
51
-
52
- /**
53
- * Validate conflicts in the options.
54
- */
55
- function validateConflicts(options: CliOptions, connectionString?: ConnectionString): void {
56
- if (options.host || options.port) {
57
- throw new MongoshInvalidInputError(i18n.__(CONFLICT), CommonErrors.InvalidArgument);
58
- }
59
-
60
- if (options.gssapiServiceName && connectionString?.searchParams.has('authMechanismProperties')) {
61
- const authProperties = new CommaAndColonSeparatedRecord(
62
- connectionString.searchParams.get('authMechanismProperties'));
63
- const serviceName = authProperties.get('SERVICE_NAME');
64
- if (serviceName !== undefined && options.gssapiServiceName !== serviceName) {
65
- throw new MongoshInvalidInputError(i18n.__(DIVERGING_SERVICE_NAME), CommonErrors.InvalidArgument);
66
- }
67
- }
68
-
69
- if (connectionString?.searchParams.has('gssapiServiceName')) {
70
- throw new MongoshInvalidInputError(i18n.__(GSSAPI_SERVICE_NAME_UNSUPPORTED), CommonErrors.InvalidArgument);
71
- }
72
- }
73
-
74
- /**
75
- * Perform basic validation of the --host option.
76
- *
77
- * @param {string} host - The value of the --host option.
78
- */
79
- function validateHost(host: string): void {
80
- const invalidCharacter = host.match(/[^a-zA-Z0-9.:\[\]_-]/);
81
- if (invalidCharacter) {
82
- throw new MongoshInvalidInputError(
83
- i18n.__(INVALID_HOST) + ': ' + invalidCharacter[0],
84
- CommonErrors.InvalidArgument);
85
- }
86
- }
87
-
88
- /**
89
- * Validates a host seed list against a specified fixed port and
90
- * returns an individual `<host>:<port>` array.
91
- */
92
- function validateHostSeedList(hosts: string, fixedPort: string | undefined): string[] {
93
- const trimmedHosts = hosts.split(',').map(h => h.trim()).filter(h => !!h);
94
- const hostList: string[] = [];
95
- trimmedHosts.forEach(h => {
96
- const [host, port] = h.split(':');
97
- if (fixedPort && port !== undefined && port !== fixedPort) {
98
- throw new MongoshInvalidInputError(
99
- i18n.__(HOST_LIST_PORT_MISMATCH),
100
- CommonErrors.InvalidArgument
101
- );
102
- }
103
- hostList.push(`${host}${(port || fixedPort) ? ':' + (port || fixedPort) : ''}`);
104
- });
105
- return hostList;
106
- }
107
-
108
- /**
109
- * Generate the host from the options or default.
110
- *
111
- * @param {CliOptions} options - The options.
112
- *
113
- * @returns {string} The host.
114
- */
115
- function generateHost(options: CliOptions): string {
116
- if (options.host) {
117
- validateHost(options.host);
118
- if (options.host.includes(':')) {
119
- return options.host.split(':')[0];
120
- }
121
- return options.host;
122
- }
123
- return DEFAULT_HOST;
124
- }
125
-
126
- /**
127
- * Generate the port from the options or default.
128
- *
129
- * @param {CliOptions} options - The options.
130
- *
131
- * @returns {string} The port.
132
- */
133
- function generatePort(options: CliOptions): string {
134
- if (options.host && options.host.includes(':')) {
135
- validateHost(options.host);
136
- const port = options.host.split(':')[1];
137
- if (!options.port || options.port === port) {
138
- return port;
139
- }
140
- throw new MongoshInvalidInputError(i18n.__(CONFLICT), CommonErrors.InvalidArgument);
141
- }
142
- return options.port ? options.port : DEFAULT_PORT;
143
- }
144
-
145
- /**
146
- * Generate a URI from the provided CLI options.
147
- *
148
- * If a full URI is provided, you cannot also specify --host or --port
149
- *
150
- * Rules from the existing Shell code:
151
- *
152
- * if nodb is set then all positional parameters are files
153
- * otherwise the first positional parameter might be a dbaddress, but
154
- * only if one of these conditions is met:
155
- * - it contains no '.' after the last appearance of '\' or '/'
156
- * - it doesn't end in '.js' and it doesn't specify a path to an existing file
157
- */
158
- function generateUri(options: CliOptions): string {
159
- if (options.nodb) {
160
- return '';
161
- }
162
- const connectionString = generateUriNormalized(options);
163
- if (connectionString.hosts.every(host =>
164
- ['localhost', '127.0.0.1'].includes(host.split(':')[0]))) {
165
- const params = connectionString.searchParams;
166
- if (!params.has('serverSelectionTimeoutMS')) {
167
- params.set('serverSelectionTimeoutMS', '2000');
168
- }
169
- }
170
- return connectionString.toString();
171
- }
172
- function generateUriNormalized(options: CliOptions): ConnectionString {
173
- const uri = options.connectionSpecifier;
174
-
175
- // If the --host argument contains /, it has the format
176
- // <replSetName>/<hostname1><:port>,<hostname2><:port>,<...>
177
- const replSetHostMatch = (options.host ?? '').match(
178
- /^(?<replSetName>[^/]+)\/(?<hosts>([A-Za-z0-9._-]+(:\d+)?,?)+)$/
179
- );
180
- if (replSetHostMatch) {
181
- const { replSetName, hosts } = replSetHostMatch.groups as { replSetName: string, hosts: string };
182
- const connectionString = new ConnectionString(`${Scheme.Mongo}replacemeHost/${encodeURIComponent(uri || '')}`);
183
- connectionString.hosts = validateHostSeedList(hosts, options.port);
184
- connectionString.searchParams.set('replicaSet', replSetName);
185
- return addShellConnectionStringParameters(connectionString);
186
- }
187
-
188
- // If the --host argument contains multiple hosts as a seed list
189
- // we directly do not do additional host/port parsing
190
- const seedList = (options.host ?? '').match(
191
- /^(?<hosts>([A-Za-z0-9._-]+(:\d+)?,?)+)$/
192
- );
193
- if (seedList && options.host?.includes(',')) {
194
- const { hosts } = seedList.groups as { hosts: string };
195
- const connectionString = new ConnectionString(`${Scheme.Mongo}replacemeHost/${encodeURIComponent(uri || '')}`);
196
- connectionString.hosts = validateHostSeedList(hosts, options.port);
197
- return addShellConnectionStringParameters(connectionString);
198
- }
199
-
200
- // There is no URI provided, use default 127.0.0.1:27017
201
- if (!uri) {
202
- return new ConnectionString(`${Scheme.Mongo}${generateHost(options)}:${generatePort(options)}/?directConnection=true`);
203
- }
204
-
205
- // mongodb+srv:// URI is provided, treat as correct and immediately return
206
- if (uri.startsWith(Scheme.MongoSrv)) {
207
- const connectionString = new ConnectionString(uri);
208
- validateConflicts(options, connectionString);
209
- return connectionString;
210
- } else if (uri.startsWith(Scheme.Mongo)) {
211
- // we need to figure out if we have to add the directConnection query parameter
212
- const connectionString = new ConnectionString(uri);
213
- validateConflicts(options, connectionString);
214
- return addShellConnectionStringParameters(connectionString);
215
- }
216
-
217
- // Capture host, port and db from the string and generate a URI from
218
- // the parts. If there is a db part, it *must* start with /.
219
- const uriMatch = /^([A-Za-z0-9][A-Za-z0-9._-]+):?(\d+)?(?:\/(\S*))?$/gi;
220
- let parts: string[] | null = uriMatch.exec(uri);
221
-
222
- if (parts === null) {
223
- if (/[/\\. "$]/.test(uri)) {
224
- // This cannot be a database name because 'uri' contains characters invalid in a database.
225
- throw new MongoshInvalidInputError(`Invalid URI: ${uri}`, CommonErrors.InvalidArgument);
226
- } else {
227
- parts = [ uri, uri ];
228
- }
229
- }
230
-
231
- let host: string | undefined = parts?.[1];
232
- const port = parts?.[2];
233
- let dbAndQueryString = parts?.[3];
234
-
235
- // If there is no port and db, host becomes db if there is no
236
- // '.' in the string. (legacy shell behaviour)
237
- if (!port && !dbAndQueryString && host.indexOf('.') < 0) {
238
- dbAndQueryString = host;
239
- host = undefined;
240
- }
241
-
242
- // If we have a host or port, validate that the options don't also
243
- // have a host or port in them.
244
- if (host || port) {
245
- validateConflicts(options);
246
- }
247
- return addShellConnectionStringParameters(new ConnectionString(
248
- `${Scheme.Mongo}${host || generateHost(options)}:${port || generatePort(options)}/${encodeURIComponent(dbAndQueryString || DEFAULT_DB)}`));
249
- }
250
-
251
- /**
252
- * Adds the `directConnection=true` query parameter if required.
253
- * @param uri mongodb:// connection string
254
- */
255
- function addShellConnectionStringParameters(uri: ConnectionString): ConnectionString {
256
- uri = uri.clone();
257
- const params = uri.searchParams;
258
- if (!params.has('replicaSet') && !params.has('directConnection') && !params.has('loadBalanced') && uri.hosts.length === 1) {
259
- params.set('directConnection', 'true');
260
- }
261
- return uri;
262
- }
263
-
264
- export default generateUri;
265
- export { Scheme };