
Security News
Another Round of TEA Protocol Spam Floods npm, But It’s Not a Worm
Recent coverage mislabels the latest TEA protocol spam as a worm. Here’s what’s actually happening.
@spscommerce/mph
Advanced tools
An alternative to lerna for dealing with multiple npm packages in the same repository.
yarn add --dev @spscommerce/mph
You will probably also want to install it globally, so you can run it with mph instead of npx mph:
npm install -g @spscommerce/mph
MPH is based upon the use of yarn workspaces. If you are using npm, you will need to either switch or not use MPH.
MPH is configured via a file in your project root, called mph.json, .mphrc, or .mphrc.json, in JSON format:
{
packages?: [
{
path: string,
scripts?: {
[scriptName: string]: string
}
}
...
],
scripts?: {
[scriptName: string]: string
},
hooks?: {
[scriptName: string]: {
beforeAll?: string,
beforeEach?: string,
afterEach?: string,
afterAll?: string
}
}
}
Whenever you run MPH, any paths under packages that aren't in your workspaces array in the root package.json will get added to it. If you provide a scripts object for an entry in packages, every package.json within those packages will get its scripts section overwritten with the one from here. That way, if you have many packages in a directory in your repo that are all built, tested, etc the same way and thus all have the same scripts anyway, you can manage that list of scripts in one place instead of many.
Any scripts in the scripts object at the root level of the config will be added to the scripts section of all packages found by MPH. If a package or group of packages does not have its own scripts as described above, these globally-defined scripts will not overwrite those packages' scripts section; they will merely be added to it.
The hooks are used for the run command. See more about that below.
In scripts and hooks, $projectRoot will be replaced with a relative path and $packageName will be replaced with the package name. For example, if you have the following project structure...
┍ project
├─┮ scripts
│ └─╸ foo-script.sh
└─┮ src
├─┮ some-package
│ └─╸ package.json
└─┮ nested-package
└─┮ package-a
└─╸ package.json
...and a global script "foo": "$projectRoot/scripts/foo-script.sh", then mph run foo will run it in both of the packages without issue.
mph <command>
Commands:
mph ls List packages
mph run <script> Run a script in each package
mph sh <cmd> Run a shell command in each package
mph version <versionNumber> Update the monorepo version number in all
packages
Options:
--version Show version number [boolean]
--help Show help [boolean]
mph ls
List packages
Options:
--version Show version number [boolean]
--help Show help [boolean]
-l Show additional information about packages
[boolean] [default: false]
mph ls will, by default, list the name of every package that MPH knows about. If you provide the -l option, you will get the name, version, and path of each package.
mph run <script>
Run a script in each package
Options:
--version Show version number [boolean]
--help Show help [boolean]
--filter, -f Filter on package names to run the script in [string]
--fail-slow, -s If the given script errors in a package, keep going through
the other packages and return the error at the end
[boolean] [default: false]
The script that is provided to this command will be run via yarn run in each package. If you provide a filter, it will only be run in packages with matching names. For example, if you have packages called "foo-a", "foo-b", and "bar-a", and you enter mph run build foo, it will only build "foo-a" and "foo-b".
If you've put hooks in your configuration for the script you're running, they will be run as well. Hooks are not run through yarn run, they are just run straight up. Unlike scripts, they are run in the project root rather than the individual package's directory. So for example, if your config looks like this...
{
"packages": [
{
"path": "packages/*",
"scripts": {
"build": "echo ' build'"
}
}
],
"hooks": {
"build": {
"beforeAll": "echo ' beforeAll'",
"beforeEach": "echo ' beforeEach'",
"afterEach": "echo ' afterEach'",
"afterAll": "echo ' afterAll'"
}
}
}
...and you have the same three packages from the previous example, and run mph run build, you will see:
Running hook build.beforeAll
beforeAll
Running hook build.beforeEach
beforeEach
Running script build in package foo-a
build
Running hook build.afterEach
afterEach
Running hook build.beforeEach
beforeEach
Running script build in package foo-b
build
Running hook build.afterEach
afterEach
Running hook build.beforeEach
beforeEach
Running script build in package bar-a
build
Running hook build.afterEach
afterEach
Running hook build.afterAll
afterAll
If the script takes arguments you can simply tack those on the end, including if you use the filter option. For example, mph run someScript filter-text scriptArg1 scriptArg2.
mph sh <cmd>
Run a shell command in each package
Options:
--version Show version number [boolean]
--help Show help [boolean]
--filter, -f Filter on package names to run the command in [string]
Does what it says on the tin, and allows filtering just like run. For example:
$ mph sh "pwd"
/path/to/project/packages/foo-a
/path/to/project/packages/foo-b
/path/to/project/packages/bar-a
mph version <versionNumber>
Update the monorepo version number in all packages
Options:
--version Show version number [boolean]
--help Show help [boolean]
Sets the version number to the number given. It is updated in the root package.json, and in all packages' package.json files, in their version field as well as the dependency versions for packages that depend on other packages in your monorepo.
FAQs
Monorepo Package Handler
We found that @spscommerce/mph demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Recent coverage mislabels the latest TEA protocol spam as a worm. Here’s what’s actually happening.

Security News
PyPI adds Trusted Publishing support for GitLab Self-Managed as adoption reaches 25% of uploads

Research
/Security News
A malicious Chrome extension posing as an Ethereum wallet steals seed phrases by encoding them into Sui transactions, enabling full wallet takeover.