Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: include Node.js driver and devtools-connect in snapshot MONGOSH-1727 #1846

Merged
merged 6 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 0 additions & 15 deletions config/webpack.base.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,6 @@ module.exports = {

externals: {
"node:crypto": "commonjs2 crypto",
// node-fetch https://github.com/node-fetch/node-fetch/blob/8b3320d2a7c07bce4afc6b2bf6c3bbddda85b01f/src/index.js#L9
"node:buffer": "commonjs2 buffer",
"node:http": "commonjs2 http",
"node:https": "commonjs2 https",
"node:stream": "commonjs2 stream",
"node:zlib": "commonjs2 zlib",
"node:url": "commonjs2 url",
"node:util": "commonjs2 util",
"node:events": "commonjs2 events",
"node:net": "commonjs2 net",
// https://github.com/node-fetch/node-fetch/blob/8b3320d2a7c07bce4afc6b2bf6c3bbddda85b01f/test/main.js#L2
"node:dns": "commonjs2 dns",
"node:fs": "commonjs2 fs",
"node:path": "commonjs2 path",
"node:vm": "commonjs2 vm",
electron: "commonjs2 electron" // optional dep of the OIDC plugin
},

Expand Down
2 changes: 1 addition & 1 deletion packages/build/src/compile/signable-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export class SignableCompiler {
useNodeSnapshot: true,
// To account for the fact that we are manually patching Node.js to include
// https://github.com/nodejs/node/pull/50453 until we have caught up with upstream
nodeSnapshotConfigFlags: ['WithoutCodeCache'],
nodeSnapshotConfigFlags: ['Default'],
});
}
}
41 changes: 38 additions & 3 deletions packages/cli-repl/webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
'use strict';
const fs = require('fs');
const Module = require('module');
const crypto = require('crypto');
const { merge } = require('webpack-merge');
const path = require('path');
const { WebpackDependenciesPlugin } = require('@mongodb-js/sbom-tools');

const baseWebpackConfig = require('../../config/webpack.base.config');

// Builtins that the driver and/or devtools-connect refer to but which
// cannot be snapshotted yet
// https://github.com/nodejs/node/pull/50943 addresses some of this,
// we can try to remove at least child_process once we are using a
// Node.js version that supports it.
const lazyNodeBuiltins = ['http', 'https', 'tls', 'child_process'];
const eagerNodeBuiltins = Module.builtinModules.filter(
(m) => !lazyNodeBuiltins.includes(m)
);

const webpackDependenciesPlugin = new WebpackDependenciesPlugin({
outputFilename: path.resolve(
__dirname,
Expand Down Expand Up @@ -38,8 +49,30 @@ const config = {
// @babel/code-frame loads chalk loads supports-color which checks
// for TTY color support during startup rather than at runtime
'@babel/code-frame': makeLazyForwardModule('@babel/code-frame'),
// express is used by oidc-plugin but is a) quite heavy and rarely used
// b) uses http, which is not a supported module for snapshots at this point.
express: makeLazyForwardModule('express'),
'openid-client': makeLazyForwardModule('openid-client'),
...Object.fromEntries(
lazyNodeBuiltins.map((m) => [m, makeLazyForwardModule(m)])
),
...Object.fromEntries(
lazyNodeBuiltins.map((m) => [`node:${m}`, makeLazyForwardModule(m)])
),
},
},

externals: {
electron: 'commonjs2 electron', // optional dep of the OIDC plugin
...Object.fromEntries(eagerNodeBuiltins.map((m) => [m, `commonjs2 ${m}`])),
...Object.fromEntries(
Module.builtinModules.map((m) => [`node:${m}`, `commonjs2 ${m}`])
), // node: builtin specifiers need to be always declared as externals in webpack right now
},

externalsPresets: {
node: false,
},
};

module.exports = merge(baseWebpackConfig, config);
Expand All @@ -57,11 +90,13 @@ function makeLazyForwardModule(pkg) {
crypto.createHash('sha256').update(pkg).digest('hex').slice(0, 16) + '.js'
);

const realRequire = Module.isBuiltin(pkg)
? `__non_webpack_require__(${S(pkg)})`
: `require(${S(require.resolve(pkg))})`;

const moduleContents = require(pkg);
let source = `'use strict';\nlet _cache;\n`;
source += `function orig() {\n_cache = require(${S(
require.resolve(pkg)
)}); orig = () => _cache; return _cache;\n}\n`;
source += `function orig() {\n_cache = ${realRequire}; orig = () => _cache; return _cache;\n}\n`;
if (typeof moduleContents === 'function') {
source += `module.exports = function(...args) { return orig().apply(this, args); };\n`;
} else {
Expand Down
2 changes: 1 addition & 1 deletion packages/logging/src/setup-logger-and-telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { inspect } from 'util';
import type { MongoLogWriter } from 'mongodb-log-writer';
import { mongoLogId } from 'mongodb-log-writer';
import type { MongoshAnalytics } from './analytics-helpers';
import { hookLogger } from '@mongodb-js/devtools-connect';

/**
* A helper class for keeping track of how often specific events occurred.
Expand Down Expand Up @@ -685,7 +686,6 @@ export function setupLoggerAndTelemetry(
// devtools-connect package which was split out from mongosh.
// 'mongodb' is not supported in startup snapshots yet.
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { hookLogger } = require('@mongodb-js/devtools-connect');
hookLogger(bus, log, 'mongosh', redactURICredentials);

bus.on('mongosh-sp:reset-connection-options', function () {
Expand Down
25 changes: 9 additions & 16 deletions packages/service-provider-server/src/cli-service-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import type {
RunCursorCommandOptions,
ClientEncryptionOptions,
MongoClient,
ReadPreference,
MongoMissingDependencyError,
} from 'mongodb';

Expand Down Expand Up @@ -82,12 +81,13 @@ import { EventEmitter } from 'events';
import type { CreateEncryptedCollectionOptions } from '@mongosh/service-provider-core';
import type { DevtoolsConnectionState } from '@mongodb-js/devtools-connect';
import { isDeepStrictEqual } from 'util';

// 'mongodb' is not supported in startup snapshots yet.
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
function driver(): typeof import('mongodb') {
return require('mongodb');
}
import * as driver from 'mongodb';
import {
MongoClient as MongoClientCtor,
ReadPreference,
ClientEncryption,
} from 'mongodb';
import { connectMongoClient } from '@mongodb-js/devtools-connect';

const bsonlib = () => {
const {
Expand All @@ -105,7 +105,7 @@ const bsonlib = () => {
BSONSymbol,
BSONRegExp,
BSON,
} = driver();
} = driver;
return {
Binary,
Code,
Expand Down Expand Up @@ -229,9 +229,6 @@ class CliServiceProvider
};
}

const { MongoClient: MongoClientCtor } = driver();
const { connectMongoClient } = require('@mongodb-js/devtools-connect');

let client: MongoClient;
let state: DevtoolsConnectionState | undefined;
if (cliOptions.nodb) {
Expand Down Expand Up @@ -312,7 +309,7 @@ class CliServiceProvider
return {
nodeDriverVersion: tryCall(() => require('mongodb/package.json').version),
libmongocryptVersion: tryCall(
() => driver().ClientEncryption.libmongocryptVersion // getter that actually loads the native addon (!)
() => ClientEncryption.libmongocryptVersion // getter that actually loads the native addon (!)
),
libmongocryptNodeBindingsVersion: tryCall(
() => require('mongodb-client-encryption/package.json').version
Expand Down Expand Up @@ -371,8 +368,6 @@ class CliServiceProvider
connectionString: ConnectionString | string,
clientOptions: DevtoolsConnectOptions
): Promise<{ client: MongoClient; state: DevtoolsConnectionState }> {
const { MongoClient: MongoClientCtor } = driver();
const { connectMongoClient } = require('@mongodb-js/devtools-connect');
try {
return await connectMongoClient(
connectionString.toString(),
Expand Down Expand Up @@ -1302,7 +1297,6 @@ class CliServiceProvider
readPreferenceFromOptions(
options?: Omit<ReadPreferenceFromOptions, 'session'>
): ReadPreferenceLike | undefined {
const { ReadPreference } = driver();
return ReadPreference.fromOptions(options);
}

Expand Down Expand Up @@ -1509,7 +1503,6 @@ class CliServiceProvider
createClientEncryption(
options: ClientEncryptionOptions
): MongoCryptClientEncryption {
const { ClientEncryption } = driver();
return new ClientEncryption(this.mongoClient, options);
}
}
Expand Down