eggjs / eggjs/egg

[RFC] egg-ast-utils

Open
#2,766 1 comment 1 reaction 2 assignees Claimed by @whxaxes View on GitHub
tools type: proposals
Dominant language
TypeScript
Stars
19k
Forks
1.8k
PR merge metrics
No merged PRs in 30d

Description

# Background

As mentioned at [egg-init improve](https://github.com/eggjs/egg/issues/379#issuecomment-286296746) and [egg-bin generate](https://github.com/eggjs/egg/issues/2723) , we found `provide API to migrate the existing egg files` is needed.

Inspired by: https://github.com/sapegin/mrm-core
Related issues:
- [[RFC] egg-init improve](https://github.com/eggjs/egg/issues/379#issuecomment-286296746)
- [[RFC] egg-bin generate](https://github.com/eggjs/egg/issues/2723)
- [[RFC] egg-bin plugin](https://github.com/eggjs/egg/issues/808)

# Discussion

choose a publish style ?
- ~~just PR to `egg-utils`(disadvantages: dependency too large)~~
- standalone in `egg-ast-utils`
- write as a `mrm-core` plugin

For most usage scenarios we need to bring in:
- `mrm-core` for common file usage, such as add script to package.json
- `egg-utils` to get plugin list, such as check whether plugin is install at framework, so only need to enable it at application
- `egg-ast-utils`, this lib, use AST to analysis and migrate egg files

# Proposal

Provide an utils for cli tools.

Use AST such as jscodeshift or babel inside.

## Usage

```js
const EggUtils = require('egg-ast-utils');
const { router, config, plugin } = new EggUtils({ baseDir });

router.add({
name: 'news_index'
path: '/news',
controller: 'news.list',
middlewares: [],
});

config('prod').set('news.pageCount', 100);

plugin().set('nunjucks', { package: 'egg-view-nunjucks' });

```

- router
- plugin
- config

## Router

- add to `app/router.js` (create if not exist)
- do not check whether controller is exist

### API

```js
/**
* @property {String} path - router path, required
* @property {String} controller - controller name, required
* @property {String} [name] - router name
* @property {String} [method] - http method, default to 'GET', case-insensitive
* @property {Array} [middlewares] - middleware names
*/
router.add({ method, name, path, controller, middlewares });

// short hand
router.add(path, controller);
router.add(method, path, controller);

```

### example

```js
router.add('/news', 'news.list');

// =>
module.exports = app => {
const { router, controller } = app;
router.get('/news', controller.news.list);
};
```

## Plugin

- **auto find `key` from plugin's package `eggPlugin.name` ?**
- support serverEnv
- add to `config/plugin.{env}.js` (create if not exist)
- only support the following style

### API

```js
/**
* @property {String} [serverEnv] - plugin file type, such as `local` for `plugin.local.js`, default to `plugin.js`
*/
const pluginFile = plugin(serverEnv);

/**
* @property {String} package - package name, required
* @property {Boolean} [enable]
* @property {Array} [env] - env list
*/
pluginFile.set({ package, enable });

pluginFile.get(key);
pluginFile.has(key);
pluginFile.remove(key);
pluginFile.enable(key);
pluginFile.disable(key);
```

### Support style

```js
exports.view = true;

exports.view = {
enable: true,
package: 'egg-view',
};
```

or

```js
module.exports = {
view: {
enable: true,
package: 'egg-view',
},
};

module.exports = {
view: true,
};
```

**DO NOT SUPPORT**:

```js
module.exports.view = true;
module.exports.view = {
enable: true,
package: 'egg-view',
};
```

## Config

- support serverEnv
- add to `config/config.{env}.js` (create if not exist)
- only support the following style

### API

```js
/**
* @property {String} [serverEnv] - config file type, such as `local` for `config.local.js`, default to `config.default.js`
*/
const configFile = config(serverEnv);

/**
* @property {String} package - package name, required
* @property {Boolean} [enable]
* @property {Array} [env] - env list
*/
configFile.set('news.pageCount', 100);

configFile.get(key);
configFile.has(key);
configFile.remove(key);
```

### Support style

```js
exports.keys ='12345';

exports.news = {
pageCount: 100,
};
```

or

```js
module.exports = {
news: {
pageCount: 100,
},
};
```

or

```js
module.exports = appInfo => {
const config = exports = {};
config.news = {
pageCount: 100,
};
return config;
};
```

# Others

- also need support fo typescript, but maybe another lib

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.