africa
Version:
A library to interactively create and read configuration files.
162 lines (124 loc) • 7.61 kB
Markdown
<div align="center">
# africa
[](https://www.npmjs.com/package/africa)
[](https://ci.appveyor.com/project/bulbazaur/africa)
<a href="https://gitlab.com/artdeco/africa/-/commits/master">
<img src="https://gitlab.com/artdeco/africa/badges/master/pipeline.svg" alt="Pipeline Badge">
</a>
</div>
<a href="https://www.npmjs.com/packages/africa">
<img src="./africa.jpg" alt="Africa" />
</a>
`africa` is a _Node.JS_ package which simplifies reading from and writing to persistent configuration files in user's home directory. If a configuration exists, it will be read, and if not, the user will be presented with questions, after which the answers will be stored in the `.rc` file.
```sh
yarn add africa
```
## Table Of Contents
- [Table Of Contents](#table-of-contents)
- [API](#api)
- [`async africa(packageName, questions=, config=): !Object`](#async-africapackagename-stringquestions-_reloquentquestionsconfig-config-object)
* [`Config`](#type-config)
- [Groups](#groups)
- [Copyright & License](#copyright--license)
<div align="center"><a href="#table-of-contents">
<img src="/.documentary/section-breaks/0.svg?sanitize=true">
</a></div>
## API
The package is available by importing its default function:
```js
import africa from 'africa'
```
<div align="center"><a href="#table-of-contents">
<img src="/.documentary/section-breaks/1.svg?sanitize=true">
</a></div>
## <code>async <ins>africa</ins>(</code><sub><br/> `packageName: string,`<br/> `questions=: !_reloquent.Questions,`<br/> `config=: !Config,`<br/></sub><code>): <i>!Object</i></code>
Read package configuration from the home directory, or ask questions with
readline interface to create a new configuration in `~/.${packageName}rc`.
- <kbd><strong>packageName*</strong></kbd> <em>`string`</em>: The name of the package.
- <kbd>questions</kbd> <em>`!_reloquent.Questions`</em> (optional): An object with questions to ask when config wasn't found.
- <kbd>config</kbd> <em><code><a href="#type-config" title="The configuration object to configure additional functionality.">!Config</a></code></em> (optional): Configuration object.
Call `africa` asynchronously to read or create a new configuration. Questions should adhere to the [`reloquent`][2]'s interface.
__<a name="type-config">`Config`</a>__: The configuration object to configure additional functionality.
| Name | Type | Description | Default |
| ---------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
| force | <em>boolean</em> | Ask questions and update the configuration file even if it already exists. | `false` |
| homedir | <em>string</em> | In which directory to save and search for configuration file. | `os.homedir()` |
| questionsTimeout | <em>number</em> | How log to wait in ms before timing out. Will wait forever by default. | - |
| local | <em>boolean</em> | Whether to read a local config file in the current working directory rather than in the `HOMEDIR`. When initialising, the default values will be taken from the home config if it exists so that it is easy to extend `.rc` files. | `false` |
| recursive | <em>boolean</em> | **`paid`** Read all configurations up to the root one from the home directory, and merge them together. | `false` |
| skipExisting | <em>boolean</em> | **`paid`** When creating nested configs, skip writing values that are taken from parent RCs. | `true` |
| rcNameFunction | <em>(packageName: string) => string</em> | Function used to generate the `.rc` name. Default: packageName => `.${packageName}rc`. | - |
```js
import africa from 'africa'
import { userInfo } from 'os'
(async () => {
try {
const config = await africa('africa', {
name: {
defaultValue: userInfo().username,
text: 'user',
},
}, { force: true })
console.log(config)
} catch ({ stack }) {
console.log(stack)
}
})()
```
```sh
user: [zavr]
{ name: 'zavr' }
```
<div align="center"><a href="#table-of-contents">
<img src="/.documentary/section-breaks/2.svg?sanitize=true">
</a></div>
## Groups
It's possible to ask questions in groups, such that answers will be received in a nested object. Only 1 level of nesting is supported at the moment. To group questions, import the _Group_ type and pass questions to it.
```js
import africa, { Group } from 'africa'
africa('test', {
group: new Group({
test: {
text: 'hello',
},
}),
nongroup: {
text: 'your-name',
},
}, { force: true, homedir: __dirname })
```
```
your-name: [name-doc] name-doc
hello: [world-doc] world-doc
```
```json
{
"nongroup": "name-doc",
"group": {
"test": "world-doc"
}
}
```
<div align="center"><a href="#table-of-contents">
<img src="/.documentary/section-breaks/3.svg?sanitize=true">
</a></div>
## Copyright & License
Photo [Diana Robinson][3], 2017
GNU Affero General Public License v3.0
<table>
<tr>
<th>
<a href="https://www.artd.eco">
<img width="100" src="https://gitlab.com/uploads/-/system/group/avatar/7454762/artdeco.png"
alt="Art Deco">
</a>
</th>
<th>© <a href="https://www.artd.eco">Art Deco™</a> 2020</th>
<th><a href="LICENSE"><img src=".documentary/agpl-3.0.svg" alt="AGPL-3.0"></a></th>
</tr>
</table>
[2]: https://www.npmjs.com/package/reloquent
[3]: https://www.flickr.com/photos/dianasch/31316774424/in/photolist-PHmDYC-moFj48-Q4Aya5-63Gpiw-mLTkJi-VNKhAn-Rz3Mrh-62BZoA-5q9HuM-6cnt7G-5Jv17M-zn5DFn-5QA73Q-6xjraT-aqGVsL-odrGp-azaw9g-wJQZ9M-4nGawg-4rHcYe-atRxbW-5JYiwy-eki9WF-ahdLm5-aTm2jZ-bp9exn-9xL37X-NBPkZ9-38Exqu-69Wv9G-7yxhvg-8GsnfW-agEC2n-svkzJf-k1ihc6-pPd9Aj-5SuyNP-aAg4Gf-DAMWZ1-DHceLL-oCxZ7U-pQe8E4-y875RB-c21GHN-dNZXJ3-NJ5yVx-e663y6-e6bFDq-jYo6Sm-cem5Xu
<div align="center"><a href="#table-of-contents">
<img src="/.documentary/section-breaks/-1.svg?sanitize=true">
</a></div>