diff --git a/README.md b/README.md index b18da96..3c7aa3a 100644 --- a/README.md +++ b/README.md @@ -99,11 +99,7 @@ Commands that modify `node_modules` might break symlinks. To fix it, run `npm ru If you want to run a command on all packages, run `node monorepo run your_command --if-present`. -There are several options to filter packages: - -- `--if-present` will check if command is present before running it. -- `--public` will execute command only for public packages (everything except demo). -- `--private` will execute command only for private packages (only demo packages). +There are several options to filter packages, see [monorepo/README.md](monorepo/README.md). ### Monorepo on Windows diff --git a/monorepo/README.md b/monorepo/README.md index c4cad66..4f02c37 100644 --- a/monorepo/README.md +++ b/monorepo/README.md @@ -1,22 +1,30 @@ -# Fix links +# Monorepo -Unfortunately, Lerna is not being actively developed and it has a lot of issues. +This package was created to manage Iconify monorepo. -One of those issues is inability to create links for local dependencies that depend on other local dependencies. +Iconify monorepo used to be managed by Lerna. Unfortunately, Lerna has been abandoned and has a lot of issues. One of those issues is inability to create symblic links for local packages that depend on other local packages, which makes it unusable for monorepos like Iconify. -This is a basic script does the same as Lerna, but with few differences: +## What does it do? -- It links everything, so dependencies of dependencies are correctly linked (broken in Lerna). For simplicity, it links everything. -- It does not check versions. This means if you have multiple versions of the same package in monorepo, this script is not for you. +This is a simple script to manage multiple packages, placed in the same monorepo. + +### Symbolic links + +Main feature is symbolic links. It creates links between all local packages, so when you can work on multiple packages at the same time. + +Unlike Lerna, currently this sctipt is very basic: it does not check dependencies, does not check versions, does not mess with `package.json`. ## Requirements -Script requires: +Script requires NPM. It was not designed to work with other package managers yet. -- NPM (not tested with other package managers) -- Unix file system (TODO: test on Windows) +## Config file -## Links +This script uses `lerna.json`, where the only property that matters is `packages`. + +Order of packages in `packages` property affects execution order, so if execution order (such as build order) matters, list most important packages first. Basic wildcards are supported, such as `packages/*`. + +## Symbolic links Script creates symbolic links for all local packages, except: @@ -25,11 +33,19 @@ Script creates symbolic links for all local packages, except: ## Commands -- `bootstrap`: runs `npm install` for all packages, then creates symbolic links. +- `install`: runs `npm install` for all packages, then creates symbolic links. - `link`: creates symbolic links (can be used to fix links after messing with packages). - `unlink`: removes local symbolic links. - `clean`: removes `node_modules` in all packages. +- `run `: runs command specified in next parameter (also `run-script `). -## Config file +## Options -This script usese `lerna.json`, where the only property that matters is `packages`. +Options for all commands: + +- `--if-present` will check if command is present before running it, used for `run` command. +- `--public` will execute command for public packages. +- `--private` will execute command only for private packages. +- `--silent` will execute command silently. +- `--workspace ` or `-w=` filters by workspace directory, such as `-w=packages/core`. You can use this option several times to specify multiple workspaces. +- `--package ` or `-p=` filter by package name, such as `-p=@iconify/core`. You can use this option several times to specify multiple packages. diff --git a/monorepo/src/helpers/options.ts b/monorepo/src/helpers/options.ts index 8a9ce45..1fae821 100644 --- a/monorepo/src/helpers/options.ts +++ b/monorepo/src/helpers/options.ts @@ -10,6 +10,12 @@ export interface ActionOptions { // Filter packages by `private` property, undefined if not set private?: PackageTypeFilter; + // Filter by workspace + workspaces: string[]; + + // Filter by package name + packages: string[]; + // Silent silent: boolean; } @@ -19,6 +25,8 @@ export interface ActionOptions { */ export const actionOptions: ActionOptions = { ifPresent: false, + workspaces: [], + packages: [], silent: false, }; diff --git a/monorepo/src/helpers/workspaces.ts b/monorepo/src/helpers/workspaces.ts index 69b4c42..0a6fb94 100644 --- a/monorepo/src/helpers/workspaces.ts +++ b/monorepo/src/helpers/workspaces.ts @@ -81,7 +81,21 @@ export function filterWorkspaces(): PackageInfo[] { } } - // TODO: match name + // Match workspace + if (actionOptions.workspaces.length) { + const workspace = item.path.join('/'); + if (actionOptions.workspaces.indexOf(workspace) === -1) { + return false; + } + } + + // Match package + if ( + actionOptions.packages.length && + actionOptions.packages.indexOf(item.name) === -1 + ) { + return false; + } // Match return true; diff --git a/monorepo/src/index.ts b/monorepo/src/index.ts index 0f5cbdb..f5c8db6 100644 --- a/monorepo/src/index.ts +++ b/monorepo/src/index.ts @@ -58,6 +58,7 @@ export function run() { // Process args let nextActionParam: string | null = null; + let nextOptionValue: string | null = null; process.argv.slice(2).forEach((arg) => { // Parameter for action with param if (nextActionParam !== null) { @@ -69,6 +70,23 @@ export function run() { return; } + // Parameter for option with param + if (nextOptionValue !== null) { + switch (nextOptionValue) { + case '--workspace': + case '-w': + actionOptions.workspaces.push(arg); + break; + + case '--package': + case '-p': + actionOptions.packages.push(arg); + break; + } + nextOptionValue = null; + return; + } + // Options switch (arg) { case '--if-present': @@ -88,6 +106,24 @@ export function run() { return; } + // Options with '=' + const argParts = arg.split('='); + if (argParts.length > 1) { + const cmd = argParts.shift(); + const value = argParts.join('='); + switch (cmd) { + case '--workspace': + case '-w': + actionOptions.workspaces.push(value); + return; + + case '--package': + case '-p': + actionOptions.packages.push(value); + return; + } + } + // Action if (actionFunctions[arg] !== void 0) { actions.push(arg); @@ -108,6 +144,9 @@ export function run() { if (nextActionParam !== null) { throw new Error(`Missing parameter for action: ${nextActionParam}`); } + if (nextOptionValue !== null) { + throw new Error(`Missing parameter for option: ${nextOptionValue}`); + } // Run actions if (!actions.length) {