### Features

* Local modules followed by symbolic links (no need reinstall it each time)
    * Symlinks are **relative** so you can save it in repository (better than `npm link` with absolute symlinks)
    * Zip follows symlinks so your app.zip contains all it need (no broken links)
* Local modules are shared between each other
* **No dependencies duplication** for shared local modules
* Single version of shared wrapper module (like `lodash` or else)
    * Also **w/o duplication**
* Recursive commands for installing and cleaning usual and shared modules  

### Install

`npm install --global shmod`

### Usage

```bash
> shmod
Usage:
  shmod find      - Show all (recursive) sharedDependencies
  shmod link      - Find all (recursive) sharedDependencies and map it to node_modules/@shared/
  shmod install   - Run recursive 'npm install' for sharedDependencies
  shmod reinstall - Run recursive 'npm prune && npm install' for sharedDependencies
  shmod clean     - Run recursive 'npm prune' for sharedDependencies
  shmod build     - Run recursive 'npm install' and link for sharedDependencies
  shmod rebuild   - Run recursive 'npm install && npm prune' and link for sharedDependencies
  shmod wrap <pkg> [version] - Generate shared module wrapper
Version: ...
```

### Example

Directories layout:

```
a/
|--_modules/
|  |- when/     # Shared wrapper module: content will be generated by 'shmod wrap'
|  \- lodash/   # Shared wrapper module: content will be generated by 'shmod wrap'
\--b/
   |- _modules/
   |  |- joi/    # Shared wrapper module: content will be generated by 'shmod wrap'
   |  \- lib/    # Custom shared module
   |     |- index.js
   |     \- package.json
   \- app/
      |- index.js
      \- package.json
```
#### Shared wrapper modules

Prepare shared module in `a/_modules` that wraps `when` module:
```bash
> cd a/_modules/when
> shmod wrap when 3.7.7
package.json:   Create
index.js:       Create
```

Prepare shared module in `a/_modules` that wraps `lodash` module:
```bash
> cd a/_modules/lodash
> shmod wrap lodash 4.17.4
package.json:   Create
index.js:       Create
```

Prepare shared module in `a/b/_modules` that wraps `joi` module:
```bash
> cd a/b/_modules/joi
> shmod wrap joi 10.2.0
package.json:   Create
index.js:       Create
```

#### Shared library module

Write your custom library in `a/b/_modules/lib/index.js`:
```js
const _ = require('@shared/lodash');
console.log('_: squares:', _.map([1, 2, 3], x => x * x));

const when = require('@shared/when');
module.exports = when.resolve('lib promise');
```
Specify shared dependencies for the app in `a/b/app/package.json` used directly in the lib:
```json
{
  "sharedDependencies": [
    "when",
    "lodash"
  ]
}
```

#### App module

Write your app in `a/b/app/index.js`:
```js
const lib = require('@shared/lib')
lib.then(console.log); // prints: 'lib promise'

const Joi = require('@shared/joi');
console.log({isJoi: Joi.string().isJoi})

const when = require('@shared/when');
when.resolve('app promise')
  .then(console.log)

// Lodash not used directly from here, but used from the lib!!!
``` 
Specify shared dependencies for the app in `a/b/app/package.json` used directly in the app:
```json
{
  "sharedDependencies": [
    "when",
    "lib",
    "joi"
  ]
}
```

Install shared local dependencies from upper `../*/_modules/' directories:
```bash
> cd a/b/app
> shmod build
cd /Users/urukhai/Job/nu/npm/shmod/test/a/_modules/when && npm install
cd /Users/urukhai/Job/nu/npm/shmod/test/a/b/_modules/lib && npm install
cd /Users/urukhai/Job/nu/npm/shmod/test/a/_modules/lodash && npm install
cd /Users/urukhai/Job/nu/npm/shmod/test/a/b/_modules/joi && npm install
cd /Users/urukhai/Job/nu/npm/shmod/test/a/b/app && npm install
Link: node_modules/@shared/when -> ../../../../_modules/when
Link: node_modules/@shared/lib -> ../../../_modules/lib
Link: node_modules/@shared/lodash -> ../../../../_modules/lodash
Link: node_modules/@shared/joi -> ../../../_modules/joi
```

Run app:
```bash
> cd a/b/app
> node --preserve-symlinks index.js     # --preserve-symlinks required for working with node_modules/@shared/* symlinks 
_: squares: [ 1, 4, 9 ]
{ isJoi: true }
lib promise
app promise
```

#### Results

* Check `a/b/app/node_modules/@shared/*` - there are local (**relative**) only links! Not absolute like `npm link`!
* All your links to shared local modules in your git repository!   
* Check `a/b/app/node_modules`: there is **no duplication** for `when` while it used from `lib` and `app`!
* Version of `when` specified once only in `a/_modules/when/package.json`!
* Version of `lodash` specified once only in `a/_modules/lodash/package.json`!
* Version of `joi` specified once only in `a/b/_modules/joi/package.json`!
* All shared and usual dependencies of the app was installed via single run `shmod build`!

### Git ignore

Ignore anything in `node_modules` but not `@shared` 

```ignore
**/node_modules/*
!**/node_modules/@shared
```

## Feedback

Feel free to add issue: https://bitbucket.org/nukisman/shmod/issues