diff --git a/.gitignore b/.gitignore index 632d9ee372d..da1e1fe9ff2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,25 @@ npm-debug.log -build/ -dist/ +build +dist node_modules .DS_Store -.idea/ +.idea *.swp *.iml .cache* report.json -.user-data/ -.compiled-sources/ +.user-data +.compiled-sources expansions.yml .nvmrc .vscode +!.vscode/extentions.json .migration-cache lerna-debug.log packages/**/*.tgz packages/**/package-lock.json tmp -# Verdaccio storage path storage +.nyc_output +coverage .ackrc diff --git a/.vscode/extentions.json b/.vscode/extentions.json new file mode 100644 index 00000000000..b498296f940 --- /dev/null +++ b/.vscode/extentions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "mike-lischke.vscode-antlr4" + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 42befd58655..9ec96960552 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,66 +17,108 @@ MongoDB welcomes community contributions! If you’re interested in making a con You can report new bugs by [creating a new issue](https://jira.mongodb.org/browse/COMPASS/). Please include as much information as possible about your environment. ## VSCode Setup -Make sure to have the following steps completed to get the best development experience: -1. Install the [prettier VSCode plugin](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) and make sure to set the `prettier.requireConfig` option for the workspace! This will ensure only packages that have `prettier` enabled will get formatted. - -## Creating a new package - -To create a new package, follow the outlined steps: - -1. Set up a basic NPM package in the `packages/` directory. -2. To configure TypeScript: - 1. Add the `@mongodb-js/tsconfig-compass` package as a `devDependency`. - 2. Add the required `typescript` dependency. - 3. Add a `tsconfig.json`, make it extend from `@mongodb-js/tsconfig-compass/tsconfig.react.json` if you plan on using React or extend from `@mongodb-js/tsconfig-compass/tsconfig.common.json` otherwise, and modify additional settings as follows: - ``` - { - "extends": "@mongodb-js/tsconfig-compass/tsconfig..json", - "compilerOptions": { - "outDir": "lib", - }, - "include": [ - "src/**/*" - ], - "exclude": [ - "src/**/*.spec.*" - ] - } - ``` - _Note that you **must** set the `outDir` explicitly as it is always relative to the config file it is declared in!_ - 4. For linting purposes, add another `tsconfig-lint.json` to include all source files: - ``` - { - "extends": "./tsconfig.json", - "include": ["**/*"], - "exclude": ["node_modules", "lib"] - } - ``` -3. To configure `eslint`: - 1. Add the `@mongodb-js/eslint-config-compass` package as a `devDependency`. - 2. Set up an `.eslintrc.js` with the following content: - ``` - module.exports = { - root: true, - extends: [ - '@mongodb-js/eslint-config-compass' - ], - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig-lint.json'] - } - } - ``` - 3. Add an `.eslintignore` with the following content: - ``` - lib/ - ``` -4. To configure `prettier`: - 1. Add the `prettier` package as a `devDependency`. - 2. Set up a `.prettierignore` file with the following content: - ``` - lib - .nyc_output - ``` - 3. Add an `.prettierrc.json` file with just `"@mongodb-js/prettier-config-compass"` as contents. -5. For setting up typical packages tasks and depcheck refer to existing packages like [`compass-components`](./packages/compass-components). Make sure to add `@mongodb-js/tsconfig-compass` and `@mongodb-js/prettier-config-compass` to the ignored packages in `.depcheckrc`. + +This repository includes a few recommended plugins for your convenience: + +- Prettier extension helps to format your code following this repository code style. + > ⚠️  If you install the [Prettier VSCode extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) please make sure to set the `prettier.requireConfig` option for the workspace! This will ensure only packages that have `prettier` enabled will get formatted. +- ESLint extension highlights possible issues in your code following our common eslint configuration. +- ANTLR4 grammar support extension helps to work with the `bson-transpilers` package that is implemented with the help of antlr (.g and .g4 files). + +## Working With the Monorepo + +You'll need node `^12.9.0` and npm `7` installed on your machine to work with the repository locally. After your environment is ready, navigate to the repository and run `npm run bootstrap`, this will install dependencies and will compile all packages. + +After bootstrap is finished, you should be able to run `npm run start` and see Compass application running locally. + +This monorepo is powered by [`npm workspaces`](https://docs.npmjs.com/cli/v7/using-npm/workspaces) an [`lerna`](https://github.com/lerna/lerna#readme), although not necessary, it might be helpful to have a high level understanding of those tools. + +### Working on Plugins + +Most of the plugins have their own development environment so you can work on them in isolation. If you want to work on a plugin without running the whole Compass application, you can run `npm run start` in the plugin directory (such as at the top of the `compass/packages/compass-connect` directory), either with the help of `lerna` or `npm workspaces`. For example, to start `compass-connect` plugin locally, you can either run `npm run start --workspace @mongodb-js/compass-connect` from the top of `compass` directory, run `npx lerna run start --scope @mongodb-js/compass-connect --stream` from anywhere in the `compass` directory, or run `npm run start` from the top of the `compass/packages/compass-connect` directory. Same approaches will work for any other workspace-specific script. If you want to run commands like `test` or `check` only for one specific workspace in the repository, you can use any of the methods described above. As an example, to run all tests in one plugin that you are working on such as the `compass-connect` plugin, you can run `npm run test` from the top of the `compass/packages/compass-connect` directory. + +If you want to see your changes applied in Compass, you might need to rebuild plugins that you changed with the `compile` command. Instead of manually writing out the `scope` you might want to use `lerna --since` filter to rebuild everything since your local or origin `HEAD` of the git history: `npx lerna run compile --stream --since origin/HEAD`. Restarting or hard-reloading (Shift+CMD+R) Compass after compilation is finished should apply your changes. + +In addition to running lerna commands directly, there are a few convenient npm scripts for working with packages: + +- `npm run compile-changed` will compile all plugins and their dependants changed since `origin/HEAD` +- `npm run test-changed` will run tests in all packages and their dependants changed since `origin/HEAD`. +- `npm run check-changed` will run `eslint` and `depcheck` validation in all packages (ignoring dependants) changed since `origin/HEAD` + +### Building Compass Locally + +To build compass you can run `package-compass` script in the scope of `mongodb-compass` workspace: + +```sh +npm run package-compass --workspace mongodb-compass +``` + +This command requires a bunch of environment variables provided (`HADRON_PRODUCT`, `HADRON_PRODUCT_NAME`, `HADRON_DISTRIBUTION`, etc) so for your convenience there is a script provided that sets all those vars to some default values and will take care of generating a required package-lock.json file for the compass workspace + +```sh +npm run test-package-compass +``` + +To speed up the process you might want to disable creating installer for the application. To do that you can set `HADRON_SKIP_INSTALLER` environmental variable to `true` when running the script + +```sh +HADRON_SKIP_INSTALLER=true npm run test-package-compass +``` + +### Publishing Packages + +For package changes to be applied in Compass beta or GA releases they need to be published first. The whole publish process happens from the main branch with the following command in order: + +1. `npm run packages-version [semver bump]`: updates package versions for everything that was changed since the last release, updates package-lock file at the root of the repository, commits and tags the changes. See lerna docs to learn more about optional [`semver bump`](https://github.com/lerna/lerna/tree/main/commands/version#semver-bump) argument. +1. `npm run packages-publish`: publishes packages to the registry, if your npm account uses OTP publishing protection get ready to enter the code a few times, as an alternative you might want to use [npm automation authorization tokens](https://docs.npmjs.com/creating-and-viewing-access-tokens) locally if OTP gets in the way too much (in that case add a [`--no-verify-access`](https://github.com/lerna/lerna/tree/main/commands/publish#--no-verify-access) flag to the publish command). Publish command can be re-run safely multiple times, so if something bad happens mid-release (e.g., your internet goes out), you should be able to safely fiinish the process. After publish finishes successfully the script will push version update commit and tags created in step 1. We do it automatically only post-release so that when evergreen picks up a commit in the main branch, all the tasks can run with the packages already published. + +### Add / Update / Remove Dependencies in Packages + +To add, remove, or update a dependency in any workspace you can use the usual `npm install` with a `--workspace` argument added, e.g. to add `react-aria` dependency to compass-connect and compass-query-bar plugins you can run `npm install --save react-aria --workspace @mongodb-js/compass-connect --workspace @mongodb-js/compass-query-bar`. + +Additionally if you want to update a version of an existing dependency, but don't want to figure out the scope manually, you can use `npm run where` helper script. To update `webpack` in every package that has it as a dev dependency you can run `npm run where "devDependencies['webpack']" -- install --save-dev webpack@latest` + +### Creating a New Workspace / Package + +To create a new package please use the `create-workspace` npm script: + +```sh +npm run create-workspace [workspace name] +``` + +This will do all the initial workspace bootstrapping for you, ensuring that your package has all the standard configs set up and ready, and all the npm scripts aligned with other packages in the monorepo, which is important to get the most out of all the provided helpers in this repository (like `npm run check-changed` commands or to make sure that your tests will not immediately fail in CI because of the test timeout being too small) + +### Caveats + +#### `hdiutil: couldn't unmount "diskn" - Resource busy` or Similar `hdiutil` Errors + + + +Sometimes when trying to package compass on macOS you can run into the said error. There doesn't seems to be any common solution to it and the reasons are probably related to the outdated versions of some electron packages we are currently using (but will eventually update). If you are running into that issue, you can disable creating an installer during the packaging process by setting `HADRON_SKIP_INSTALLER` env variable to `true`: + +```sh +HADRON_SKIP_INSTALLER=true npm run test-package-compass +``` + +#### `Module did not self-register` or `Module '' was compiled against a different Node.js version` Errors + + + +When running Compass application or tests suites locally, you might run into errors like the following: + +``` +Error: Module did not self-register: '/path/to/native/module.node'. +``` + +``` +Error: The module '/path/to/native/module.node' was compiled against a different Node.js version using NODE_MODULE_VERSION $XYZ. This version of Node.js requires NODE_MODULE_VERSION $ABC. +``` + +The root cause is native modules compiled for a different version of the runtime (either Node.js or Electron) that tries to import the module. In our case this is usually caused by combination of two things: + +1. Modules have to be recompiled for the runtime they will be used in +1. Due to npm workspaces hoisting all shared dependencies to the very root of the monorepo, all packages use the same modules imported from the same location + +This means that if you e.g., start Compass application locally it will recompile all native modules to work in Electron runtime, if you would try to run tests for `mongodb-connection-model` library right after that, tests would fail due to `keytar` library not being compatible with Node.js environment that the tests are running in. + +If you run into this issue, make sure that native modules are rebuilt for whatever runtime you are planning to use at the moment. To help with that we provide two npm scripts: `npm run electron-rebuild` will recompile native modules to work with Electron and `npm run node-rebuild` will recompile them to work with Node.js. diff --git a/README.md b/README.md index b9590754e41..571084a452e 100644 --- a/README.md +++ b/README.md @@ -45,12 +45,9 @@ This repository contains the source code and build tooling used in [MongoDB Comp ### Shared Libraries and Build Tools - [**@mongodb-js/compass-components**](packages/compass-components): A set of React Components used in Compass -- [**@mongodb-js/eslint-config-compass**](packages/eslint-config-compass): Shared eslint configuration used in Compass packages. - [**@mongodb-js/hadron-plugin-manager**](packages/hadron-plugin-manager): Hadron Plugin Manager - [**@mongodb-js/mongodb-notary-service-client**](packages/notary-service-client): A client for our notary-service: an API for codesigning. - [**@mongodb-js/mongodb-redux-common**](packages/redux-common): Common Redux Modules for mongodb-js -- [**@mongodb-js/prettier-config-compass**](packages/prettier-config-compass): Shared prettier configurations used in Compass packages. -- [**@mongodb-js/tsconfig-compass**](packages/tsconfig-compass): Shared basic TypeScript configurations used in Compass packages. - [**app-migrations**](packages/app-migrations): Helper for application schema migrations. - [**compass-preferences-model**](packages/compass-preferences-model): Compass preferences model. - [**compass-user-model**](packages/compass-user-model): MongoDB user model. @@ -85,100 +82,19 @@ This repository contains the source code and build tooling used in [MongoDB Comp - [**mongodb-security**](packages/security): Portable business logic of MongoDB security model - [**storage-mixin**](packages/storage-mixin): Ampersand model mixin to persist data via various storage backends -## Working With the Monorepo +### Shared Configuration Files -You'll need node ^12.9.0 and npm 7 installed on your machine to work with the repository locally. After your environment is ready, navigate to the repository and run `npm run bootstrap`, this will install dependencies and will compile all packages. - -After bootstrap is finished, you should be able to run `npm run start` and see Compass application running locally. - -This monorepo is powered by [`npm workspaces`](https://docs.npmjs.com/cli/v7/using-npm/workspaces) an [`lerna`](https://github.com/lerna/lerna#readme), although not necessary, it might be helpful to have a high level understanding of those tools. - -### Working on Plugins - -Most of the plugins have their own development environment so you can work on them in isolation. If you want to work on a plugin without running the whole Compass application, you can run `npm run start` in the plugin directory (such as at the top of the `compass/packages/compass-connect` directory), either with the help of `lerna` or `npm workspaces`. For example, to start `compass-connect` plugin locally, you can either run `npm run start --workspace @mongodb-js/compass-connect` from the top of `compass` directory, run `npx lerna run start --scope @mongodb-js/compass-connect --stream` from anywhere in the `compass` directory, or run `npm run start` from the top of the `compass/packages/compass-connect` directory. Same approaches will work for any other workspace-specific script. If you want to run commands like `test` or `check` only for one specific workspace in the repository, you can use any of the methods described above. As an example, to run all tests in one plugin that you are working on such as the `compass-connect` plugin, you can run `npm run test` from the top of the `compass/packages/compass-connect` directory. - -If you want to see your changes applied in Compass, you might need to rebuild plugins that you changed with the `compile` command. Instead of manually writing out the `scope` you might want to use `lerna --since` filter to rebuild everything since your local or origin `HEAD` of the git history: `npx lerna run compile --stream --since origin/HEAD`. Restarting or hard-reloading (Shift+CMD+R) Compass after compilation is finished should apply your changes. - -In addition to running lerna commands directly, there are a few convenient npm scripts for working with packages: - -- `npm run compile-changed` will compile all plugins and their dependants changed since `origin/HEAD` -- `npm run test-changed` will run tests in all packages and their dependants changed since `origin/HEAD`. -- `npm run check-changed` will run `eslint` and `depcheck` validation in all packages (ignoring dependants) changed since `origin/HEAD` - -### Building Compass Locally - -To build compass you can run `package-compass` script in the scope of `mongodb-compass` workspace: - -```sh -npm run package-compass --workspace mongodb-compass -``` - -This command requires a bunch of environment variables provided (`HADRON_PRODUCT`, `HADRON_PRODUCT_NAME`, `HADRON_DISTRIBUTION`, etc) so for your convenience there is a script provided that sets all those vars to some default values and will take care of generating a required package-lock.json file for the compass workspace - -```sh -npm run test-package-compass -``` - -To speed up the process you might want to disable creating installer for the application. To do that you can set `HADRON_SKIP_INSTALLER` environmental variable to `true` when running the script - -```sh -HADRON_SKIP_INSTALLER=true npm run test-package-compass -``` - -### Caveats - -#### `hdiutil: couldn't unmount "diskn" - Resource busy` or Similar `hdiutil` Errors - - - -Sometimes when trying to package compass on macOS you can run into the said error. There doesn't seems to be any common solution to it and the reasons are probably related to the outdated versions of some electron packages we are currently using (but will eventually update). If you are running into that issue, you can disable creating an installer during the packaging process by setting `HADRON_SKIP_INSTALLER` env variable to `true`: - -```sh -HADRON_SKIP_INSTALLER=true npm run test-package-compass -``` - -#### `Module did not self-register` or `Module '' was compiled against a different Node.js version` Errors - - - -When running Compass application or tests suites locally, you might run into errors like the following: - -``` -Error: Module did not self-register: '/path/to/native/module.node'. -``` - -``` -Error: The module '/path/to/native/module.node' was compiled against a different Node.js version using NODE_MODULE_VERSION $XYZ. This version of Node.js requires NODE_MODULE_VERSION $ABC. -``` - -The root cause is native modules compiled for a different version of the runtime (either Node.js or Electron) that tries to import the module. In our case this is usually caused by combination of two things: - -1. Modules have to be recompiled for the runtime they will be used in -1. Due to npm workspaces hoisting all shared dependencies to the very root of the monorepo, all packages use the same modules imported from the same location - -This means that if you e.g., start Compass application locally it will recompile all native modules to work in Electron runtime, if you would try to run tests for `mongodb-connection-model` library right after that, tests would fail due to `keytar` library not being compatible with Node.js environment that the tests are running in. - -If you run into this issue, make sure that native modules are rebuilt for whatever runtime you are planning to use at the moment. To help with that we provide two npm scripts: `npm run electron-rebuild` will recompile native modules to work with Electron and `npm run node-rebuild` will recompile them to work with Node.js. - -### Publishing Packages - -For package changes to be applied in Compass beta or GA releases they need to be published first. The whole publish process happens from the main branch with the following command in order: - -1. `npm run packages-version [semver bump]`: updates package versions for everything that was changed since the last release, updates package-lock file at the root of the repository, commits and tags the changes. See lerna docs to learn more about optional [`semver bump`](https://github.com/lerna/lerna/tree/main/commands/version#semver-bump) argument. -1. `npm run packages-publish`: publishes packages to the registry, if your npm account uses OTP publishing protection get ready to enter the code a few times, as an alternative you might want to use [npm automation authorization tokens](https://docs.npmjs.com/creating-and-viewing-access-tokens) locally if OTP gets in the way too much (in that case add a [`--no-verify-access`](https://github.com/lerna/lerna/tree/main/commands/publish#--no-verify-access) flag to the publish command). Publish command can be re-run safely multiple times, so if something bad happens mid-release (e.g., your internet goes out), you should be able to safely fiinish the process. After publish finishes successfully the script will push version update commit and tags created in step 1. We do it automatically only post-release so that when evergreen picks up a commit in the main branch, all the tasks can run with the packages already published. - -### Add / Update / Remove Dependencies in Packages - -To add, remove, or update a dependency in any workspace you can use the usual `npm install` with a `--workspace` argument added, e.g. to add `react-aria` dependency to compass-connect and compass-query-bar plugins you can run `npm install --save react-aria --workspace @mongodb-js/compass-connect --workspace @mongodb-js/compass-query-bar`. - -Additionally if you want to update a version of an existing dependency, but don't want to figure out the scope manually, you can use `npm run where` helper script. To update `webpack` in every package that has it as a dev dependency you can run `npm run where "devDependencies['webpack']" -- install --save-dev webpack@latest` +- [**@mongodb-js/eslint-config-compass**](configs/eslint-config-compass): Shared eslint configuration used in Compass packages. +- [**@mongodb-js/mocha-config-compass**](configs/mocha-config-compass): Shared mocha configuration used in Compass packages. +- [**@mongodb-js/prettier-config-compass**](configs/prettier-config-compass): Shared prettier configurations used in Compass packages. +- [**@mongodb-js/tsconfig-compass**](configs/tsconfig-compass): Shared basic TypeScript configurations used in Compass packages. ## Contributing -For issues, please create a ticket in our [JIRA Project](https://jira.mongodb.org/browse/COMPASS). - For contributing, please refer to [CONTRIBUTING.md](CONTRIBUTING.md) +For issues, please create a ticket in our [JIRA Project](https://jira.mongodb.org/browse/COMPASS). + Is there anything else you’d like to see in Compass? Let us know by submitting suggestions in out [feedback forum](https://feedback.mongodb.com/forums/924283-compass). ## License diff --git a/packages/eslint-config-compass/.gitignore b/configs/eslint-config-compass/.gitignore similarity index 100% rename from packages/eslint-config-compass/.gitignore rename to configs/eslint-config-compass/.gitignore diff --git a/packages/prettier-config-compass/.prettierrc.json b/configs/eslint-config-compass/.prettierrc.json similarity index 100% rename from packages/prettier-config-compass/.prettierrc.json rename to configs/eslint-config-compass/.prettierrc.json diff --git a/packages/eslint-config-compass/README.md b/configs/eslint-config-compass/README.md similarity index 100% rename from packages/eslint-config-compass/README.md rename to configs/eslint-config-compass/README.md diff --git a/configs/eslint-config-compass/index.js b/configs/eslint-config-compass/index.js new file mode 100644 index 00000000000..fa63b5e1048 --- /dev/null +++ b/configs/eslint-config-compass/index.js @@ -0,0 +1,71 @@ +const jsConfigurations = ['eslint:recommended']; + +const tsConfigurations = [ + ...jsConfigurations, + 'plugin:@typescript-eslint/recommended', + 'plugin:@typescript-eslint/recommended-requiring-type-checking', +]; +const tsRules = { + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-return': 'off', +}; + +const reactConfigurations = [ + 'plugin:react/recommended', + 'plugin:jsx-a11y/recommended', +]; + +const testConfigurations = ['plugin:mocha/recommended']; + +module.exports = { + plugins: ['@typescript-eslint', 'jsx-a11y', 'mocha', 'react'], + env: { node: true }, + overrides: [ + { + parserOptions: { + ecmaVersion: 2018, + }, + files: ['**/*.js'], + env: { node: true, es6: true }, + extends: [...jsConfigurations, 'prettier'], + }, + { + parser: '@typescript-eslint/parser', + files: ['**/*.ts'], + extends: [...tsConfigurations, 'prettier'], + rules: { ...tsRules }, + }, + { + parserOptions: { + ecmaVersion: 2018, + }, + files: ['**/*.jsx'], + env: { node: true, browser: true, es6: true }, + extends: [...jsConfigurations, ...reactConfigurations, 'prettier'], + }, + { + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + files: ['**/*.tsx'], + env: { node: true, browser: true }, + extends: [...tsConfigurations, ...reactConfigurations, 'prettier'], + rules: { ...tsRules }, + }, + { + files: ['**/*.spec.js', '**/*.spec.jsx', '**/*.spec.ts', '**/*.spec.tsx'], + env: { mocha: true }, + extends: [...testConfigurations], + }, + ], + settings: { + react: { + version: 'detect', + }, + }, +}; diff --git a/packages/eslint-config-compass/package.json b/configs/eslint-config-compass/package.json similarity index 100% rename from packages/eslint-config-compass/package.json rename to configs/eslint-config-compass/package.json diff --git a/configs/mocha-config-compass/.gitignore b/configs/mocha-config-compass/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/tsconfig-compass/.prettierrc.json b/configs/mocha-config-compass/.prettierrc.json similarity index 100% rename from packages/tsconfig-compass/.prettierrc.json rename to configs/mocha-config-compass/.prettierrc.json diff --git a/configs/mocha-config-compass/README.md b/configs/mocha-config-compass/README.md new file mode 100644 index 00000000000..2f1a9cae31b --- /dev/null +++ b/configs/mocha-config-compass/README.md @@ -0,0 +1,25 @@ +# @mongodb-js/mocha-config-compass + +> Shared [mocha][mocha] configuration for Compass packages. + +## Usage + +For general-purpose packages install as dependency and add the following configuration file + +```js +// file:/.mocharc.js +module.exports = require('@mongodb-js/mocha-config-compass'); +``` + +This configuration activates the colors and sets default timeout to 15 seconds (helpful for CI runs). It also registers `ts-node` so that you can run tests written in typescript without compiling them first + +For packages that are intended for the browser use the following configuration file + +```js +// file:/.mocharc.js +module.exports = require('@mongodb-js/mocha-config-compass/react'); +``` + +This configuration extends on the general-purpose one, but also adds `jsdom` to the environment and registers `chai-dom` helpers (if you don't have chai-dom types installed already you should add them with `npm i -D @types/chai-dom`) + +[mocha]: https://mochajs.org/#configuring-mocha-nodejs diff --git a/configs/mocha-config-compass/chai-dom-register.js b/configs/mocha-config-compass/chai-dom-register.js new file mode 100644 index 00000000000..74068093cf7 --- /dev/null +++ b/configs/mocha-config-compass/chai-dom-register.js @@ -0,0 +1,4 @@ +const chai = require('chai'); +const chaiDom = require('chai-dom'); + +chai.use(chaiDom); diff --git a/configs/mocha-config-compass/index.js b/configs/mocha-config-compass/index.js new file mode 100644 index 00000000000..a212b49465c --- /dev/null +++ b/configs/mocha-config-compass/index.js @@ -0,0 +1,12 @@ +const path = require('path'); + +module.exports = { + colors: true, + timeout: 15000, + require: [ + 'ts-node/register', + path.resolve(__dirname, 'sinon-chai-register.js'), + ], + spec: 'src/**/*.spec.*', + watchFiles: 'src/**/*', +}; diff --git a/configs/mocha-config-compass/package.json b/configs/mocha-config-compass/package.json new file mode 100644 index 00000000000..ce738f23045 --- /dev/null +++ b/configs/mocha-config-compass/package.json @@ -0,0 +1,33 @@ +{ + "name": "@mongodb-js/mocha-config-compass", + "version": "0.1.0", + "description": "Shared mocha mocha configuration for Compass packages", + "license": "SSPL", + "main": "index.js", + "devDependencies": { + "@mongodb-js/prettier-config-compass": "0.1.0", + "prettier": "2.3.2" + }, + "scripts": { + "prettier": "prettier", + "lint": "npm run prettier -- --check .", + "check": "npm run lint", + "check-ci": "npm run lint", + "reformat": "npm run prettier -- --write ." + }, + "repository": { + "type": "git", + "url": "https://github.com/mongodb-js/compass.git" + }, + "homepage": "https://github.com/mongodb-js/compass", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "chai": "^4.3.4", + "chai-dom": "^1.9.0", + "jsdom-global": "^3.0.2", + "sinon-chai": "^3.7.0", + "ts-node": "^10.2.1" + } +} diff --git a/configs/mocha-config-compass/react.js b/configs/mocha-config-compass/react.js new file mode 100644 index 00000000000..d75a705f994 --- /dev/null +++ b/configs/mocha-config-compass/react.js @@ -0,0 +1,10 @@ +const path = require('path'); +const base = require('./'); + +module.exports = { + ...base, + require: base.require.concat([ + 'jsdom-global/register', + path.resolve(__dirname, 'chai-dom-register.js'), + ]), +}; diff --git a/configs/mocha-config-compass/sinon-chai-register.js b/configs/mocha-config-compass/sinon-chai-register.js new file mode 100644 index 00000000000..7f94e8abcec --- /dev/null +++ b/configs/mocha-config-compass/sinon-chai-register.js @@ -0,0 +1,4 @@ +const chai = require('chai'); +const sinonChai = require('sinon-chai'); + +chai.use(sinonChai); diff --git a/packages/prettier-config-compass/.gitignore b/configs/prettier-config-compass/.gitignore similarity index 100% rename from packages/prettier-config-compass/.gitignore rename to configs/prettier-config-compass/.gitignore diff --git a/configs/prettier-config-compass/.prettierrc.json b/configs/prettier-config-compass/.prettierrc.json new file mode 100644 index 00000000000..18853d1532e --- /dev/null +++ b/configs/prettier-config-compass/.prettierrc.json @@ -0,0 +1 @@ +"@mongodb-js/prettier-config-compass" diff --git a/packages/prettier-config-compass/README.md b/configs/prettier-config-compass/README.md similarity index 100% rename from packages/prettier-config-compass/README.md rename to configs/prettier-config-compass/README.md diff --git a/packages/prettier-config-compass/index.json b/configs/prettier-config-compass/index.json similarity index 100% rename from packages/prettier-config-compass/index.json rename to configs/prettier-config-compass/index.json diff --git a/packages/prettier-config-compass/package.json b/configs/prettier-config-compass/package.json similarity index 100% rename from packages/prettier-config-compass/package.json rename to configs/prettier-config-compass/package.json diff --git a/packages/tsconfig-compass/.gitignore b/configs/tsconfig-compass/.gitignore similarity index 100% rename from packages/tsconfig-compass/.gitignore rename to configs/tsconfig-compass/.gitignore diff --git a/configs/tsconfig-compass/.prettierrc.json b/configs/tsconfig-compass/.prettierrc.json new file mode 100644 index 00000000000..18853d1532e --- /dev/null +++ b/configs/tsconfig-compass/.prettierrc.json @@ -0,0 +1 @@ +"@mongodb-js/prettier-config-compass" diff --git a/packages/tsconfig-compass/README.md b/configs/tsconfig-compass/README.md similarity index 100% rename from packages/tsconfig-compass/README.md rename to configs/tsconfig-compass/README.md diff --git a/packages/tsconfig-compass/package.json b/configs/tsconfig-compass/package.json similarity index 100% rename from packages/tsconfig-compass/package.json rename to configs/tsconfig-compass/package.json diff --git a/packages/tsconfig-compass/tsconfig.common.json b/configs/tsconfig-compass/tsconfig.common.json similarity index 100% rename from packages/tsconfig-compass/tsconfig.common.json rename to configs/tsconfig-compass/tsconfig.common.json diff --git a/packages/tsconfig-compass/tsconfig.react.json b/configs/tsconfig-compass/tsconfig.react.json similarity index 100% rename from packages/tsconfig-compass/tsconfig.react.json rename to configs/tsconfig-compass/tsconfig.react.json diff --git a/lerna.json b/lerna.json index a2bb50ba7ca..fb43a1ace68 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,4 @@ { - "packages": [ - "packages/*" - ], + "packages": ["packages/*", "configs/*"], "version": "independent" } diff --git a/package-lock.json b/package-lock.json index f0f0078b30c..0c1766d7616 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,8 @@ "name": "mongodb-compass-monorepo", "license": "SSPL", "workspaces": [ - "packages/*" + "packages/*", + "configs/*" ], "devDependencies": { "chalk": "^4.1.1", @@ -18,7 +19,9 @@ "minimist": "^1.2.5", "npm-cli-adduser": "^1.1.4", "ora": "^5.4.0", + "pacote": "^11.3.5", "pkg-up": "^3.1.0", + "prompts": "^2.4.1", "ps-list": "^7.2.0", "semver": "^7.3.5", "wait-on": "^5.3.0" @@ -28,6 +31,64 @@ "npm": ">=7.16.0" } }, + "configs/eslint-config-compass": { + "name": "@mongodb-js/eslint-config-compass", + "version": "0.1.0", + "license": "SSPL", + "dependencies": { + "@typescript-eslint/eslint-plugin": "^4.28.4", + "@typescript-eslint/parser": "^4.28.4", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-jsx-a11y": "^6.4.1", + "eslint-plugin-mocha": "^8.0.0", + "eslint-plugin-react": "^7.24.0" + }, + "devDependencies": { + "prettier": "2.3.2" + }, + "peerDependencies": { + "eslint": "^7.25.0" + } + }, + "configs/mocha-config-compass": { + "name": "@mongodb-js/mocha-config-compass", + "version": "0.1.0", + "license": "SSPL", + "dependencies": { + "chai": "^4.3.4", + "chai-dom": "^1.9.0", + "jsdom-global": "^3.0.2", + "sinon-chai": "^3.7.0", + "ts-node": "^10.2.1" + }, + "devDependencies": { + "@mongodb-js/prettier-config-compass": "0.1.0", + "prettier": "2.3.2" + } + }, + "configs/prettier-config-compass": { + "name": "@mongodb-js/prettier-config-compass", + "version": "0.1.0", + "license": "SSPL", + "devDependencies": { + "prettier": "2.3.2" + }, + "peerDependencies": { + "prettier": "2.3.2" + } + }, + "configs/tsconfig-compass": { + "name": "@mongodb-js/tsconfig-compass", + "version": "0.1.0", + "license": "SSPL", + "devDependencies": { + "@mongodb-js/prettier-config-compass": "*", + "prettier": "2.3.2" + }, + "peerDependencies": { + "typescript": "^4.3.5" + } + }, "node_modules/@babel/cli": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.14.5.tgz", @@ -1945,6 +2006,25 @@ "node": ">=6.9.0" } }, + "node_modules/@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz", + "integrity": "sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg==", + "dependencies": { + "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@dabh/diagnostics": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", @@ -4454,13 +4534,17 @@ } }, "node_modules/@mongodb-js/eslint-config-compass": { - "resolved": "packages/eslint-config-compass", + "resolved": "configs/eslint-config-compass", "link": true }, "node_modules/@mongodb-js/hadron-plugin-manager": { "resolved": "packages/hadron-plugin-manager", "link": true }, + "node_modules/@mongodb-js/mocha-config-compass": { + "resolved": "configs/mocha-config-compass", + "link": true + }, "node_modules/@mongodb-js/mongodb-notary-service-client": { "resolved": "packages/notary-service-client", "link": true @@ -4470,7 +4554,7 @@ "link": true }, "node_modules/@mongodb-js/prettier-config-compass": { - "resolved": "packages/prettier-config-compass", + "resolved": "configs/prettier-config-compass", "link": true }, "node_modules/@mongodb-js/ssh-tunnel": { @@ -4482,7 +4566,7 @@ } }, "node_modules/@mongodb-js/tsconfig-compass": { - "resolved": "packages/tsconfig-compass", + "resolved": "configs/tsconfig-compass", "link": true }, "node_modules/@mongosh/async-rewriter2": { @@ -5775,26 +5859,22 @@ "node_modules/@tsconfig/node10": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", - "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==" }, "node_modules/@tsconfig/node12": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", - "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==" }, "node_modules/@tsconfig/node14": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", - "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==" }, "node_modules/@tsconfig/node16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", - "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==" }, "node_modules/@types/aria-query": { "version": "4.2.2", @@ -8154,8 +8234,7 @@ "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" }, "node_modules/argparse": { "version": "1.0.10", @@ -10653,7 +10732,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", - "dev": true, "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", @@ -10682,7 +10760,6 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/chai-dom/-/chai-dom-1.9.0.tgz", "integrity": "sha512-UXSbhcGVBWv/5qVqbJY/giTDRyo3wKapUsWluEuVvxcJLFXkyf8l4D2PTd6trzrmca6WWnGdpaFkYdl1P0WjtA==", - "dev": true, "engines": { "node": ">= 0.12.0" }, @@ -10758,7 +10835,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true, "engines": { "node": "*" } @@ -12214,8 +12290,7 @@ "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, "node_modules/cross-env": { "version": "7.0.3", @@ -13126,7 +13201,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, "dependencies": { "type-detect": "^4.0.0" }, @@ -20536,7 +20610,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true, "engines": { "node": "*" } @@ -24673,7 +24746,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-3.0.2.tgz", "integrity": "sha1-a9KZwTsMRiay2iwDk81DhdYGrLk=", - "dev": true, "peerDependencies": { "jsdom": ">=10.0.0" } @@ -25708,6 +25780,15 @@ "graceful-fs": "^4.1.9" } }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -28774,8 +28855,7 @@ "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" }, "node_modules/make-fetch-happen": { "version": "8.0.14", @@ -36311,7 +36391,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, "engines": { "node": "*" } @@ -37479,6 +37558,19 @@ "integrity": "sha512-bNwZusuNIW4m0SPR8jooSyndD35ggirHlxVl/UhIaZD/F0OBv9ebfc6tNmbpZts3QXHggkjIBH8lvtnzhtcz0A==", "dev": true }, + "node_modules/prompts": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", + "integrity": "sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/promzard": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz", @@ -40411,7 +40503,6 @@ "version": "3.7.0", "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", - "dev": true, "peerDependencies": { "chai": "^4.0.0", "sinon": ">=4.0.0" @@ -40461,6 +40552,12 @@ "path-to-regexp": "^1.7.0" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -42925,20 +43022,21 @@ "dev": true }, "node_modules/ts-node": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.1.0.tgz", - "integrity": "sha512-6szn3+J9WyG2hE+5W8e0ruZrzyk1uFLYye6IGMBadnOzDh8aP7t8CbFpsfCiEx2+wMixAhjFt7lOZC4+l+WbEA==", - "dev": true, + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.2.1.tgz", + "integrity": "sha512-hCnyOyuGmD5wHleOQX6NIjJtYVIO8bPP8F2acWkB4W06wdlkgyvJtubO/I9NkI88hCFECbsEgoLc0VNkYmcSfw==", "dependencies": { + "@cspotcode/source-map-support": "0.6.1", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.1", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "source-map-support": "^0.5.17", "yn": "3.1.1" }, "bin": { @@ -42966,11 +43064,18 @@ } } }, + "node_modules/ts-node/node_modules/acorn-walk": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.1.1.tgz", + "integrity": "sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ts-node/node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, "engines": { "node": ">=0.3.1" } @@ -47076,7 +47181,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, "engines": { "node": ">=6" } @@ -54465,16 +54569,16 @@ "@leafygreen-ui/confirmation-modal": "^2.2.1" }, "devDependencies": { - "@mongodb-js/eslint-config-compass": "*", - "@mongodb-js/prettier-config-compass": "*", - "@mongodb-js/tsconfig-compass": "*", + "@mongodb-js/eslint-config-compass": "^0.1.0", + "@mongodb-js/mocha-config-compass": "^0.1.0", + "@mongodb-js/prettier-config-compass": "^0.1.0", + "@mongodb-js/tsconfig-compass": "^0.1.0", "@testing-library/react": "^12.0.0", "@types/chai": "^4.2.21", "@types/chai-dom": "^0.0.10", "@types/mocha": "^9.0.0", "@types/react": "^17.0.5", "chai": "^4.3.4", - "chai-dom": "^1.9.0", "eslint": "^7.25.0", "jsdom-global": "^3.0.2", "mocha": "^8.4.0", @@ -90934,9 +91038,10 @@ "mongodb-security": "^1.3.0" }, "devDependencies": { - "@mongodb-js/eslint-config-compass": "*", - "@mongodb-js/prettier-config-compass": "*", - "@mongodb-js/tsconfig-compass": "*", + "@mongodb-js/eslint-config-compass": "^0.1.0", + "@mongodb-js/mocha-config-compass": "^0.1.0", + "@mongodb-js/prettier-config-compass": "^0.1.0", + "@mongodb-js/tsconfig-compass": "^0.1.0", "@types/async": "^3.2.7", "@types/debug": "^4.1.7", "@types/lodash": "^4.14.172", @@ -93170,25 +93275,6 @@ "node": ">=0.10.0" } }, - "packages/eslint-config-compass": { - "name": "@mongodb-js/eslint-config-compass", - "version": "0.1.0", - "license": "SSPL", - "dependencies": { - "@typescript-eslint/eslint-plugin": "^4.28.4", - "@typescript-eslint/parser": "^4.28.4", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-jsx-a11y": "^6.4.1", - "eslint-plugin-mocha": "^8.0.0", - "eslint-plugin-react": "^7.24.0" - }, - "devDependencies": { - "prettier": "2.3.2" - }, - "peerDependencies": { - "eslint": "^7.25.0" - } - }, "packages/explain-plan-model": { "name": "mongodb-explain-plan-model", "version": "1.3.0", @@ -98435,17 +98521,6 @@ "node": ">=0.10.0" } }, - "packages/prettier-config-compass": { - "name": "@mongodb-js/prettier-config-compass", - "version": "0.1.0", - "license": "SSPL", - "devDependencies": { - "prettier": "2.3.2" - }, - "peerDependencies": { - "prettier": "2.3.2" - } - }, "packages/redux-common": { "name": "@mongodb-js/mongodb-redux-common", "version": "1.4.0", @@ -100643,18 +100718,6 @@ "mocha": "^7.0.0", "xvfb-maybe": "^0.2.1" } - }, - "packages/tsconfig-compass": { - "name": "@mongodb-js/tsconfig-compass", - "version": "0.1.0", - "license": "SSPL", - "devDependencies": { - "@mongodb-js/prettier-config-compass": "*", - "prettier": "2.3.2" - }, - "peerDependencies": { - "typescript": "^4.3.5" - } } }, "dependencies": { @@ -101995,6 +102058,19 @@ "to-fast-properties": "^2.0.0" } }, + "@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==" + }, + "@cspotcode/source-map-support": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz", + "integrity": "sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg==", + "requires": { + "@cspotcode/source-map-consumer": "0.8.0" + } + }, "@dabh/diagnostics": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", @@ -108554,16 +108630,16 @@ "version": "file:packages/compass-components", "requires": { "@leafygreen-ui/confirmation-modal": "^2.2.1", - "@mongodb-js/eslint-config-compass": "*", - "@mongodb-js/prettier-config-compass": "*", - "@mongodb-js/tsconfig-compass": "*", + "@mongodb-js/eslint-config-compass": "^0.1.0", + "@mongodb-js/mocha-config-compass": "^0.1.0", + "@mongodb-js/prettier-config-compass": "^0.1.0", + "@mongodb-js/tsconfig-compass": "^0.1.0", "@testing-library/react": "^12.0.0", "@types/chai": "^4.2.21", "@types/chai-dom": "^0.0.10", "@types/mocha": "^9.0.0", "@types/react": "^17.0.5", "chai": "^4.3.4", - "chai-dom": "^1.9.0", "eslint": "^7.25.0", "jsdom-global": "^3.0.2", "mocha": "^8.4.0", @@ -133337,7 +133413,7 @@ } }, "@mongodb-js/eslint-config-compass": { - "version": "file:packages/eslint-config-compass", + "version": "file:configs/eslint-config-compass", "requires": { "@typescript-eslint/eslint-plugin": "^4.28.4", "@typescript-eslint/parser": "^4.28.4", @@ -134095,6 +134171,18 @@ } } }, + "@mongodb-js/mocha-config-compass": { + "version": "file:configs/mocha-config-compass", + "requires": { + "@mongodb-js/prettier-config-compass": "0.1.0", + "chai": "^4.3.4", + "chai-dom": "^1.9.0", + "jsdom-global": "^3.0.2", + "prettier": "2.3.2", + "sinon-chai": "^3.7.0", + "ts-node": "^10.2.1" + } + }, "@mongodb-js/mongodb-notary-service-client": { "version": "file:packages/notary-service-client", "requires": { @@ -135874,7 +135962,7 @@ } }, "@mongodb-js/prettier-config-compass": { - "version": "file:packages/prettier-config-compass", + "version": "file:configs/prettier-config-compass", "requires": { "prettier": "2.3.2" } @@ -135888,7 +135976,7 @@ } }, "@mongodb-js/tsconfig-compass": { - "version": "file:packages/tsconfig-compass", + "version": "file:configs/tsconfig-compass", "requires": { "@mongodb-js/prettier-config-compass": "*", "prettier": "2.3.2" @@ -136968,26 +137056,22 @@ "@tsconfig/node10": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", - "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==" }, "@tsconfig/node12": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", - "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==" }, "@tsconfig/node14": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", - "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==" }, "@tsconfig/node16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", - "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==" }, "@types/aria-query": { "version": "4.2.2", @@ -139101,8 +139185,7 @@ "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" }, "argparse": { "version": "1.0.10", @@ -142058,7 +142141,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", - "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", @@ -142080,8 +142162,7 @@ "chai-dom": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/chai-dom/-/chai-dom-1.9.0.tgz", - "integrity": "sha512-UXSbhcGVBWv/5qVqbJY/giTDRyo3wKapUsWluEuVvxcJLFXkyf8l4D2PTd6trzrmca6WWnGdpaFkYdl1P0WjtA==", - "dev": true + "integrity": "sha512-UXSbhcGVBWv/5qVqbJY/giTDRyo3wKapUsWluEuVvxcJLFXkyf8l4D2PTd6trzrmca6WWnGdpaFkYdl1P0WjtA==" }, "chai-enzyme": { "version": "1.0.0-beta.1", @@ -142130,8 +142211,7 @@ "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, "check-types": { "version": "8.0.3", @@ -145992,8 +146072,7 @@ "create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, "cross-env": { "version": "7.0.3", @@ -146713,7 +146792,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, "requires": { "type-detect": "^4.0.0" } @@ -153459,8 +153537,7 @@ "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" }, "get-intrinsic": { "version": "1.1.1", @@ -158537,8 +158614,7 @@ "jsdom-global": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-3.0.2.tgz", - "integrity": "sha1-a9KZwTsMRiay2iwDk81DhdYGrLk=", - "dev": true + "integrity": "sha1-a9KZwTsMRiay2iwDk81DhdYGrLk=" }, "jsesc": { "version": "2.5.2", @@ -159374,6 +159450,12 @@ "graceful-fs": "^4.1.9" } }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, "kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -162209,8 +162291,7 @@ "make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" }, "make-fetch-happen": { "version": "8.0.14", @@ -165312,9 +165393,10 @@ "mongodb-data-service": { "version": "file:packages/data-service", "requires": { - "@mongodb-js/eslint-config-compass": "*", - "@mongodb-js/prettier-config-compass": "*", - "@mongodb-js/tsconfig-compass": "*", + "@mongodb-js/eslint-config-compass": "^0.1.0", + "@mongodb-js/mocha-config-compass": "^0.1.0", + "@mongodb-js/prettier-config-compass": "^0.1.0", + "@mongodb-js/tsconfig-compass": "^0.1.0", "@types/async": "^3.2.7", "@types/debug": "^4.1.7", "@types/lodash": "^4.14.172", @@ -171987,8 +172069,7 @@ "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==" }, "pause-stream": { "version": "0.0.11", @@ -172923,6 +173004,16 @@ "integrity": "sha512-bNwZusuNIW4m0SPR8jooSyndD35ggirHlxVl/UhIaZD/F0OBv9ebfc6tNmbpZts3QXHggkjIBH8lvtnzhtcz0A==", "dev": true }, + "prompts": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", + "integrity": "sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, "promzard": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz", @@ -175377,7 +175468,12 @@ "sinon-chai": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", - "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", + "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==" + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true }, "slash": { @@ -177484,28 +177580,33 @@ "dev": true }, "ts-node": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.1.0.tgz", - "integrity": "sha512-6szn3+J9WyG2hE+5W8e0ruZrzyk1uFLYye6IGMBadnOzDh8aP7t8CbFpsfCiEx2+wMixAhjFt7lOZC4+l+WbEA==", - "dev": true, + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.2.1.tgz", + "integrity": "sha512-hCnyOyuGmD5wHleOQX6NIjJtYVIO8bPP8F2acWkB4W06wdlkgyvJtubO/I9NkI88hCFECbsEgoLc0VNkYmcSfw==", "requires": { + "@cspotcode/source-map-support": "0.6.1", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.1", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "source-map-support": "^0.5.17", "yn": "3.1.1" }, "dependencies": { + "acorn-walk": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.1.1.tgz", + "integrity": "sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==" + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" } } }, @@ -180808,8 +180909,7 @@ "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" }, "yocto-queue": { "version": "0.1.0", diff --git a/package.json b/package.json index 1f7bed24a27..d310ad3ed21 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "update-authors": "node scripts/generate-authors.js", "update-third-party-notices": "node scripts/gather-licenses.js packages/compass/ > THIRD-PARTY-NOTICES.md", "version": "node ./scripts/bump-private-dependencies.js --no-commit", - "where": "node ./scripts/monorepo/where.js" + "where": "node ./scripts/monorepo/where.js", + "create-workspace": "node ./scripts/create-workspace.js" }, "repository": { "type": "git", @@ -55,7 +56,9 @@ "minimist": "^1.2.5", "npm-cli-adduser": "^1.1.4", "ora": "^5.4.0", + "pacote": "^11.3.5", "pkg-up": "^3.1.0", + "prompts": "^2.4.1", "ps-list": "^7.2.0", "semver": "^7.3.5", "wait-on": "^5.3.0" @@ -69,6 +72,7 @@ "email": "compass@mongodb.com" }, "workspaces": [ - "packages/*" + "packages/*", + "configs/*" ] } diff --git a/packages/compass-components/.depcheckrc b/packages/compass-components/.depcheckrc index 266cce001cd..e4302ca6d32 100644 --- a/packages/compass-components/.depcheckrc +++ b/packages/compass-components/.depcheckrc @@ -2,5 +2,6 @@ ignores: [ "jsdom-global", "ts-node", "@mongodb-js/prettier-config-compass", - "@mongodb-js/tsconfig-compass" + "@mongodb-js/tsconfig-compass", + "@types/chai-dom" ] diff --git a/packages/compass-components/.gitignore b/packages/compass-components/.gitignore index 173bbad7a0d..7951405f85a 100644 --- a/packages/compass-components/.gitignore +++ b/packages/compass-components/.gitignore @@ -1,5 +1 @@ -.nyc_output -node_modules -package-lock.json -coverage -lib +lib \ No newline at end of file diff --git a/packages/compass-components/.mocharc.js b/packages/compass-components/.mocharc.js new file mode 100644 index 00000000000..30aecfb78c3 --- /dev/null +++ b/packages/compass-components/.mocharc.js @@ -0,0 +1 @@ +module.exports = require('@mongodb-js/mocha-config-compass/react'); diff --git a/packages/compass-components/package.json b/packages/compass-components/package.json index dd89f1c0f07..eaa28ad2a02 100644 --- a/packages/compass-components/package.json +++ b/packages/compass-components/package.json @@ -15,21 +15,22 @@ "README.md" ], "scripts": { - "check": "npm run lint && npm run depcheck", - "check-ci": "npm run check", - "clean": "rimraf lib", "bootstrap": "npm run compile", + "prepublishOnly": "npm run compile", + "clean": "rimraf lib", "precompile": "npm run clean", - "compile": "npm run compile-ts && gen-esm-wrapper . ./lib/.esm-wrapper.mjs", - "compile-ts": "tsc -p tsconfig.json", - "cover": "nyc npm run test", + "compile": "tsc -p tsconfig.json && gen-esm-wrapper . ./lib/.esm-wrapper.mjs", + "eslint": "eslint", + "prettier": "prettier", + "lint": "npm run eslint . && npm run prettier -- --check .", "depcheck": "depcheck", - "lint": "eslint . && prettier --check .", - "prepublishOnly": "npm run compile", - "pretest": "npm run compile", - "test": "nyc mocha --colors -r jsdom-global/register -r ts-node/register -r test-setup.ts src/**/*.spec.tsx", - "test-ci": "npm run test", - "reformat": "prettier --write ." + "check": "npm run lint && npm run depcheck", + "check-ci": "npm run check", + "test": "mocha", + "test-cov": "cross-env TS_NODE_FILES=true nyc -x \"**/*.spec.*\" npm run test", + "test-watch": "npm run test -- --watch", + "test-ci": "npm run test-cov", + "reformat": "npm run prettier -- --write ." }, "dependencies": { "@leafygreen-ui/confirmation-modal": "^2.2.1" @@ -38,16 +39,16 @@ "react": "^16.14.0" }, "devDependencies": { - "@mongodb-js/eslint-config-compass": "*", - "@mongodb-js/prettier-config-compass": "*", - "@mongodb-js/tsconfig-compass": "*", + "@mongodb-js/eslint-config-compass": "^0.1.0", + "@mongodb-js/mocha-config-compass": "^0.1.0", + "@mongodb-js/prettier-config-compass": "^0.1.0", + "@mongodb-js/tsconfig-compass": "^0.1.0", "@testing-library/react": "^12.0.0", "@types/chai": "^4.2.21", "@types/chai-dom": "^0.0.10", "@types/mocha": "^9.0.0", "@types/react": "^17.0.5", "chai": "^4.3.4", - "chai-dom": "^1.9.0", "eslint": "^7.25.0", "jsdom-global": "^3.0.2", "mocha": "^8.4.0", diff --git a/packages/compass-components/test-setup.ts b/packages/compass-components/test-setup.ts deleted file mode 100644 index a0b1ca2f247..00000000000 --- a/packages/compass-components/test-setup.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as chai from 'chai'; -import chaiDom from 'chai-dom'; - -chai.use(chaiDom); diff --git a/packages/data-service/.gitignore b/packages/data-service/.gitignore index f318d57a226..a895e8d89f1 100644 --- a/packages/data-service/.gitignore +++ b/packages/data-service/.gitignore @@ -2,11 +2,9 @@ npm-debug.log node_modules/ lib-cov -coverage .lock-wscript .idea/ *.iml .nvmrc *.swp lib/ -.nyc_output/ diff --git a/packages/data-service/.mocharc.js b/packages/data-service/.mocharc.js new file mode 100644 index 00000000000..7e473d17b76 --- /dev/null +++ b/packages/data-service/.mocharc.js @@ -0,0 +1 @@ +module.exports = require('@mongodb-js/mocha-config-compass'); diff --git a/packages/data-service/package.json b/packages/data-service/package.json index ba76a26e451..e134eb0cd46 100644 --- a/packages/data-service/package.json +++ b/packages/data-service/package.json @@ -31,27 +31,26 @@ "README.md" ], "scripts": { - "check": "npm run lint && npm run depcheck", - "check-ci": "npm run check", + "bootstrap": "npm run compile", + "prepublishOnly": "npm run compile", "clean": "rimraf lib", "precompile": "npm run clean", - "compile": "npm run compile-ts && gen-esm-wrapper . ./lib/.esm-wrapper.mjs", - "compile-ts": "tsc -p tsconfig.json", - "cover": "nyc npm run test", + "compile": "tsc -p tsconfig.json && gen-esm-wrapper . ./lib/.esm-wrapper.mjs", + "eslint": "eslint", + "prettier": "prettier", + "lint": "npm run eslint . && npm run prettier -- --check .", "depcheck": "depcheck", - "lint": "eslint . && prettier --check .", - "bootstrap": "npm run compile", - "prepublishOnly": "npm run compile", + "check": "npm run lint && npm run depcheck", + "check-ci": "npm run check", "pretest": "npm run compile && mongodb-runner start --port=27018", - "test": "cross-env TS_NODE_FILES=true nyc mocha --colors --timeout 15000 -r ts-node/register src/**/*.spec.*", - "test-ci": "npm run test", + "test": "mocha", "posttest": "mongodb-runner stop --port=27018", + "test-cov": "cross-env TS_NODE_FILES=true nyc -x \"**/*.spec.*\" npm run test", + "test-watch": "npm run test -- --watch", + "test-ci": "npm run test-cov", "posttest-ci": "node ../../scripts/killall-mongo.js", - "reformat": "prettier --write ." + "reformat": "npm run prettier -- --write ." }, - "pre-commit": [ - "check" - ], "peerDependencies": { "mongodb": "^4.1.0", "mongodb-connection-model": "*" @@ -67,9 +66,10 @@ "mongodb-security": "^1.3.0" }, "devDependencies": { - "@mongodb-js/eslint-config-compass": "*", - "@mongodb-js/prettier-config-compass": "*", - "@mongodb-js/tsconfig-compass": "*", + "@mongodb-js/eslint-config-compass": "^0.1.0", + "@mongodb-js/mocha-config-compass": "^0.1.0", + "@mongodb-js/prettier-config-compass": "^0.1.0", + "@mongodb-js/tsconfig-compass": "^0.1.0", "@types/async": "^3.2.7", "@types/debug": "^4.1.7", "@types/lodash": "^4.14.172", diff --git a/packages/eslint-config-compass/.prettierrc.json b/packages/eslint-config-compass/.prettierrc.json deleted file mode 100644 index 0967ef424bc..00000000000 --- a/packages/eslint-config-compass/.prettierrc.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/packages/eslint-config-compass/index.js b/packages/eslint-config-compass/index.js deleted file mode 100644 index 3a3590ab162..00000000000 --- a/packages/eslint-config-compass/index.js +++ /dev/null @@ -1,71 +0,0 @@ -const jsConfigurations = ["eslint:recommended"]; - -const tsConfigurations = [ - ...jsConfigurations, - "plugin:@typescript-eslint/recommended", - "plugin:@typescript-eslint/recommended-requiring-type-checking", -]; -const tsRules = { - "@typescript-eslint/no-unsafe-assignment": "off", - "@typescript-eslint/no-unsafe-call": "off", - "@typescript-eslint/no-unsafe-member-access": "off", - "@typescript-eslint/no-unsafe-return": "off", -}; - -const reactConfigurations = [ - "plugin:react/recommended", - "plugin:jsx-a11y/recommended", -]; - -const testConfigurations = ["plugin:mocha/recommended"]; - -module.exports = { - plugins: ["@typescript-eslint", "jsx-a11y", "mocha", "react"], - env: { node: true }, - overrides: [ - { - parserOptions: { - ecmaVersion: 2018, - }, - files: ["**/*.js"], - env: { node: true, es6: true }, - extends: [...jsConfigurations, "prettier"], - }, - { - parser: "@typescript-eslint/parser", - files: ["**/*.ts"], - extends: [...tsConfigurations, "prettier"], - rules: { ...tsRules }, - }, - { - parserOptions: { - ecmaVersion: 2018, - }, - files: ["**/*.jsx"], - env: { node: true, browser: true, es6: true }, - extends: [...jsConfigurations, ...reactConfigurations, "prettier"], - }, - { - parser: "@typescript-eslint/parser", - parserOptions: { - ecmaFeatures: { - jsx: true, - }, - }, - files: ["**/*.tsx"], - env: { node: true, browser: true }, - extends: [...tsConfigurations, ...reactConfigurations, "prettier"], - rules: { ...tsRules }, - }, - { - files: ["**/*.spec.js", "**/*.spec.jsx", "**/*.spec.ts", "**/*.spec.tsx"], - env: { mocha: true }, - extends: [...testConfigurations], - }, - ], - settings: { - react: { - version: "detect", - }, - }, -}; diff --git a/scripts/create-workspace.js b/scripts/create-workspace.js new file mode 100644 index 00000000000..5ceb4256667 --- /dev/null +++ b/scripts/create-workspace.js @@ -0,0 +1,402 @@ +const path = require('path'); +const { promises: fs } = require('fs'); +const prompts = require('prompts'); +const pacote = require('pacote'); +const { + collectWorkspacesDependencies, + collectWorkspacesMeta +} = require('./workspace-dependencies'); +const { getHighestRange } = require('./semver-helpers'); +const { runInDir } = require('./run-in-dir'); +const { updatePackageJson } = require('./monorepo/update-package-json'); +const { withProgress } = require('./monorepo/with-progress'); + +function packageNameToDir(pkgName) { + return pkgName ? pkgName.replace(/^@mongodb-js\//, '') : pkgName; +} + +function dirToScopedPackageName(dir) { + return dir.startsWith('@mongodb-js/') ? dir : `@mongodb-js/${dir}`; +} + +async function main(argv) { + let workspaceNameFromArgs = argv[0]; + const workspacesMeta = await collectWorkspacesMeta(); + const dirs = Array.from(workspacesMeta.values()).map(({ location }) => + path.basename(location) + ); + const names = Array.from(workspacesMeta.values()).map(({ name }) => name); + + const nameExists = (pkgName) => { + return dirs.includes(packageNameToDir(pkgName)) || names.includes(pkgName); + }; + + console.log(); + + if (nameExists(workspaceNameFromArgs)) { + console.warn( + `⚠️ Workspace with the name "%s" already exists, please choose another name`, + workspaceNameFromArgs + ); + console.warn(); + workspaceNameFromArgs = null; + } + + if (workspaceNameFromArgs) { + console.log('Setting up new workspace "%s"', workspaceNameFromArgs); + console.log(); + } + + let canceled = false; + + const { + name = workspaceNameFromArgs, + description, + isPublic, + react, + dependants, + depType + } = await prompts( + [ + { + type: workspaceNameFromArgs ? null : 'text', + name: 'name', + message: 'Provide a name for the new workspace', + hint: '(this name will be part of the package name)', + validate(value) { + if (!value) { + return 'Workspace name is required'; + } + + if (nameExists(value)) { + return `Workspace name "${value}" is already taken. Please provide another name`; + } + + return true; + } + }, + { + type: 'text', + name: 'description', + message: 'Provide a one-line description of the workspace' + }, + { + type: 'confirm', + name: 'isPublic', + message: 'Is it a public package?', + initial: true + }, + { + type: 'confirm', + name: 'react', + message: 'Will the package use React?', + initial: true + }, + { + type: 'autocompleteMultiselect', + name: 'dependants', + message: 'Will any of the packages in the monorepo depend on this one?', + choices: Array.from(workspacesMeta.values()) + .sort((a, b) => a.name.localeCompare(b.name)) + .map(({ name, location }) => ({ title: name, value: location })), + hint: '(select as many as you like, or none)', + instructions: ` + + · Use up and down arrows to navigate the list + · Use space to toggle the selection + · Type text to filter choices + · Enter to complete the answer +`, + initial: [] + }, + { + type(prev) { + return prev.length > 0 ? 'select' : null; + }, + name: 'depType', + message: 'What type of dependency is it?', + choices: [ + { title: 'Production', value: 'dependencies' }, + { title: 'Development', value: 'devDependencies' } + ] + } + ], + { + onCancel() { + canceled = true; + } + } + ); + + if (canceled) { + return; + } + + console.log(); + + const pkgJson = { + name: dirToScopedPackageName(name), + ...(description && { description }), + author: { + name: 'MongoDB Inc', + email: 'compass@mongodb.com' + }, + ...(isPublic ? { publishConfig: { access: 'public' } } : { private: true }), + bugs: { + url: 'https://jira.mongodb.org/projects/COMPASS/issues', + email: 'compass@mongodb.com' + }, + homepage: 'https://github.com/mongodb-js/compass', + version: '0.1.0', + repository: { + type: 'git', + url: 'https://github.com/mongodb-js/compass.git' + }, + files: ['dist'], + license: 'SSPL', + main: 'dist/index.js', + exports: { + require: './dist/index.js', + import: './dist/.esm-wrapper.mjs' + }, + types: './dist/index.d.ts', + scripts: { + bootstrap: 'npm run compile', + prepublishOnly: 'npm run compile', + compile: + 'tsc -p tsconfig.json && gen-esm-wrapper . ./dist/.esm-wrapper.mjs', + eslint: 'eslint', + prettier: 'prettier', + lint: 'npm run eslint . && npm run prettier -- --check .', + depcheck: 'depcheck', + check: 'npm run lint && npm run depcheck', + 'check-ci': 'npm run check', + test: 'mocha', + 'test-cov': + 'cross-env TS_NODE_FILES=true nyc -x "**/*.spec.*" npm run test', + 'test-watch': 'npm run test -- --watch', + 'test-ci': 'npm run test-cov', + reformat: 'npm run prettier -- --write .' + }, + ...(react && { peerDependencies: { react: '*', 'react-dom': '*' } }), + ...(react && { dependencies: { react: '*', 'react-dom': '*' } }), + devDependencies: { + '@mongodb-js/eslint-config-compass': '*', + '@mongodb-js/mocha-config-compass': '*', + '@mongodb-js/prettier-config-compass': '*', + '@mongodb-js/tsconfig-compass': '*', + '@types/chai': '*', + '@types/mocha': '*', + '@types/sinon-chai': '*', + 'cross-env': '*', + chai: '*', + depcheck: '*', + eslint: '*', + mocha: '*', + nyc: '*', + prettier: '*', + sinon: '*', + typescript: '*', + ...(react && { + '@testing-library/react': '*', + '@types/chai-dom': '*', + '@types/react': '*', + '@types/react-dom': '*' + }) + } + }; + + await applyBestVersionMatch(pkgJson, workspacesMeta); + // Otherwise npm will do this on next install and generate an unwanted diff + sortDepsByName(pkgJson); + + const packagePath = path.resolve( + __dirname, + '..', + 'packages', + packageNameToDir(name) + ); + + const packageJsonPath = path.join(packagePath, 'package.json'); + const packageJsonContent = JSON.stringify(pkgJson, null, 2); + + const depcheckrcPath = path.join(packagePath, '.depcheckrc'); + const ignores = [ + '@mongodb-js/prettier-config-compass', + '@mongodb-js/tsconfig-compass', + '@types/chai', + '@types/sinon-chai', + 'sinon' + ] + .concat( + react ? ['@types/chai-dom', '@types/react', '@types/react-dom'] : [] + ) + .map((dep) => ` - "${dep}"`) + .join('\n'); + const depcheckrcContent = `ignores:\n${ignores}\n`; + + const prettierrcPath = path.join(packagePath, '.prettierrc.json'); + const prettierrcContent = JSON.stringify( + '@mongodb-js/prettier-config-compass' + ); + + const prettierIgnorePath = path.join(packagePath, '.prettierignore'); + const prettierIgnoreContent = '.nyc-output\ndist\n'; + + const tsconfigPath = path.join(packagePath, 'tsconfig.json'); + const tsconfigContent = JSON.stringify( + { + extends: `@mongodb-js/tsconfig-compass/tsconfig.${ + react ? 'react' : 'common' + }.json`, + compilerOptions: { + outDir: 'dist' + }, + include: ['src/**/*'], + exclude: ['./src/**/*.spec.*'] + }, + null, + 2 + ); + + const tsconfigLintPath = path.join(packagePath, 'tsconfig-lint.json'); + const tsconfigLintContent = JSON.stringify( + { + extends: './tsconfig.json', + include: ['**/*'], + exclude: ['node_modules', 'dist'] + }, + null, + 2 + ); + + const eslintrcPath = path.join(packagePath, '.eslintrc.js'); + const eslintrcContent = ` +module.exports = { + root: true, + extends: ['@mongodb-js/eslint-config-compass'], + parserOptions: { + tsconfigRootDir: __dirname, + project: ['./tsconfig-lint.json'], + }, +};`; + + const eslintIgnorePath = path.join(packagePath, '.eslintignore'); + const eslintIgnoreContent = '.nyc-output\ndist\n'; + + const mocharcPath = path.join(packagePath, '.mocharc.js'); + const mocharcContent = `module.exports = require('${ + react + ? '@mongodb-js/mocha-config-compass/react' + : '@mongodb-js/mocha-config-compass' + }');`; + + const indexSrcDir = path.join(packagePath, 'src'); + const indexSrcPath = path.join(indexSrcDir, 'index.ts'); + const indexSpecPath = path.join(indexSrcDir, 'index.spec.ts'); + + await withProgress('Generating package source', async () => { + await fs.mkdir(packagePath, { recursive: true }); + await fs.writeFile(packageJsonPath, packageJsonContent); + await fs.writeFile(depcheckrcPath, depcheckrcContent); + await fs.writeFile(prettierrcPath, prettierrcContent); + await fs.writeFile(prettierIgnorePath, prettierIgnoreContent); + await fs.writeFile(tsconfigPath, tsconfigContent); + await fs.writeFile(tsconfigLintPath, tsconfigLintContent); + await fs.writeFile(eslintrcPath, eslintrcContent); + await fs.writeFile(eslintIgnorePath, eslintIgnoreContent); + await fs.writeFile(mocharcPath, mocharcContent); + await fs.mkdir(indexSrcDir, { recursive: true }); + await fs.writeFile(indexSrcPath, ''); + await fs.writeFile(indexSpecPath, ''); + }); + + if (dependants.length > 0) { + await withProgress('Updating dependants', async () => { + for (const location of dependants) { + await updatePackageJson(location, (pkgJson) => { + if (!pkgJson[depType]) { + pkgJson[depType] = {}; + } + pkgJson[depType][dirToScopedPackageName(name)] = '^0.1.0'; + sortDepsByName(pkgJson, [depType]); + return pkgJson; + }); + } + }); + } + + await withProgress( + 'Updating package-lock and prettifying workspace source', + async () => { + await runInDir('npm install'); + await runInDir('npm run reformat', packagePath); + } + ); + + console.log(); + console.log( + 'Workspace is ready at %s', + path.relative(process.cwd(), packagePath) + ); + console.log(); +} + +const BestMatchCache = new Map(); + +async function resolveLatestVersionFromRegistry( + depName, + registry = process.env.npm_config_registry +) { + try { + return `^${(await pacote.manifest(depName, { registry })).version}`; + } catch (e) { + return '*'; + } +} + +async function applyBestVersionMatch( + pkgJson, + meta, + types = ['dependencies', 'devDependencies'] +) { + const dependencies = collectWorkspacesDependencies(meta); + + for (const depType of types) { + for (const depName in pkgJson[depType]) { + if (BestMatchCache.has(depName)) { + pkgJson[depType][depName] = BestMatchCache.get(depName); + } else { + const maybeRanges = (dependencies.get(depName) || []).map( + ({ version }) => version + ); + pkgJson[depType][depName] = + getHighestRange(maybeRanges) || + (await resolveLatestVersionFromRegistry(depName)); + + BestMatchCache.set(depName, pkgJson[depType][depName]); + } + } + } +} + +function sortDepsByName( + pkgJson, + types = ['dependencies', 'devDependencies', 'peerDependencies'] +) { + for (const depType of types) { + if (pkgJson[depType]) { + pkgJson[depType] = Object.fromEntries( + Object.entries(pkgJson[depType]).sort(([a], [b]) => a.localeCompare(b)) + ); + } + } +} + +process.on('unhandledRejection', (err) => { + console.error(); + console.error(err.stack || err.message || err); + process.exitCode = 1; +}); + +main(process.argv.slice(2)); diff --git a/scripts/depalign.js b/scripts/depalign.js index a104357f20a..0e4b8f9fba2 100644 --- a/scripts/depalign.js +++ b/scripts/depalign.js @@ -1,10 +1,15 @@ const path = require('path'); const { promises: fs } = require('fs'); -const semver = require('semver'); const chalk = require('chalk'); const { runInDir } = require('./run-in-dir'); const { updatePackageJson } = require('./monorepo/update-package-json'); const { withProgress } = require('./monorepo/with-progress'); +const { + collectWorkspacesMeta, + collectWorkspacesDependencies, + DepTypes +} = require('./workspace-dependencies'); +const { calculateReplacements, intersects } = require('./semver-helpers'); const USAGE = `Check for dependency alignment issues. @@ -29,10 +34,6 @@ Options: For example: {"ignore": {"async": ["^1.2.3"]}}. `; -const ROOT_DIR = path.resolve(__dirname, '..'); - -const LERNA_BIN = path.join(ROOT_DIR, 'node_modules', '.bin', 'lerna'); - async function main(args) { if (args.help) { console.log(USAGE); @@ -186,74 +187,6 @@ async function main(args) { process.exitCode = report.mismatched.size; } -async function collectWorkspacesMeta() { - const workspaces = JSON.parse( - (await runInDir(`${LERNA_BIN} list --all --json --toposort`)).stdout - ); - - return new Map( - workspaces - .concat({ location: ROOT_DIR }) - .map(({ location }) => [ - location, - require(path.join(location, 'package.json')) - ]) - ); -} - -const DepTypes = { - Prod: 'prod', - Dev: 'dev', - Optional: 'optional', - Peer: 'peer' -}; - -function getDepType(dependency, version, pkgJson) { - return pkgJson.devDependencies && - pkgJson.devDependencies[dependency] === version - ? DepTypes.Dev - : pkgJson.peerDependencies && - pkgJson.peerDependencies[dependency] === version - ? DepTypes.Peer - : pkgJson.optionalDependencies && - pkgJson.optionalDependencies[dependency] === version - ? DepTypes.Optional - : pkgJson.dependencies && pkgJson.dependencies[dependency] === version - ? DepTypes.Prod - : null; -} - -function collectWorkspacesDependencies(workspaces) { - const dependencies = new Map(); - - for (const [location, pkgJson] of workspaces) { - for (const [dependency, versionRange] of [ - ...Object.entries(pkgJson.dependencies || {}), - ...Object.entries(pkgJson.devDependencies || {}), - ...filterOutStarDeps(Object.entries(pkgJson.peerDependencies || {})), - ...filterOutStarDeps(Object.entries(pkgJson.optionalDependencies || {})) - ]) { - const item = { - version: versionRange, - from: location, - type: getDepType(dependency, versionRange, pkgJson) - }; - - if (dependencies.has(dependency)) { - dependencies.get(dependency).push(item); - } else { - dependencies.set(dependency, [item]); - } - } - } - - return dependencies; -} - -function filterOutStarDeps(entries) { - return entries.filter(([, v]) => v !== '*'); -} - function generateReport( dependencies, { includeTypes, includeTypesOnly, ignore = {} } = { ignore: {} } @@ -296,65 +229,6 @@ function generateReport( return report; } -function intersects(range) { - for (const [idx, v1] of Object.entries(range)) { - for (const v2 of range.slice(Number(idx) + 1)) { - try { - if (!semver.intersects(v1, v2)) { - return false; - } - } catch (e) { - return false; - } - } - } - return true; -} - -function calculateReplacements(ranges) { - const replacements = new Map(); - const highestRange = getHighestRange(ranges); - - for (const range of ranges) { - try { - if (semver.subset(highestRange, range)) { - replacements.set(range, highestRange); - } - } catch (e) { - // Range is probably not valid, let's proceed as if there is no - // replacement for it - } - } - - return replacements; -} - -function getHighestRange(ranges) { - const validRanges = ranges.filter( - (range) => semver.validRange(range) && range !== '*' - ); - - const sortedRanges = validRanges.sort((v1, v2) => { - const res = semver.compare(semver.minVersion(v2), semver.minVersion(v1)); - - if (res === 1 || res === -1) { - return res; - } - - if (semver.valid(v1) && !semver.valid(v2)) { - return 1; - } - - if (!semver.valid(v1) && semver.valid(v2)) { - return -1; - } - - return 0; - }); - - return sortedRanges[0] || null; -} - function normalizeIgnore({ deduped, mismatched }, ignore = {}) { const ignoreMap = new Map(Object.entries(ignore)); const mergedReport = new Map([...deduped, ...mismatched]); diff --git a/scripts/monorepo/for-each-package.js b/scripts/monorepo/for-each-package.js index ac45df2895a..2ab023689c6 100644 --- a/scripts/monorepo/for-each-package.js +++ b/scripts/monorepo/for-each-package.js @@ -17,7 +17,6 @@ async function forEachPackage(fn) { const interrupt = () => { interrupted = true; }; - const packagesDir = path.resolve(ROOT, 'packages'); const packages = JSON.parse( (await runInDir(`${LERNA_BIN} list --all --json --toposort`)).stdout ); diff --git a/scripts/semver-helpers.js b/scripts/semver-helpers.js new file mode 100644 index 00000000000..c42d5a887cf --- /dev/null +++ b/scripts/semver-helpers.js @@ -0,0 +1,66 @@ +const semver = require('semver'); + +function intersects(range) { + for (const [idx, v1] of Object.entries(range)) { + for (const v2 of range.slice(Number(idx) + 1)) { + try { + if (!semver.intersects(v1, v2)) { + return false; + } + } catch (e) { + return false; + } + } + } + return true; +} + +function calculateReplacements(ranges) { + const replacements = new Map(); + const highestRange = getHighestRange(ranges); + + for (const range of ranges) { + try { + if (semver.subset(highestRange, range)) { + replacements.set(range, highestRange); + } + } catch (e) { + // Range is probably not valid, let's proceed as if there is no + // replacement for it + } + } + + return replacements; +} + +function getHighestRange(ranges) { + const validRanges = ranges.filter( + (range) => semver.validRange(range) && range !== '*' + ); + + const sortedRanges = validRanges.sort((v1, v2) => { + const res = semver.compare(semver.minVersion(v2), semver.minVersion(v1)); + + if (res === 1 || res === -1) { + return res; + } + + if (semver.valid(v1) && !semver.valid(v2)) { + return 1; + } + + if (!semver.valid(v1) && semver.valid(v2)) { + return -1; + } + + return 0; + }); + + return sortedRanges[0] || null; +} + +module.exports = { + intersects, + calculateReplacements, + getHighestRange +}; diff --git a/scripts/workspace-dependencies.js b/scripts/workspace-dependencies.js new file mode 100644 index 00000000000..c516f879a08 --- /dev/null +++ b/scripts/workspace-dependencies.js @@ -0,0 +1,85 @@ +const path = require('path'); +const { runInDir } = require('./run-in-dir'); + +const ROOT_DIR = path.resolve(__dirname, '..'); + +const LERNA_BIN = path.join(ROOT_DIR, 'node_modules', '.bin', 'lerna'); + +async function collectWorkspacesMeta() { + const workspaces = JSON.parse( + (await runInDir(`${LERNA_BIN} list --all --json --toposort`)).stdout + ); + + return new Map( + workspaces + .concat({ location: ROOT_DIR }) + .map(({ location }) => [ + location, + { ...require(path.join(location, 'package.json')), location } + ]) + ); +} + +const DepTypes = { + Prod: 'prod', + Dev: 'dev', + Optional: 'optional', + Peer: 'peer' +}; + +function getDepType(dependency, version, pkgJson) { + return pkgJson.devDependencies && + pkgJson.devDependencies[dependency] === version + ? DepTypes.Dev + : pkgJson.peerDependencies && + pkgJson.peerDependencies[dependency] === version + ? DepTypes.Peer + : pkgJson.optionalDependencies && + pkgJson.optionalDependencies[dependency] === version + ? DepTypes.Optional + : pkgJson.dependencies && pkgJson.dependencies[dependency] === version + ? DepTypes.Prod + : null; +} + +/** + * + * @param {Map} workspaces + * @returns {Map} + */ +function collectWorkspacesDependencies(workspaces) { + const dependencies = new Map(); + + for (const [location, pkgJson] of workspaces) { + for (const [dependency, versionRange] of [ + ...Object.entries(pkgJson.dependencies || {}), + ...Object.entries(pkgJson.devDependencies || {}), + ...filterOutStarDeps(Object.entries(pkgJson.peerDependencies || {})), + ...filterOutStarDeps(Object.entries(pkgJson.optionalDependencies || {})) + ]) { + const item = { + version: versionRange, + from: location, + type: getDepType(dependency, versionRange, pkgJson) + }; + + if (dependencies.has(dependency)) { + dependencies.get(dependency).push(item); + } else { + dependencies.set(dependency, [item]); + } + } + } + + return dependencies; +} + +function filterOutStarDeps(entries) { + return entries.filter(([, v]) => v !== '*'); +} + +module.exports = { + DepTypes, + collectWorkspacesMeta, + collectWorkspacesDependencies +};