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

fix(browser-repl)!: keep operation in progress COMPASS-8576 MONGOSH-1966 #2284

Merged
merged 33 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
a339feb
Don't lose the isOperationInProgress state when the user switches tabs
lerouxb Nov 28, 2024
6e7d247
minus comment
lerouxb Nov 28, 2024
98430ee
initial like the others for now
lerouxb Dec 4, 2024
4a95d91
progress towards moving Shell to be a function component
lerouxb Dec 4, 2024
5d48859
typo
lerouxb Dec 4, 2024
8587f0d
readme tweaks
lerouxb Dec 4, 2024
2e85187
rm comment
lerouxb Dec 4, 2024
8ca4f52
browser-repl tests using testing library
lerouxb Dec 6, 2024
5ab819b
Merge branch 'main' into keep-operation-in-progress2
lerouxb Dec 6, 2024
45946cb
Update packages/browser-repl/scripts/sync-to-compass.js
lerouxb Dec 9, 2024
4a7f4e9
Update packages/browser-repl/scripts/sync-to-compass.js
lerouxb Dec 9, 2024
5cf7a44
Update packages/browser-repl/src/components/shell.tsx
lerouxb Dec 9, 2024
e3bf5f7
Update packages/browser-repl/src/components/shell.tsx
lerouxb Dec 9, 2024
a87e420
Update packages/browser-repl/src/components/shell.tsx
lerouxb Dec 9, 2024
85143c0
always clear on enter
lerouxb Dec 9, 2024
e54962a
lint
lerouxb Dec 9, 2024
50313a7
Merge branch 'main' into keep-operation-in-progress2
lerouxb Dec 9, 2024
7c3a692
remove darkMode
lerouxb Dec 11, 2024
e24af9f
move the eslint comments
lerouxb Dec 11, 2024
3567fcb
update readme
lerouxb Dec 11, 2024
705f4ff
Merge branch 'main' into keep-operation-in-progress2
lerouxb Dec 11, 2024
be07c02
keep the text value as initialText
lerouxb Dec 11, 2024
686cbc9
and the sandbox
lerouxb Dec 11, 2024
b34b9a4
use shell input container ref
lerouxb Dec 12, 2024
757ef7c
cap history before redacting
lerouxb Dec 12, 2024
72d16b3
unnecessary lint comment
lerouxb Dec 12, 2024
72a438b
editor ref
lerouxb Dec 12, 2024
d0b920d
test fixes
lerouxb Dec 12, 2024
9b15c06
unnecessary import
lerouxb Dec 12, 2024
add38a0
more stable
lerouxb Dec 12, 2024
6f20f37
don't re-run initialEvaluate AND don't lose the output
lerouxb Dec 12, 2024
37e3c8b
optimisation: don't get the shell prompt before executing initialEval…
lerouxb Dec 12, 2024
4e66b19
use refs and update them
lerouxb Dec 13, 2024
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
192 changes: 192 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions packages/browser-repl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,20 @@ const runtime = new IframeRuntime(serviceProvider);
Shell is a React component with the following properties:

- `runtime: Runtime`: The runtime used to evaluate code.
- `onOutputChanged?: (output: readonly ShellOutputEntry[]) => void`: A function called each time the output changes with an array of `ShellOutputEntryes`.
- `onHistoryChanged?: (history: readonly string[]) => void`: A function called each time the history changes with an array of history entries ordered from the most recent to the oldest entry.
- `onOutputChanged?: (output: ShellOutputEntry[]) => void`: A function called each time the output changes with an array of `ShellOutputEntries`.
- `onHistoryChanged?: (history: string[]) => void`: A function called each time the history changes with an array of history entries ordered from the most recent to the oldest entry.
- `onEditorChanged?: (editor: EditorRef | null) => void`: A function called each time the editor ref changes. Can be used to call editor methods.
- `onOperationStarted?: () => void`: A function called when an operation has begun.
- `onOperationEnd?: () => void`: A function called when an operation has completed (both error and success).
- `redactInfo?: boolean`: If set, the shell will omit or redact entries containing sensitive info from history. Defaults to `false`.
- `maxOutputLength?: number`: The maxiumum number of lines to keep in the output. Defaults to `1000`.
- `maxHistoryLength?: number`: The maxiumum number of lines to keep in the history. Defaults to `1000`.
- `initialOutput?: readonly ShellOutputEntry[]`: An array of entries to be displayed in the output area. Can be used to restore the output between sessions, or to setup a greeting message. **Note**: new entries will not be appended to the array.
- `initialHistory?: readonly string[]`: An array of history entries to prepopulate the history.
- `initialEvaluate?: string|string[]`: A set of input strings to evaluate right after shell is mounted.
- `inputText?: string`: Initial text for the input field.
lerouxb marked this conversation as resolved.
Show resolved Hide resolved
- `output?: ShellOutputEntry[]`: An array of entries to be displayed in the output area. Can be used to restore the output between sessions, or to setup a greeting message. **Note**: new entries will not be appended to the array.
Anemy marked this conversation as resolved.
Show resolved Hide resolved
- `history?: readonly string[]`: An array of history entries to prepopulate the history.
Can be used to restore the history between sessions. Entries must be ordered from the most recent to the oldest. Note: new entries will not be appended to the array.
- `isOperationInProgress?: boolean`: Can be used to restore the value between sessions.

### `ShellOutputEntry`

Expand Down
7 changes: 6 additions & 1 deletion packages/browser-repl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"depcheck": "depcheck",
"compile": "tsc -p tsconfig.json",
"prettier": "prettier",
"reformat": "npm run prettier -- --write . && npm run eslint --fix"
"reformat": "npm run prettier -- --write . && npm run eslint --fix",
"sync-to-compass": "node scripts/sync-to-compass.js"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useful in combination with this. Based on https://github.com/mongodb-js/compass/blob/main/packages/compass-web/scripts/sync-dist-to-mms.js

This way you can save a file in browser-repl in mongosh and it hot-reloads in compass.

},
"config": {
"unsafe-perm": true
Expand Down Expand Up @@ -76,6 +77,9 @@
"@mongodb-js/prettier-config-devtools": "^1.0.1",
"@mongodb-js/tsconfig-mongosh": "^1.0.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.8",
"@testing-library/dom": "^8.20.1",
"@testing-library/react": "^12.1.5",
"@testing-library/user-event": "^13.5.0",
"@types/numeral": "^2.0.2",
"@types/react": "^16.9.17",
"@types/react-dom": "^18.0.8",
Expand All @@ -96,6 +100,7 @@
"karma-mocha-reporter": "^2.2.5",
"karma-typescript": "^5.5.4",
"karma-webpack": "^5.0.0",
"lodash": "^4.17.21",
"path-browserify": "^1.0.1",
"prettier": "^2.8.8",
"prop-types": "^15.7.2",
Expand Down
74 changes: 74 additions & 0 deletions packages/browser-repl/scripts/sync-to-compass.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/* eslint-disable no-console */
'use strict';
const fs = require('fs');
const path = require('path');
const child_process = require('child_process');
const { debounce } = require('lodash');
lerouxb marked this conversation as resolved.
Show resolved Hide resolved

if (!process.env.COMPASS_HOME) {
throw new Error('Missing required environment variable $COMPASS_HOME.');
}

const packageDir = path.resolve(__dirname, '..');
const srcDir = path.resolve(__dirname, '..', 'src');
const libDir = path.resolve(__dirname, '..', 'lib');

const destDir = path.dirname(
child_process.execFileSync(
'node',
['-p', "require.resolve('@mongosh/browser-repl')"],
{ cwd: process.env.COMPASS_HOME, encoding: 'utf-8' }
)
);

console.log({ packageDir, srcDir, libDir, destDir });

const compileAndCopy = debounce(
function () {
try {
child_process.execFileSync('npm', ['run', 'compile'], {
cwd: packageDir,
encoding: 'utf-8',
});
} catch (err) {
if (err.code) {
// Spawning child process failed
console.error(err.code);
} else {
// Child was spawned but exited with non-zero exit code
// Error contains any stdout and stderr from the child
const { stdout, stderr } = err;

console.log(stdout);
console.error(stderr);
}
}
fs.cpSync(libDir, destDir, { recursive: true });
console.log('done.');
},
1_000,
{
leading: true,
trailing: true,
}
);

const srcWatcher = fs.watch(
srcDir,
{ recursive: true },
function (eventType, filename) {
console.log(eventType, filename);
compileAndCopy();
}
);

function cleanup() {
srcWatcher.close();
}

for (const evt of ['SIGINT', 'SIGTERM']) {
process.on(evt, cleanup);
}

// do an initial copy on startup
compileAndCopy();
5 changes: 3 additions & 2 deletions packages/browser-repl/src/components/password-prompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ export class PasswordPrompt extends Component<PasswordPromptProps> {

render(): JSX.Element {
return (
<label id="password-promt-label" className={passwordPrompt}>
<label id="password-prompt-label" className={passwordPrompt}>
{this.props.prompt}:&nbsp;
<TextInput
aria-labelledby="password-promt-label"
data-testid="password-prompt"
aria-labelledby="password-prompt-label"
type="password"
onKeyDown={this.onKeyDown}
className={passwordPropmtInputStyles}
Expand Down
9 changes: 6 additions & 3 deletions packages/browser-repl/src/components/shell-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,14 @@ export class ShellInput extends Component<ShellInputProps, ShellInputState> {
};

private onEnter = async (): Promise<void> => {
const value = this.state.currentValue;
// clear the value before evaluating the input because it could take a long
// time
this.setState({ currentValue: '' });

if (this.props.onInput) {
await this.props.onInput(this.state.currentValue);
await this.props.onInput(value);
}

this.setState({ currentValue: '' });
};

render(): JSX.Element {
Expand Down
Loading
Loading