# lenv-cli

> ![](./cover.png)

Latest version **2.1.4** (published 2021-10-03) · MIT license · 0 weekly downloads

## Install

```sh
npm install lenv-cli
pnpm add lenv-cli
yarn add lenv-cli
bun add lenv-cli
```

Provides the command `lenv`.

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 2.1.4 |
| Published | 2021-10-03 |
| First published | 2021-04-10 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Node | >=10 |
| Dependencies | 20 |
| Unpacked size | 4.8 MB |
| Known vulnerabilities | 0 (+1 in 1 direct dependencies) |
| Install scripts | no |
| Maintainers | vitramir |

## Links

- npm: https://www.npmjs.com/package/lenv-cli
- Repository: https://gitlab.com/lenv/cli
- Issues: https://gitlab.com/lenv/cli/-/issues
- npm.io page: https://npm.io/package/lenv-cli

## Dependencies (20)

- [ink](https://npm.io/package/ink.md) ^3.0.8
- [glob](https://npm.io/package/glob.md) ^7.1.6
- [uuid](https://npm.io/package/uuid.md) ^8.3.2
- [yaml](https://npm.io/package/yaml.md) ^1.10.2
- [ramda](https://npm.io/package/ramda.md) ^0.27.1
- [react](https://npm.io/package/react.md) ^17.0.2
- [redux](https://npm.io/package/redux.md) ^4.0.5
- [figures](https://npm.io/package/figures.md) ^3.2.0
- [chokidar](https://npm.io/package/chokidar.md) ^3.5.2
- [reselect](https://npm.io/package/reselect.md) ^4.0.0
- [react-dom](https://npm.io/package/react-dom.md) ^17.0.2
- [ink-divider](https://npm.io/package/ink-divider.md) ^3.0.0
- [ink-spinner](https://npm.io/package/ink-spinner.md) ^4.0.1
- [react-redux](https://npm.io/package/react-redux.md) ^7.2.3
- [redux-persist](https://npm.io/package/redux-persist.md) ^6.0.0
- [ink-text-input](https://npm.io/package/ink-text-input.md) ^4.0.1
- [latest-version](https://npm.io/package/latest-version.md) ^5.1.0
- [@reduxjs/toolkit](https://npm.io/package/@reduxjs/toolkit.md) ^1.5.1
- [ink-use-stdout-dimensions](https://npm.io/package/ink-use-stdout-dimensions.md) ^1.0.5
- [redux-persist-node-storage](https://npm.io/package/redux-persist-node-storage.md) ^2.0.0

## Recent versions

- 2.1.4 (latest) — 2021-10-03
- 2.1.3 — 2021-10-03
- 2.1.2 — 2021-09-28
- 2.1.1 — 2021-09-28
- 2.1.0 — 2021-09-28
- 2.0.0 — 2021-09-28
- 1.0.0 — 2021-09-17
- 0.8.1 — 2021-09-11
- 0.8.0 — 2021-08-26
- 0.7.0 — 2021-08-15
- 0.6.1 — 2021-08-08
- 0.6.0 — 2021-08-08
- 0.5.1 — 2021-06-22
- 0.5.0 — 2021-06-19
- 0.4.3 — 2021-06-19
- … 6 more at https://npm.io/package/lenv-cli/versions

## README

![](./cover.png)

## Install
### NPM
```bash
$ npm install --global lenv-cli
```

### YARN
```bash
$ yarn global add lenv-cli
```

## Run
```bash
$ lenv
```


## What is LENV?
LENV is a CLI tool which allows to configure and build docker-compose file from modules, secrets and automation artifacts.

## What is module?
Module is a small piece of configuration. It may contain multiple configuration variants. For example local, staging and production. End user of LENV CLI has to select which modules to run and configuration variant for each module. LENV will resolve dependencies and use all required modules to build docker-compose file.

## How to create a module?
Modules are built from multiple files. At least two files are required:
* Module declaration file `./modules/MODULE_DIR/*.module.js`
* Module configuration variant `./modules/MODULE_DIR/configs/*.js`

Module declaration file has only two fields:
```javascript
module.exports = {
  name: "mongodb", // module name
  defaultConfig: "local", // default configuration variant
};
```

Module configuration variant:
```javascript
module.exports = {
  name: "local", // variant name
  requires: [
	  /* 
		Array of dependencies. 
		Values are names of other modules.
		(optional)
	  */
  ],
  jobs: [
	  /* 
		Array of jobs required for this configuration. 
		Values are names of other modules.
		(optional)
	  */
  ],
  output: {
    /*
		Object with exported variables 
		which other modules may use
		(optional)
	  */
  },
  docker: {
    /*
		This object will be merged into the final
		docker-compose file
		(optional)
	  */
  },
};
```

## How to share variables between modules?
There are to steps.
* Export values from one module
* Import values in another

### How to export values?
Add them into the output section
```javascript
module.exports = {
  name: "local", // variant name
  output: {
    host: "mongodb"
  },
};
```

### How to import values?
We can use values from other modules inside two sections:
* output
* docker

There is a function `getVar`. Input of the function is a string `MODULE_NAME.VARIABLE_NAME`. Output is a Promise.

Example of usage:
```javascript
module.exports = {
  name: "local", // variant name
  requires: [
    "mongodb",
  ],
  docker: {
    services: {
		api: {
		  /* ....... */
		  environment: {
			DB_HOST: ({ getVar }) => getVar("mongodb.host")
		  }
		  /* ....... */
		}
	  }
  },
};
```

If some transformations to the value are required there are two options to implement them:
* Promise `.then`
* async/await

#### Important! 
Don’t forget to add module into the requires section.

## When to use dependencies?
There are two main reasons to add module as a dependency:
* To be able to use exported variables (output) from another module.
* To enable module and to include it into the final docker-compose file.

## How to add custom logic?
All configurations are unique and sometimes there is a requirement to add custom logic into the configuration process. There are two options to do this:
* Jobs
* Custom functions

## What are Jobs?
During build process LENV CLI runs some code which is grouped into the Jobs. Jobs are grouped into the Stages. 

Out of the box there are two stages:
* build 
* run 

And two jobs:
* docker-compose
* docker-compose up
One job in one stage.

LENV runs all jobs in one stage simultaneously. LENV will not continue to the next stage in case not all of the jobs from the current stage have Success state.

A few examples for jobs:
* Check that code repository is cloned
* Check that `/etc/hosts` contains required records
* There is a dynamic configuration which requires user input or manual actions

### How to add Stages?
LENV checks for stages inside `lenv.config.js` .
```javascript
module.exports={
    runStages:[
        "prepare", 
        "build",
        "run"
    ]
}
```

In case file doesn’t exist the default fallback is:
```javascript
module.exports={
    runStages:[
        "build",
        "run"
    ]
}
```

#### Note
It is possible to completely replace list of stages, but:
* if `build` stage doesn’t exist LENV will not create docker-compose file
* if `run` stage doesn’t exist LENV will not run containers automatically

### How to add Jobs?
LENV looks for jobs at  `./jobs/*.job.js`
```javascript
module.exports = {
  name: "check-sources", // job name
  stage: "prepare", // stage to run the job
  requires: [
	  /* 
		Array of dependencies. 
		Values are names of other modules.
		(optional)
	  */
  ],
  jobs: [
	  /* 
		Array of jobs required for this configuration. 
		Values are names of other modules.
		(optional)
	  */
  ],
  body: (params) => {
		// code to be executed inside JS function
	}
};
```

`requires` and `jobs` sections are identical to the same sections in modules. More information [here](#how-lenv-resolves-dependencies-requires-jobs)

`body` is a simple JS function which receives object with parameters:
```typescript
interface Params {
  /* 
      log, error and info allows to log message to the job's
      output with different level
	*/
  log: (msg: string) => void,
  error: (msg: string) => void,
  info: (msg: string) => void,

	/*
		adds log to the job's output and updates job status to
      'success' 
	*/
  success: (msg?: string) => void, 

	/*
		adds log to the job's output and updates job status to
      'failed' 
	*/
  fail:  (msg?: string) => void,

	/*
		updates job status to 'waiting'
      user has to enter string to continue 
	*/
  textInput: () => Promise<string>,

	/*
		array of all parameters passed to the job
	*/
	args: any[]

  /*
		get and set artifacts
  */
  getArtifacts: () => Record<string, any>,
  updateArtifacts: (data: Record<string, any>) => void,
}
```

#### Artifacts
Artifacts are persistent storage for the jobs. They may be used in modules similar to outputs with `getArtifact` function.

```javascript
module.exports = {
  jobs: [
    "get-user-token",
    { target: "SERIVCE_NAME" }
  ],
  docker: {
    services: {
		api: {
		  /* ....... */
		  environment: {
			SERVICE_TOKEN: ({ getArtifact }) => getArtifact("get-user-token.artifactNameForTheToken")
		  }
		  /* ....... */
		}
	  }
  },
};
```

#### Job example
```javascript
module.exports = {
  name: "get-token",
  stage: "prepare",
  body: async ({ textInput, updateArtifacts, success }) => {
		const token = await textInput();
		updateArtifacts({ token });
		success();
	}
};
```

More job examples here (TBD)

## What are custom functions?
TBD

## How does LENV resolve dependencies (requires, jobs)?
TBD

---
_Source: https://npm.io/package/lenv-cli · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
