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

feat(cli-repl): add --eject [WIP] [Skunkworks] #1712

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/arg-parser/src/cli-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,5 @@ export interface CliOptions {
oidcRedirectUri?: string;
oidcTrustedEndpoint?: boolean;
browser?: string | false;
eject?: boolean;
}
1 change: 1 addition & 0 deletions packages/cli-repl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ CLI interface for [MongoDB Shell][mongosh], an extension to Node.js REPL with Mo
--version Show version information
--quiet Silence output from the shell during the connection process
--shell Run the shell after executing files
--eject Execute a script rather than entering a REPL
--nodb Don't connect to mongod on startup - no 'db address' [arg] expected
--norc Will not run the '.mongoshrc.js' file on start up
--eval [arg] Evaluate javascript
Expand Down
1 change: 1 addition & 0 deletions packages/cli-repl/src/arg-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const OPTIONS = {
'apiDeprecationErrors',
'apiStrict',
'buildInfo',
'eject',
'help',
'ipv6',
'nodb',
Expand Down
130 changes: 86 additions & 44 deletions packages/cli-repl/src/cli-repl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ export class CliRepl implements MongoshIOProvider {
driverUri: string,
driverOptions: DevtoolsConnectOptions
): Promise<void> {
const { eject } = this.cliOptions;

const { version } = require('../package.json');
await this.verifyNodeVersion();

Expand Down Expand Up @@ -346,14 +348,20 @@ export class CliRepl implements MongoshIOProvider {
}
throw err;
}
const initialized = await this.mongoshRepl.initialize(
initialServiceProvider,
await this.getMoreRecentMongoshVersion()
);
this.injectReplFunctions();

// no repl if we're gonna eject
let initialized;
if (!eject) {
initialized = await this.mongoshRepl.initialize(
initialServiceProvider,
await this.getMoreRecentMongoshVersion()
);
this.injectReplFunctions();
}

const commandLineLoadFiles = this.cliOptions.fileNames ?? [];
const evalScripts = this.cliOptions.eval ?? [];
// TODO: these should probably be false if we're gonna eject?
const willExecuteCommandLineScripts =
commandLineLoadFiles.length > 0 || evalScripts.length > 0;
const willEnterInteractiveMode =
Expand All @@ -371,48 +379,59 @@ export class CliRepl implements MongoshIOProvider {
}

let snippetManager: SnippetManager | undefined;
if (this.config.snippetIndexSourceURLs !== '') {
snippetManager = SnippetManager.create({
installdir: this.shellHomeDirectory.roamingPath('snippets'),
// no snippets if we're gonna eject
if (!eject) {
if (this.config.snippetIndexSourceURLs !== '') {
snippetManager = SnippetManager.create({
installdir: this.shellHomeDirectory.roamingPath('snippets'),
instanceState: this.mongoshRepl.runtimeState().instanceState,
skipInitialIndexLoad: !willEnterInteractiveMode,
});
}
}

// no editor if we're gonna eject
if (!eject) {
Editor.create({
input: this.input,
vscodeDir: this.shellHomeDirectory.rcPath('.vscode'),
tmpDir: this.shellHomeDirectory.localPath('editor'),
instanceState: this.mongoshRepl.runtimeState().instanceState,
skipInitialIndexLoad: !willEnterInteractiveMode,
loadExternalCode: this.mongoshRepl.loadExternalCode.bind(
this.mongoshRepl
),
});
}

Editor.create({
input: this.input,
vscodeDir: this.shellHomeDirectory.rcPath('.vscode'),
tmpDir: this.shellHomeDirectory.localPath('editor'),
instanceState: this.mongoshRepl.runtimeState().instanceState,
loadExternalCode: this.mongoshRepl.loadExternalCode.bind(
this.mongoshRepl
),
});

if (willExecuteCommandLineScripts) {
this.mongoshRepl.setIsInteractive(willEnterInteractiveMode);
this.bus.emit('mongosh:start-loading-cli-scripts', {
usesShellOption: !!this.cliOptions.shell,
});
const exitCode = await this.loadCommandLineFilesAndEval(
commandLineLoadFiles,
evalScripts
);
if (exitCode !== 0) {
await this.exit(exitCode);
return;
}
if (!this.cliOptions.shell) {
// We flush the telemetry data as part of exiting. Make sure we have
// the right config value.
this.setTelemetryEnabled(await this.getConfig('enableTelemetry'));
await this.exit(0);
return;
// don't do the usual execution of command line scripts if we're gonna eject
if (!eject) {
if (willExecuteCommandLineScripts) {
this.mongoshRepl.setIsInteractive(willEnterInteractiveMode);
this.bus.emit('mongosh:start-loading-cli-scripts', {
usesShellOption: !!this.cliOptions.shell,
});
const exitCode = await this.loadCommandLineFilesAndEval(
commandLineLoadFiles,
evalScripts
);
if (exitCode !== 0) {
await this.exit(exitCode);
return;
}
if (!this.cliOptions.shell) {
// We flush the telemetry data as part of exiting. Make sure we have
// the right config value.
this.setTelemetryEnabled(await this.getConfig('enableTelemetry'));
await this.exit(0);
return;
}
} else {
this.mongoshRepl.setIsInteractive(true);
}
} else {
this.mongoshRepl.setIsInteractive(true);
}
if (!this.cliOptions.norc) {

// no snippets if we're gonna eject
if (!this.cliOptions.norc && !eject) {
/**
* We are deliberately loading snippets only after handling command line
* scripts and files:
Expand All @@ -427,15 +446,38 @@ export class CliRepl implements MongoshIOProvider {
*/
await snippetManager?.loadAllSnippets();
}
await this.loadRcFiles();

// TODO: loadRcFiles uses this.mongoshRepl, so we'll have to provide alternative code
if (!eject) {
await this.loadRcFiles();
}

this.verifyPlatformSupport();

// We only enable/disable here, since the rc file/command line scripts
// can disable the telemetry setting.
this.setTelemetryEnabled(await this.getConfig('enableTelemetry'));
this.bus.emit('mongosh:start-mongosh-repl', { version });
await this.mongoshRepl.startRepl(initialized);
if (!eject && initialized) {
this.bus.emit('mongosh:start-mongosh-repl', { version });
await this.mongoshRepl.startRepl(initialized);
}

// TODO: we should probably depend on ts-node somewhere
(await import('ts-node')).register({
/* options */
});

// TODO: relative paths aren't work well here in development because cwd is packages/cli-repl
const fileName = commandLineLoadFiles[0];
console.log(`executing ${fileName}...`);

// TODO: would be nice if we could also dynamically import .js files and have ESM syntax work
const script = await import(fileName);

// TODO: we could pass all sorts of info here, not just the client
await script.run({ client: initialServiceProvider.mongoClient });

await this.exit(0);
}

injectReplFunctions(): void {
Expand Down
1 change: 1 addition & 0 deletions packages/cli-repl/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const USAGE = `
)}
--quiet ${i18n.__('cli-repl.args.quiet')}
--shell ${i18n.__('cli-repl.args.shell')}
--eject ${i18n.__('cli-repl.args.eject')}
--nodb ${i18n.__('cli-repl.args.nodb')}
--norc ${i18n.__('cli-repl.args.norc')}
--eval [arg] ${i18n.__('cli-repl.args.eval')}
Expand Down
1 change: 1 addition & 0 deletions packages/i18n/src/locales/en_US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const translations: Catalog = {
version: 'Show version information',
quiet: 'Silence output from the shell during the connection process',
shell: 'Run the shell after executing files',
eject: 'Execute a script rather than entering the REPL',
nodb: "Don't connect to mongod on startup - no 'db address' [arg] expected",
norc: "Will not run the '.mongoshrc.js' file on start up",
eval: 'Evaluate javascript',
Expand Down