创建一个Feathers插件

创建插件的最简单方法是使用 Yeoman generator.

首先安装发电机

$ npm install -g generator-feathers-plugin

然后在新目录中运行:

$ yo feathers-plugin

这将支持开始编写插件所需的一切.

从发电机输出文件:

create package.json
create .babelrc
create .editorconfig
create .jshintrc
create .travis.yml
create src/index.js
create test/index.test.js
create README.md
create LICENSE
create .gitignore
create .npmignore

简单吧?我们在技术上可以称它为一天,因为我们创建了一个插件.但是,我们可能想要做更多.一般来说,插件是 服务.有趣的是,插件可以包含我们将在下面创建的多个服务.这个例子将构建2个服务.第一个将允许我们找到Feathers核心团队的成员,第二个将允许我们找到美国最好的州.

##验证我们的服务

在我们开始编写更多代码之前,我们需要看到事情正在发挥作用.

$ cd example && node app.js

Error: Cannot find module '../lib/index'

简单?我们可以在技术上称它为一天,因为我们创建了一个插件.但是,我们可能想要做更多.一般来说,插件是 ../api/services.有趣的是,该插件可以包含我们将在下面创建的多个服务.此示例将构建2个服务.第一个将允许我们找到Feathers核心团队的成员,第二个将允许我们找到美国最好的州.

"scripts": {
    "prepublish": "npm run compile",
    "publish": "git push origin && git push origin --tags",
    "release:patch": "npm version patch && npm publish",
    "release:minor": "npm version minor && npm publish",
    "release:major": "npm version major && npm publish",
    "compile": "rimraf lib/ && babel -d lib/ src/",
    "watch": "babel --watch -d lib/ src/",
    "jshint": "jshint src/. test/. --config",
    "mocha": "mocha --recursive test/ --compilers js:babel-core/register",
    "test": "npm run compile && npm run jshint && npm run mocha",
    "start": "npm run compile && node example/app"
  }

回到工作.该错误消息告诉我们,我们需要构建我们的项目.在这种情况下,这意味着babel需要做的事情.对于开发,您可以运行手表

$ npm run watch

> creatingPlugin@0.0.0 watch /Users/ajones/git/training/creatingPlugin
> babel --watch -d lib/ src/

src/index.js -> lib/index.js

之后,您可以运行示例应用程序,一切都应该很好.

$ node app.js
Feathers app started on 127.0.0.1:3030

扩展我们的插件

现在我们进行了验证,我们可以安全地改变一切.对于此示例,我们希望从插件中公开2个服务.让我们在src文件夹中创建一个服务目录.

// From the src directory
$ mkdir services
$ ls
index.js services

现在让我们创建两个服务.我们将只复制index.js文件.

$ cp index.js services/core-team.js
$ cp index.js services/best-state.js
$ cd services && ls
best-state.js core-team.js

$ cat best-state.js

if (!global._babelPolyfill) { require('babel-polyfill'); }

import errors from 'feathers-errors';
import makeDebug from 'debug';

const debug = makeDebug('creatingPlugin');

class Service {
  constructor(options = {}) {
    this.options = options;
  }

  find(params) {
    return new Promise((resolve, reject) => {
      // Put some async code here.
      if (!params.query) {
        return reject(new errors.BadRequest());
      }

      resolve([]);
    });
  }
}

export default function init(options) {
  debug('Initializing creatingPlugin plugin');
  return new Service(options);
}

init.Service = Service;

此时我们有index.js,best-state.js和core-team.js,内容相同.下一步将是更改index.js,以便它是我们的主文件.

我们新的index.js

if (!global._babelPolyfill) { require('babel-polyfill'); }

import coreTeam from './services/core-team';
import bestState from './services/best-state';

export default { coreTeam, bestState };

现在我们需要实际编写服务.我们只会实现find动作,因为您可以参考 服务 来了解更多信息.从core-team.js开始,我们想要找出github上的feathers.js org中列出的成员的名字.

//core-team.js
if (!global._babelPolyfill) { require('babel-polyfill'); }

import errors from 'feathers-errors';
import makeDebug from 'debug';

const debug = makeDebug('creatingPlugin');

class Service {
  constructor(options = {}) {
    this.options = options;
  }

  //We are only changing the find...
  find(params) {
    return Promise.resolve(['Mikey', 'Cory Smith', 'David Luecke', 'Emmanuel Bourmalo', 'Eric Kryski',
      'Glavin Wiechert', 'Jack Guy', 'Anton Kulakov', 'Marshall Thompson'])
  }
}

export default function init(options) {
  debug('Initializing creatingPlugin plugin');
  return new Service(options);
}

init.Service = Service;

现在,当调用service.find时,它将返回一个名称数组.继续使用最佳状态服务,我们可以遵循相同的模式

if (!global._babelPolyfill) { require('babel-polyfill'); }

import errors from 'feathers-errors';
import makeDebug from 'debug';

const debug = makeDebug('creatingPlugin');

class Service {
  constructor(options = {}) {
    this.options = options;
  }

  find(params) {
    return Promise.resolve(['Alaska']);
  }
}

export default function init(options) {
  debug('Initializing creatingPlugin plugin');
  return new Service(options);
}

init.Service = Service;

请注意,在上面的服务中,它返回一个列出最佳状态的单个项目数组.

用法

使用我们插件的最简单方法是在我们之前使用的app.js文件中.让我们在该文件中写出一些基本用法.

//app.js
const feathers = require('feathers');
const rest = require('feathers-rest');
const hooks = require('feathers-hooks');
const bodyParser = require('body-parser');
const errorHandler = require('feathers-errors/handler');
const plugin = require('../lib/index');

// Initialize the application
const app = feathers()
  .configure(rest())
  .configure(hooks())
  // Needed for parsing bodies (login)
  .use(bodyParser.json())
  .use(bodyParser.urlencoded({ extended: true }))
  // Initialize your feathers plugin
  .use('/plugin/coreTeam', plugin.coreTeam())
  .use('/plugin/bestState', plugin.bestState())
  .use(errorHandler());


var bestStateService = app.service('/plugin/bestState')
var coreTeamService = app.service('/plugin/coreTeam')

bestStateService.find().then( (result) => {
  console.log(result)
}).catch( error => {
  console.log('Error finding the best state ', error)
})

coreTeamService.find().then( (result) => {
  console.log(result)
}).catch( error => {
  console.log('Error finding the core team ', error)
})

app.listen(3030);

console.log('Feathers app started on 127.0.0.1:3030');
$ node app.js

Feathers app started on 127.0.0.1:3030
[ 'Alaska' ]
[ 'Mikey',
  'Cory Smith',
  'David Luecke',
  'Emmanuel Bourmalo',
  'Eric Kryski',
  'Glavin Wiechert',
  'Jack Guy',
  'Anton Kulakov',
  'Marshall Thompson' ]

测试

我们的发电机剔除了一些基本测试.我们将删除所有内容并将其替换为以下内容.

import { expect } from 'chai';
import plugin from '../src';

const bestStateService = plugin.bestState()

describe('bestState', () => {
  it('is Alaska', () => {
    bestStateService.find().then(result => {
      console.log(result)
      expect(result).to.eql(['Alaska']);
      done();
    });
  });
});
$ npm run test

因为这只是一个快速的示例jshint可能会失败.您可以修复语法或更改测试命令.

$ npm run compile && npm run mocha

这应该为您提供创建Feathers插件的基本概念.