Spaces:
Runtime error
Runtime error
Download static/node_modules/mongodb/lib/cmap/connect.js from kaab4321/NarrativeFlow: direct link, hf CLI and curl.
- Browser
- Download file 15 kB
-
https://huggingface.co/spaces/kaab4321/NarrativeFlow/resolve/main/static/node_modules/mongodb/lib/cmap/connect.js
- Command line
-
hf download hf://spaces/kaab4321/NarrativeFlow/static/node_modules/mongodb/lib/cmap/connect.js
-
curl -L -o connect.js https://huggingface.co/spaces/kaab4321/NarrativeFlow/resolve/main/static/node_modules/mongodb/lib/cmap/connect.js
15 kB
| ; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| exports.makeSocket = exports.LEGAL_TCP_SOCKET_OPTIONS = exports.LEGAL_TLS_SOCKET_OPTIONS = exports.prepareHandshakeDocument = exports.performInitialHandshake = exports.makeConnection = exports.connect = void 0; | |
| const net = require("net"); | |
| const tls = require("tls"); | |
| const constants_1 = require("../constants"); | |
| const deps_1 = require("../deps"); | |
| const error_1 = require("../error"); | |
| const utils_1 = require("../utils"); | |
| const auth_provider_1 = require("./auth/auth_provider"); | |
| const providers_1 = require("./auth/providers"); | |
| const connection_1 = require("./connection"); | |
| const constants_2 = require("./wire_protocol/constants"); | |
| async function connect(options) { | |
| let connection = null; | |
| try { | |
| const socket = await makeSocket(options); | |
| connection = makeConnection(options, socket); | |
| await performInitialHandshake(connection, options); | |
| return connection; | |
| } | |
| catch (error) { | |
| connection?.destroy(); | |
| throw error; | |
| } | |
| } | |
| exports.connect = connect; | |
| function makeConnection(options, socket) { | |
| let ConnectionType = options.connectionType ?? connection_1.Connection; | |
| if (options.autoEncrypter) { | |
| ConnectionType = connection_1.CryptoConnection; | |
| } | |
| return new ConnectionType(socket, options); | |
| } | |
| exports.makeConnection = makeConnection; | |
| function checkSupportedServer(hello, options) { | |
| const maxWireVersion = Number(hello.maxWireVersion); | |
| const minWireVersion = Number(hello.minWireVersion); | |
| const serverVersionHighEnough = !Number.isNaN(maxWireVersion) && maxWireVersion >= constants_2.MIN_SUPPORTED_WIRE_VERSION; | |
| const serverVersionLowEnough = !Number.isNaN(minWireVersion) && minWireVersion <= constants_2.MAX_SUPPORTED_WIRE_VERSION; | |
| if (serverVersionHighEnough) { | |
| if (serverVersionLowEnough) { | |
| return null; | |
| } | |
| const message = `Server at ${options.hostAddress} reports minimum wire version ${JSON.stringify(hello.minWireVersion)}, but this version of the Node.js Driver requires at most ${constants_2.MAX_SUPPORTED_WIRE_VERSION} (MongoDB ${constants_2.MAX_SUPPORTED_SERVER_VERSION})`; | |
| return new error_1.MongoCompatibilityError(message); | |
| } | |
| const message = `Server at ${options.hostAddress} reports maximum wire version ${JSON.stringify(hello.maxWireVersion) ?? 0}, but this version of the Node.js Driver requires at least ${constants_2.MIN_SUPPORTED_WIRE_VERSION} (MongoDB ${constants_2.MIN_SUPPORTED_SERVER_VERSION})`; | |
| return new error_1.MongoCompatibilityError(message); | |
| } | |
| async function performInitialHandshake(conn, options) { | |
| const credentials = options.credentials; | |
| if (credentials) { | |
| if (!(credentials.mechanism === providers_1.AuthMechanism.MONGODB_DEFAULT) && | |
| !options.authProviders.getOrCreateProvider(credentials.mechanism, credentials.mechanismProperties)) { | |
| throw new error_1.MongoInvalidArgumentError(`AuthMechanism '${credentials.mechanism}' not supported`); | |
| } | |
| } | |
| const authContext = new auth_provider_1.AuthContext(conn, credentials, options); | |
| conn.authContext = authContext; | |
| const handshakeDoc = await prepareHandshakeDocument(authContext); | |
| // @ts-expect-error: TODO(NODE-5141): The options need to be filtered properly, Connection options differ from Command options | |
| const handshakeOptions = { ...options, raw: false }; | |
| if (typeof options.connectTimeoutMS === 'number') { | |
| // The handshake technically is a monitoring check, so its socket timeout should be connectTimeoutMS | |
| handshakeOptions.socketTimeoutMS = options.connectTimeoutMS; | |
| } | |
| const start = new Date().getTime(); | |
| const response = await conn.command((0, utils_1.ns)('admin.$cmd'), handshakeDoc, handshakeOptions); | |
| if (!('isWritablePrimary' in response)) { | |
| // Provide hello-style response document. | |
| response.isWritablePrimary = response[constants_1.LEGACY_HELLO_COMMAND]; | |
| } | |
| if (response.helloOk) { | |
| conn.helloOk = true; | |
| } | |
| const supportedServerErr = checkSupportedServer(response, options); | |
| if (supportedServerErr) { | |
| throw supportedServerErr; | |
| } | |
| if (options.loadBalanced) { | |
| if (!response.serviceId) { | |
| throw new error_1.MongoCompatibilityError('Driver attempted to initialize in load balancing mode, ' + | |
| 'but the server does not support this mode.'); | |
| } | |
| } | |
| // NOTE: This is metadata attached to the connection while porting away from | |
| // handshake being done in the `Server` class. Likely, it should be | |
| // relocated, or at very least restructured. | |
| conn.hello = response; | |
| conn.lastHelloMS = new Date().getTime() - start; | |
| if (!response.arbiterOnly && credentials) { | |
| // store the response on auth context | |
| authContext.response = response; | |
| const resolvedCredentials = credentials.resolveAuthMechanism(response); | |
| const provider = options.authProviders.getOrCreateProvider(resolvedCredentials.mechanism, resolvedCredentials.mechanismProperties); | |
| if (!provider) { | |
| throw new error_1.MongoInvalidArgumentError(`No AuthProvider for ${resolvedCredentials.mechanism} defined.`); | |
| } | |
| try { | |
| await provider.auth(authContext); | |
| } | |
| catch (error) { | |
| if (error instanceof error_1.MongoError) { | |
| error.addErrorLabel(error_1.MongoErrorLabel.HandshakeError); | |
| if ((0, error_1.needsRetryableWriteLabel)(error, response.maxWireVersion)) { | |
| error.addErrorLabel(error_1.MongoErrorLabel.RetryableWriteError); | |
| } | |
| } | |
| throw error; | |
| } | |
| } | |
| // Connection establishment is socket creation (tcp handshake, tls handshake, MongoDB handshake (saslStart, saslContinue)) | |
| // Once connection is established, command logging can log events (if enabled) | |
| conn.established = true; | |
| } | |
| exports.performInitialHandshake = performInitialHandshake; | |
| /** | |
| * @internal | |
| * | |
| * This function is only exposed for testing purposes. | |
| */ | |
| async function prepareHandshakeDocument(authContext) { | |
| const options = authContext.options; | |
| const compressors = options.compressors ? options.compressors : []; | |
| const { serverApi } = authContext.connection; | |
| const clientMetadata = await options.extendedMetadata; | |
| const handshakeDoc = { | |
| [serverApi?.version || options.loadBalanced === true ? 'hello' : constants_1.LEGACY_HELLO_COMMAND]: 1, | |
| helloOk: true, | |
| client: clientMetadata, | |
| compression: compressors | |
| }; | |
| if (options.loadBalanced === true) { | |
| handshakeDoc.loadBalanced = true; | |
| } | |
| const credentials = authContext.credentials; | |
| if (credentials) { | |
| if (credentials.mechanism === providers_1.AuthMechanism.MONGODB_DEFAULT && credentials.username) { | |
| handshakeDoc.saslSupportedMechs = `${credentials.source}.${credentials.username}`; | |
| const provider = authContext.options.authProviders.getOrCreateProvider(providers_1.AuthMechanism.MONGODB_SCRAM_SHA256, credentials.mechanismProperties); | |
| if (!provider) { | |
| // This auth mechanism is always present. | |
| throw new error_1.MongoInvalidArgumentError(`No AuthProvider for ${providers_1.AuthMechanism.MONGODB_SCRAM_SHA256} defined.`); | |
| } | |
| return await provider.prepare(handshakeDoc, authContext); | |
| } | |
| const provider = authContext.options.authProviders.getOrCreateProvider(credentials.mechanism, credentials.mechanismProperties); | |
| if (!provider) { | |
| throw new error_1.MongoInvalidArgumentError(`No AuthProvider for ${credentials.mechanism} defined.`); | |
| } | |
| return await provider.prepare(handshakeDoc, authContext); | |
| } | |
| return handshakeDoc; | |
| } | |
| exports.prepareHandshakeDocument = prepareHandshakeDocument; | |
| /** @public */ | |
| exports.LEGAL_TLS_SOCKET_OPTIONS = [ | |
| 'ALPNProtocols', | |
| 'ca', | |
| 'cert', | |
| 'checkServerIdentity', | |
| 'ciphers', | |
| 'crl', | |
| 'ecdhCurve', | |
| 'key', | |
| 'minDHSize', | |
| 'passphrase', | |
| 'pfx', | |
| 'rejectUnauthorized', | |
| 'secureContext', | |
| 'secureProtocol', | |
| 'servername', | |
| 'session' | |
| ]; | |
| /** @public */ | |
| exports.LEGAL_TCP_SOCKET_OPTIONS = [ | |
| 'family', | |
| 'hints', | |
| 'localAddress', | |
| 'localPort', | |
| 'lookup' | |
| ]; | |
| function parseConnectOptions(options) { | |
| const hostAddress = options.hostAddress; | |
| if (!hostAddress) | |
| throw new error_1.MongoInvalidArgumentError('Option "hostAddress" is required'); | |
| const result = {}; | |
| for (const name of exports.LEGAL_TCP_SOCKET_OPTIONS) { | |
| if (options[name] != null) { | |
| result[name] = options[name]; | |
| } | |
| } | |
| if (typeof hostAddress.socketPath === 'string') { | |
| result.path = hostAddress.socketPath; | |
| return result; | |
| } | |
| else if (typeof hostAddress.host === 'string') { | |
| result.host = hostAddress.host; | |
| result.port = hostAddress.port; | |
| return result; | |
| } | |
| else { | |
| // This should never happen since we set up HostAddresses | |
| // But if we don't throw here the socket could hang until timeout | |
| // TODO(NODE-3483) | |
| throw new error_1.MongoRuntimeError(`Unexpected HostAddress ${JSON.stringify(hostAddress)}`); | |
| } | |
| } | |
| function parseSslOptions(options) { | |
| const result = parseConnectOptions(options); | |
| // Merge in valid SSL options | |
| for (const name of exports.LEGAL_TLS_SOCKET_OPTIONS) { | |
| if (options[name] != null) { | |
| result[name] = options[name]; | |
| } | |
| } | |
| if (options.existingSocket) { | |
| result.socket = options.existingSocket; | |
| } | |
| // Set default sni servername to be the same as host | |
| if (result.servername == null && result.host && !net.isIP(result.host)) { | |
| result.servername = result.host; | |
| } | |
| return result; | |
| } | |
| async function makeSocket(options) { | |
| const useTLS = options.tls ?? false; | |
| const noDelay = options.noDelay ?? true; | |
| const connectTimeoutMS = options.connectTimeoutMS ?? 30000; | |
| const existingSocket = options.existingSocket; | |
| let socket; | |
| if (options.proxyHost != null) { | |
| // Currently, only Socks5 is supported. | |
| return await makeSocks5Connection({ | |
| ...options, | |
| connectTimeoutMS // Should always be present for Socks5 | |
| }); | |
| } | |
| if (useTLS) { | |
| const tlsSocket = tls.connect(parseSslOptions(options)); | |
| if (typeof tlsSocket.disableRenegotiation === 'function') { | |
| tlsSocket.disableRenegotiation(); | |
| } | |
| socket = tlsSocket; | |
| } | |
| else if (existingSocket) { | |
| // In the TLS case, parseSslOptions() sets options.socket to existingSocket, | |
| // so we only need to handle the non-TLS case here (where existingSocket | |
| // gives us all we need out of the box). | |
| socket = existingSocket; | |
| } | |
| else { | |
| socket = net.createConnection(parseConnectOptions(options)); | |
| } | |
| socket.setKeepAlive(true, 300000); | |
| socket.setTimeout(connectTimeoutMS); | |
| socket.setNoDelay(noDelay); | |
| let cancellationHandler = null; | |
| const { promise: connectedSocket, resolve, reject } = (0, utils_1.promiseWithResolvers)(); | |
| if (existingSocket) { | |
| resolve(socket); | |
| } | |
| else { | |
| const connectEvent = useTLS ? 'secureConnect' : 'connect'; | |
| socket | |
| .once(connectEvent, () => resolve(socket)) | |
| .once('error', error => reject(connectionFailureError('error', error))) | |
| .once('timeout', () => reject(connectionFailureError('timeout'))) | |
| .once('close', () => reject(connectionFailureError('close'))); | |
| if (options.cancellationToken != null) { | |
| cancellationHandler = () => reject(connectionFailureError('cancel')); | |
| options.cancellationToken.once('cancel', cancellationHandler); | |
| } | |
| } | |
| try { | |
| socket = await connectedSocket; | |
| return socket; | |
| } | |
| catch (error) { | |
| socket.destroy(); | |
| throw error; | |
| } | |
| finally { | |
| socket.setTimeout(0); | |
| socket.removeAllListeners(); | |
| if (cancellationHandler != null) { | |
| options.cancellationToken?.removeListener('cancel', cancellationHandler); | |
| } | |
| } | |
| } | |
| exports.makeSocket = makeSocket; | |
| let socks = null; | |
| function loadSocks() { | |
| if (socks == null) { | |
| const socksImport = (0, deps_1.getSocks)(); | |
| if ('kModuleError' in socksImport) { | |
| throw socksImport.kModuleError; | |
| } | |
| socks = socksImport; | |
| } | |
| return socks; | |
| } | |
| async function makeSocks5Connection(options) { | |
| const hostAddress = utils_1.HostAddress.fromHostPort(options.proxyHost ?? '', // proxyHost is guaranteed to set here | |
| options.proxyPort ?? 1080); | |
| // First, connect to the proxy server itself: | |
| const rawSocket = await makeSocket({ | |
| ...options, | |
| hostAddress, | |
| tls: false, | |
| proxyHost: undefined | |
| }); | |
| const destination = parseConnectOptions(options); | |
| if (typeof destination.host !== 'string' || typeof destination.port !== 'number') { | |
| throw new error_1.MongoInvalidArgumentError('Can only make Socks5 connections to TCP hosts'); | |
| } | |
| socks ??= loadSocks(); | |
| try { | |
| // Then, establish the Socks5 proxy connection: | |
| const { socket } = await socks.SocksClient.createConnection({ | |
| existing_socket: rawSocket, | |
| timeout: options.connectTimeoutMS, | |
| command: 'connect', | |
| destination: { | |
| host: destination.host, | |
| port: destination.port | |
| }, | |
| proxy: { | |
| // host and port are ignored because we pass existing_socket | |
| host: 'iLoveJavaScript', | |
| port: 0, | |
| type: 5, | |
| userId: options.proxyUsername || undefined, | |
| password: options.proxyPassword || undefined | |
| } | |
| }); | |
| // Finally, now treat the resulting duplex stream as the | |
| // socket over which we send and receive wire protocol messages: | |
| return await makeSocket({ | |
| ...options, | |
| existingSocket: socket, | |
| proxyHost: undefined | |
| }); | |
| } | |
| catch (error) { | |
| throw connectionFailureError('error', error); | |
| } | |
| } | |
| function connectionFailureError(type, cause) { | |
| switch (type) { | |
| case 'error': | |
| return new error_1.MongoNetworkError(error_1.MongoError.buildErrorMessage(cause), { cause }); | |
| case 'timeout': | |
| return new error_1.MongoNetworkTimeoutError('connection timed out'); | |
| case 'close': | |
| return new error_1.MongoNetworkError('connection closed'); | |
| case 'cancel': | |
| return new error_1.MongoNetworkError('connection establishment was cancelled'); | |
| default: | |
| return new error_1.MongoNetworkError('unknown network error'); | |
| } | |
| } | |
| //# sourceMappingURL=connect.js.map |