Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/ryardley/indexr

Autogenerate dynamic ES6 index modules.
https://github.com/ryardley/indexr

Last synced: 23 days ago
JSON representation

Autogenerate dynamic ES6 index modules.

Awesome Lists containing this project

README

        

# Indexr


Coverage Status
Coverage Status

Dynamic index module boilerplate creator for your Node or client packaged ES6 submodules. **Indexr** overcomes some of the limits of ES6 modules by autogenerating module index boilerplate code usually as part of a precompilation stage in your build process.

##Contents

- [Background](#background)
- [Installation](#installation)
- [Usage](#usage)
- [CLI Usage](#cli-usage)
- [Syntax Example](#syntax-example)
- [Change the modules folder](#change-the-modules-folder)
- [Change the output filename](#change-the-output-filename)
- [Change what qualifies as a module.](#change-what-qualifies-as-a-module)
- [ES5 module output](#es5-module-output)
- [Use named Exports.](#use-named-exports)
- [Including the globbed files.](#including-the-globbed-files)
- [File Watching](#file-watching)
- [Node API](#node-api)
- [Signature](#signature)
- [Arguments](#arguments)
- [Available options](#available-options)
- [Example](#example)
- [Contributing](#contributing)
- [Feedback?](#feedback)
- [Found a bug?](#found-a-bug)

# Background
When creating great applications it is important to provide systems that allow features to be implemented and maintained as discrete units of code.

It is also important to avoid magic runtime binding where functionality is implied by folder structure or some other magic variables or constants.

ES6 modules have come along and they are a great way to organise JavaScript code. They are declarative and statically analysable. Very importantly what you see is what you get.

However they lack the ability to autoload modules on the fly based on a dynamic folder structure such as the kind you would see in a modular framework that needs to bind dynamic packages of code together.

It is for this reason I created the [Indexr](http://github.com/ryardley/indexr) open source project.

What [Indexr](http://github.com/ryardley/indexr) does is it takes a folder, searches for any 'module' folders based on globs you provide and generates index files that export all the 'submodules' within the 'module' folders in whatever way you choose.

Let's look at an example:

```bash
$ indexr . \
--out reducers.js \
--modules **/modules/ \
--submodules */reducer.js \
--direct-import
--named-exports
```

This example does the following:

1. Use the current folder as a root folder
1. Find module folders nested within this root folder that have the name `modules`
1. Within each `modules` folder find subfolder that contains an `reducer.js` file
1. Create an ES6 `reducers.js` file within each 'modules' folder that directly imports the submodule's `reducer.js` file.
1. Export the reducers as named exports.

You can also do the same thing via Node API

```javascript
import indexr from 'indexr';
indexr(__dirname, {
outputFilename: 'reducers.js',
modules: '**/modules/',
submodules: '*/reducer.js',
directImport: true,
namedExports: true,
});
```

http://github.com/ryardley/indexr

# Installation

Install locally and use the node API or use indexr in npm scripts (recommended).

```bash
# better
npm install indexr --save
```

**Tip**
Try adding `./node_modules/.bin` to your path for your terminal. That way you can get access to local cli programs as you enter your npm projects.

```bash
# ~/.bash_profile
...
PATH=$PATH:./node_modules/.bin
...
```

Alternatively if you have to you can install globally and use indexr in the bash prompt.

```bash
# You probably don't want to do this
npm install indexr -g
```

# Usage

You can use indexr as either a command-line program or a node API.

Assuming we have a folder tree like this:

```bash
./modules
├── bar
├── baz
└── foo
```

We run this in the root:

```bash
$ indexr .
```

Within any subfolder it finds called 'modules' you will find it will create a file called `./index.r.js` that contains the following:

```javascript
/**
This file is autogenerated by indexr.
Check this file into source control.
Do not edit this file.
For more information: http://github.com/ryardley/indexr
**/
import bar from './bar';
import baz from './baz';
import foo from './foo';
export default [
bar,
baz,
foo
];
/** End autogenerated content **/
```

Alternatively if we run this:

```bash
$ indexr . --named-exports
```

Within any subfolder it finds called 'modules' you will find it will create a file called `./index.r.js` that contains the following index with named exports:

```javascript
/**
This file is autogenerated by indexr.
Check this file into source control.
Do not edit this file.
For more information: http://github.com/ryardley/indexr
**/
export { default as bar } from './bar';
export { default as baz } from './baz';
export { default as foo } from './foo';
/** End autogenerated content **/
```

## CLI Usage

For help with the commandline program you can try the help flag:

```
$ indexr --help

Usage: indexr [options]

Options:

-h, --help output usage information
-V, --version output the version number
-e --ext Remove this extension from imports.
-o --out The name of the output file.
-d --direct-import Directly import files as opposed to folders.
-m --modules Glob string that determine which folders hold modules.
-i --modules-ignore Glob string that determine which folders are ignored.
-5 --es5 Use ES5 template for index output.
-n --named-exports Use named exports instead of arrays.
-s --submodules Glob string that determine what is a submodule.
-g --submodules-ignore Glob string that determine which submodules are ignored.
-w --watch [string] Files to watch as a glob string.

```

### Syntax Example

**NOTE: All commandline globs must be enclosed in quotes!!**

The following example will look in the `./app` folder for modules folders identified by '**/modules/' and then identify submodules given by '*/server.js' and use them to write a file to `./app/modules/server.js`.

```bash
$ indexr ./app --out 'server.js' --modules '**/modules/' --submodules '*/server.js'
```

### Change the modules folder

We can change the glob used to find the modules folder which is useful if you don't want to have your modules under 'modules'.

```bash
$ indexr . --modules '**/features/'
```

### Change the output filename

We can change the output filename of the file indexr produces.

```bash
$ indexr . --out 'index.js'
```

### Change what qualifies as a module.

We can also filter which modules and entry files we want by setting some options. the following will only include modules which contain `reducer.js` files.

```bash
$ indexr . --submodules '*/reducer.js'
```

### ES5 module output

```bash
$ indexr . --es5
```

If the es5 flag is set Indexr can export the template in es5/common js style.

```javascript
/**
This file is autogenerated by indexr.
Check this file into source control.
Do not edit this file.
For more information: http://github.com/ryardley/indexr
**/
var foo = require('./foo');
var bar = require('./bar');
var baz = require('./baz');
module.exports = [foo, bar, baz];
/** End autogenerated content **/
```

### Use named Exports.

By using the `--named-exports` flag it will export the submodules as named exports:

```bash
$ indexr . --named-exports
```

```javascript
export { default as bar } from './bar';
export { default as baz } from './baz';
export { default as foo } from './foo';
```

### Including the globbed files.

By using the `--direct-import` flag it will include the searched files specifically in the import statements:

```bash
$ indexr . --submodules '*/server.js' --direct-import
```

```javascript
import foo from './foo/server.js';
import bar from './bar/server.js';
export default [foo, bar];
```

## File Watching

You can watch files using the `--watch` flag:

```bash
$ indexr . --watch
```

## Node API

### Signature

```ts
indexr(rootFolder:String, options?:Object):Promise
```

### Arguments

| argument | notes |
| ------------------- | ------------- |
| `rootFolder` | The root folder to work from. |
| `options` | An object containing configuration options |

### Available options

| option | default | notes |
| -------------- | ------ | -----------|
| `directImport` | `false` | Include the searched files in the import statements. |
| `es5` | `false` | Boolean flag to use es5 commonjs style modules over es6. This is overridden if a template function|
| `exts` | `[]` | Remove this extension from the imported files. A usefull example might be `['js']` which you would use if you would prefer to import `./foo/server` instead of `./foo/server.js` |
| `modules` | `'\*\*/modules/'` | A glob or array of globs pathed to the rootFolder that will determine which folders are module holders. If this is ommitted defaults to `**/modules/`. |
| `modulesIgnore` | `undefined` | A glob pathed to the rootFolder that will determine which folders are not module holders. If this is ommitted nothing is ignored. |
| `namedExports` | `false` | This flag will ensure that indexes use named exports instead of arrays. |
| `submodules` | `'\*/'` | A glob pathed to each module holder folder that will determine which submodules are imported to the index. Defaults to `*/index.js` |
| `submodulesIgnore` | `undefined` | A glob pathed to the rootFolder that will determine which folders are not considered submodules. If this is ommitted nothing is ignored. |
| `template` | indexr's es6 template | A template function the function should takes an array of relative module paths and output the module file as a string |
| `outputFilename` | `'index.r.js'` | The name of the output file. This file will be added to each module folder. |
| `watch` | `false` | Either a boolean value or a glob that represents files for chokdir to watch. |

### Example

Here is an example

```javascript
import indexr from 'indexr';
import es6 from 'indexr/dist/modules/template/es6'; // This will change don't do this.

indexr(__dirname, {
es5: false,
modules: '**/modules/',
submodules: '*/index.js',
directImport: true,
exts: ['js', 'jsx'],
namedExports: false,
outputFilename: 'index.js',
template: es6, // or some function that takes an array of module paths and spits out a template
watch: false,
})
.then((err, result) => {
console.log('Files have been indexed!');
});
```

*NOTE: dont load the template from the dist file as it's location may change. This is only for illustration purposes.*

# Contributing

Start the gulp watcher.

```bash
$ gulp
```

Run the tests

```bash
$ npm run test-watch
```

Edit the code.

### Feedback?

1. [Submit an issue](https://github.com/ryardley/indexr/issues)

___

### Found a bug?

1. [Submit an issue](https://github.com/ryardley/indexr/issues)
or
1. [Submit a pull request!](https://github.com/ryardley/indexr/pulls)

If anything is unclear or wrong in these docs please let me know by [submitting an issue](https://github.com/ryardley/indexr/issues)