Skip to content
This repository has been archived by the owner on Oct 18, 2023. It is now read-only.

Commit

Permalink
Merge pull request #19 from Financial-Times/matth/extend-filter-option
Browse files Browse the repository at this point in the history
Extend filter option
  • Loading branch information
i-like-robots authored Nov 21, 2018
2 parents a8794f1 + 65107e5 commit de307da
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 12 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@
"async-sema": "^2.1.2",
"byline": "^5.0.0",
"chalk": "^2.4.1",
"commander": "^2.16.0",
"commander": "^2.19.0",
"find-up": "^3.0.0",
"glob": "^7.1.2",
"jest": "^23.4.1",
"log-symbols": "^2.2.0",
"semver": "^5.5.0",
"semver": "^5.6.0",
"toposort": "^2.0.2"
},
"devDependencies": {
"@financial-times/n-gage": "^2.0.2"
"@financial-times/n-gage": "^2.0.2",
"jest": "^23.4.1"
}
}
30 changes: 25 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
Athloi is a tool to assist with the management of multi-package repositories (a.k.a. [monorepos]) with git and npm. It provides an interface to execute commands and scripts within the scope of each package.

[monorepos]: https://github.com/babel/babel/blob/master/doc/design/monorepo.md
[lerna]: https://lernajs.io/

## Getting Started

Expand Down Expand Up @@ -31,6 +30,8 @@ Configuration can be passed to Athloi by providing a `monorepo.json` file in you

## Commands

_Please note:_ Before executing a command Athloi will sort the packages [topologically] based on their cross-dependencies and run tasks in this order.

### exec

Runs an arbitrary command in the scope of each package.
Expand Down Expand Up @@ -99,19 +100,38 @@ A global concurrency option which can be used to execute multiple tasks in paral
athloi run build --concurrency 3
```

_Please note:_ using a concurrency value higher than 1 no longer ensures that tasks will finish for packages which are dependencies of other packages.

### filter

A global filter option which can be used for all tasks. It can filter packages based on the value of a field within each package manifest file.
A global filter option which can be used for all tasks. It filters packages based on the value of a field within their package manifest file.

```sh
# Run a build script in only the packages marked as private
athloi run build --filter "private:true"
athloi run build --filter private:true
```

The value of the field will be coerced using `JSON.parse()` so boolean and number values can be used and string values must use double-quotes:

```sh
# Run a build script for only the package named "x-interaction"
athloi run build --filter 'name:"x-interaction"'
```

Property values inside arrays and objects can also be matched:

```sh
# Run the script for packages with a keyword of "demo"
athloi run build --filter 'keywords:"demo"'

# Run the script for packages with a dependency on the "lodash" package
athloi run build --filter 'dependencies:"lodash"'
```

The field name preceeding the colon (`:`) is optional and the default field is `name`.
The field name preceeding the colon (`:`) is optional and if omitted will set the default field to `name`.

```sh
# Run a build script only for the package named `x-interaction`
# Run a build script for only the package named "x-interaction"
athloi run build --filter x-interaction
```

Expand Down
18 changes: 15 additions & 3 deletions src/filter-packages.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
const test = (a, b) => {
if (Array.isArray(a) && typeof b === 'string') {
return a.includes(b);
}

if (typeof a === 'object' && typeof b === 'string') {
return a.hasOwnProperty(b);
}

return a === b;
};

module.exports = (filter, packages = []) => (
filter
? packages.filter(({ manifest }) => {
if (filter.includes(':')) {
const [key, val] = filter.split(':');
return manifest[key] === JSON.parse(val);
const [key, value] = filter.split(':');
return test(manifest[key], JSON.parse(value));
} else {
// By default filter on the package name
return manifest.name.split('/').slice(-1)[0] === filter;
return manifest.name.split('/')[0] === filter;
}
})
: packages
Expand Down
21 changes: 21 additions & 0 deletions test/src/filter-packages.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ describe('src/filter-packages', () => {
{
name: 'baz',
private: false
},
{
name: 'qux',
dependencies: {
lodash: '^1.0.0'
},
keywords: [
'awesome'
]
}
];

Expand All @@ -37,6 +46,18 @@ describe('src/filter-packages', () => {
expect(b[0].manifest.name).toEqual('bar');
});

it('handles object and array matching', () => {
const a = subject('keywords:"awesome"', fixture);

expect(a.length).toEqual(1);
expect(a[0].manifest.name).toEqual('qux');

const b = subject('dependencies:"lodash"', fixture);

expect(b.length).toEqual(1);
expect(b[0].manifest.name).toEqual('qux');
});

it('defaults to matching the package name', () => {
const result = subject('baz', fixture);

Expand Down

0 comments on commit de307da

Please sign in to comment.