senecaãšactionheroã䜿çšããåŸãfeathersjsãç¥ã£ãŠããŸãã Feathersjsã«ã¯ããã€ãã®è¯ãç¹ããããŸãïŒãªã¢ã«ã¿ã€ã APIãããã¯ãããŒã¿ããŒã¹ã¢ããã¿ãŒïŒç¶ç·šãknexãç°è°ïŒã ãã ããäºåå®çŸ©ããããµãŒãã¹ã¡ãœãã[æ€çŽ¢ãååŸãäœæãæŽæ°ããããé©çšãåé€ãã»ããã¢ãã]å ã«ãªãç¬èªã®ã¡ãœããåãå®çŸ©ããããšã¯ã§ããŸããã
Feathers.slackã§ãeddyystopã¯æåã®ãã©ã¡ãŒã¿ãŒãšããŠã¡ãœããåã䜿çšããããšãææ¡ããŸããrpcService.create({ action: 'the RPC action', param1: ... , ... })
ããããããã¯ã¢ã³ããã¿ãŒã³ã®æ¹æ³ã®ããã«èŠããŸãã
足ãç®ãåŒãç®ãæãç®ãå²ãç®ã®ã¡ãœãããæã€æ°åŠãµãŒãã¹ãäœæããŸãã 1ã€ã®ãšã³ããã€ã³ãã«ã«ãŒãã£ã³ã°ããã¹ã€ããã䜿çšããŠæåã®ãã©ã¡ãŒã¿ãŒã確èªããå¿ èŠããããŸãã ããžãã¯ã¯ããã°ãããã¹ããå°é£ã«ãªããŸãã
RESTã®éå®ãããåè©ã䜿çšããããšãé©åããªãå¯èœæ§ãããããã€ãã®äŸïŒ
RESTã®æ矩ã¯ããªãœãŒã¹ãšå¶éãããHTTPåè©ã§ãã
RPCã®æ矩ã¯ãè¡åãåœä»€ã§ãã
ãã§ã¶ãŒãRESTãšRPCã®äž¡æ¹ããµããŒãããŠããã°çŽ æŽãããã§ãããã éçºè ããµãŒãã¹ããšã«æé©ãªãªãã·ã§ã³ãèªç±ã«éžæã§ããããã«ããŸãã
Feathersã¯RESTã¢ãŒããã¯ãã£ã®å¶çŽã«åºã¥ããŠæ§ç¯ãããŠãããããã«ã¯å€ãã®æ£åœãªçç±ããããŸãïŒ @marshallswainããã§ã«ãªã³ã¯ããŠãããã®ã§èšåãããŠãããã®ã
ãããŸã§ã®å©ç¹ïŒã»ãã¥ãªãã£ãäºæž¬å¯èœæ§ãæ確ã«å®çŸ©ããããªã¢ã«ã¿ã€ã ã€ãã³ãã®éä¿¡ãªã©ïŒã¯ãã¢ããªã±ãŒã·ã§ã³ããžãã¯ãæŠå¿µåãããšãã«å¿ èŠãªèãæ¹ã®å€åãå€§å¹ ã«äžåã£ãŠããŸãã
ããªãã®äŸã®ããã«ïŒ
ãªãœãŒã¹ãããŒã¿ããŒã¹ã¬ã³ãŒãã§ããå¿ èŠããããšã¯ã©ãã«ãèšããŸããã ããã¯ãä»»æã®çš®é¡ã®ãªãœãŒã¹ã«ããããšãã§ããŸãïŒéœåžã®çŸåšã®å€©æ°ãããããéä¿¡ããé»åã¡ãŒã«ã®äœæãªã©ïŒã é»åã¡ãŒã«ã®éä¿¡ã¯éåžžãå¥ã®é»åã¡ãŒã«ãµãŒãã¹ã®ããããã䜿çšããŠè¡ãããŸãã
app.use('/email', {
create(data) {
return sendEmail(data);
}
})
ãŸãã¯ããã¯ã§ã
ããããã§ã¶ãŒããã¯ã®ç®çã§ãã ãããã£ãŠãæ°ãã泚æãäœæãããšãã¯ãæ確ã«å®çŸ©ãããããã¯ãã§ãŒã³ããããŸãã
app.service('orders').before({
create: [
validateData(),
checkStock(),
checkVoucher()
]
}).after({
create: [
chargePayment(), // hook that calls `app.service('payment').create()`
sendEmail(), // hook that calls `app.service('email').create()`
updateStock() // Update product stock here
]
})
æåã¯å°ãå¥åŠã«æãããããããŸãããããããã®ãã¿ãŒã³ã«åãããŠã¿ãããšããå§ãããŸãã RPCã¹ã¿ã€ã«ã®ã©ã€ãã©ãªãæ¢ããŠãããªããFeathersã¯æ£ããéžæã§ã¯ãããŸããã
ã¹ã¬ããã¹ã¿ãŒã¿ãŒã«åæããŸãã ããã¯FeatherJSã®èšèšäžã®æ¬ é¥ã§ããå¯èœæ§ããããŸãã
é»åã¡ãŒã«ãšæ³šæãµãŒãã¹ã®äŸã¯ãcreateãã¡ãœããã䜿çšããŠã¢ãã«åã§ããŸãããç§ã®æ¥åã«ã¯ãåçŽã«RESTã¡ãœããã䜿çšã§ããªãããžãã¹ããžãã¯ã€ã³ã¹ã¿ã³ã¹ããããããããŸãã
ããã«ã€ããŠã®é«ã¬ãã«ã®è°è«ã¯ç¶ããŸããã ç¹å®ã®äŸãããå Žåã¯ããããã®ãã¿ãŒã³ãäžå¿ã«ãããè€éãªãŠãŒã¹ã±ãŒã¹ãã¢ãã«åããæ¹æ³ã玹ä»ããŸãã Feathersã¯ã RESTã¢ãŒããã¯ãã£ãã¿ãŒã³ãäžå¿ã«æ§ç¯ããããããå®æœãããã¬ãŒã ã¯ãŒã¯ã§ãã å®éã«RESTfulAPIãæäŸãããïŒãããŠãªã¢ã«ã¿ã€ã æ©èœãç¡æã§å ¥æãããïŒå Žåããããã®å¶çŽãåé¿ããæ¹æ³ã¯ãããŸããã
ããã§ãªãå Žåã¯ããã§ã«è¿°ã¹ãããã«ãå¥ã®ãã¬ãŒã ã¯ãŒã¯ãæ¢ãå¿ èŠããããŸãã
GraphQL + PostgraphQLã®æ¹ãè¡šçŸåã«åªããŠããããšãããããŸããã ãã§ã«åãæ¿ããŸããïŒ
Featherjsã¯åªããRESTãã¬ãŒã ã¯ãŒã¯ã§ãããããèªäœãå°æ°ã®RESTåè©ã«å¶éãããŠãããå®éã®äœ¿çšã«ã¯å®çšçã§ã¯ãããŸããã
äžçäžã®ã»ãŒãã¹ãŠã®ãã¯ãããžãŒäŒæ¥ã§äœ¿çšãããŠãããéå»25幎éã€ã³ã¿ãŒãããå šäœã§æ©èœããŠãããã¿ãŒã³ããå®éã«äœ¿çšãããŠããªãããšãç解ã§ããŸãããïŒ
GraphQLã¯ããŒã¿ã¯ãšãªã«é©ããŠããŸãããïŒããŒã¿ãã©ã®ããã«/å€æŽããããã決å®ããæ確ã«å®çŸ©ãããåè©ã®ã»ããã®ä»£ããã«ïŒä»»æã®ãã¥ãŒããŒã·ã§ã³ãå®çŸ©ã§ããããšã«ã¯ãç¬èªã®äžé£ã®èª²é¡ããããŸãïŒãããŠããã誰ãããªãçç±ã®1ã€ã§ãïŒããšãã°SOAPããã䜿çšããŠããŸãïŒã
ããã«ã¡ã¯ãFeathersJSã¯ãã®éšåãé€ããŠéåžžã«åªãããã¶ã€ã³ã ãšæããŸãã
ïŒå®éãç§ã¯èªåã®ä»äºã§Javaã®FeatherJS REST CrudïŒQuery Serviceãšåæ§ã®ããšãè¡ãããããåºç¯å²ã«äœ¿çšããŸãããGraphQLã®ãã¡ã³ã§ã¯ãããŸããïŒ
ãã ããã¢ããªã±ãŒã·ã§ã³ã䜿çšãããµãŒãã¹ã¯RESTãµãŒãã¹ã ãã§ã¯ãããŸããã ããããRESTãµãŒãã¹ã¯åã«ããµãŒãã¹ããšåŒã°ããã¹ãã§ã¯ãããŸããã
ç¹å®ã®ããžãã¹ããžãã¯ã®å Žåãcreate / update / patch / deleteã®ä»£ããã«ãããšãã°ãdoSomethingããªã©ã®ãµãŒãã¹ã¡ãœãããå¿
èŠã§ãã ïŒcosã®å Žåãã«ã¹ã¿ã ãµãŒãã¹APIã«ãŒããäœæããããšã¯å¯èœã§ãããWebSocketã䜿çšããå Žåã¯ããã¬ãŒã ã¯ãŒã¯ã«ãã£ãŠãã§ã«å¶åŸ¡ãããŠãããããã§ããŸãããïŒfeatherjs WebSocketåŠçã³ãŒãèªäœãå€æŽããªãéãïŒ
ãšã«ãããç§ã¯ããªããã¡ããã§ã«ã¯ãŒã«ãªãã¬ãŒã ã¯ãŒã¯ãããã«æ¹åããããã®ãã£ãŒãããã¯ãšããŠãããåãåãããšãã§ããããšãé¡ã£ãŠããŸãã 也æ¯ã
ããã§ããåé¡ã«åãçµãã¡ã³ã¿ã«ã¢ãã«ã®èª¿æŽã«ãããªãããšãå€ããšæããŸãã ã»ãšãã©ã®ãã«ã¹ã¿ã ãã¡ãœãã/æ©èœã¯ãæåã¯ãã®ããã«èŠããªãå Žåã§ããããã¯ã®ãã§ãŒã³ãŸãã¯ã«ã¹ã¿ã ãµãŒãã¹ãšããŠè¡šãããšãã§ããŸãã
ã°ããŒãã«ãªãã¿ã¹ã¯ãã®å Žåãããããããã¯ã§ããtasks
ãµãŒãã¹ãäœæããããšã«äœãåé¡ã¯ãªããšæããŸãã ããã¯æ¬¡ã®ããã«äœ¿çšã§ããŸã
app.service('tasks').create({
action: 'doSomething',
arguments: []
});
ãããã¯WebSocketãä»ããŠäœ¿çšã§ããã«ã¹ã¿ã ã€ãã³ããªã©ãä»ããŠã¹ããŒã¿ã¹ãå ±åããããšãã§ããŸãã
ã¯ãã 確ãã«ãããã¯åé¿çã§ãã ããããããã»ã©ãã¡ããšã¯ããŠããŸããã ãŸã åé¿çã ïŒ/
ãµãŒãã¹ã«ã«ã¹ã¿ã ã¡ãœãããè¿œå ã§ãããã©ã°ã€ã³ãäœæããŸããïŒ https ïŒ
@ arve0ãŸã ã¯ã©ã€ã¢ã³ãã§createã䜿çšããŠããŸãããä»ã®ãšããæ°ã«å ¥ã£ãŠããŸãã è¿œå ãèããŠããŸã
class BaseService {
constructor (options) {
this.options = options || {};
}
async create (data, params) {
if (Array.isArray(data)) {
return Promise.all(data.map(current => this.create(current, params)));
}
return data;
}
}
module.exports = BaseService;
åºæ¬ãµãŒãã¹ãäœæããããµãŒãã¹ã«createã³ãã³ããå«ããå¿ èŠã¯ãããŸããã
const BaseService = require('../base/base.service');
/* eslint-disable no-unused-vars */
class Service extends BaseService{
async doSomething (){
console.log('custom');
return {
text: `custom response`
};
}
}
module.exports = function (options) {
return new Service(options);
};
module.exports.Service = Service;
ãŸãããã®ã³ãŒãããžã§ãã¬ãŒã¿ãŒã«å«ãããšäŸ¿å©ã§ãã :)
ãã®åé¡ã¯ãã¯ããŒãºãããåŸãæè¿ã®ã¢ã¯ãã£ããã£ããªããããèªåçã«ããã¯ãããŠããŸãã é¢é£ãããã°ã«ã€ããŠã¯ããã®åé¡ãžã®ãªã³ã¯ãå«ãæ°ããåé¡ãéããŠãã ããã
æãåèã«ãªãã³ã¡ã³ã
Feathersã¯RESTã¢ãŒããã¯ãã£ã®å¶çŽã«åºã¥ããŠæ§ç¯ãããŠãããããã«ã¯å€ãã®æ£åœãªçç±ããããŸãïŒ @marshallswainããã§ã«ãªã³ã¯ããŠãããã®ã§èšåãããŠãããã®ã
ãããŸã§ã®å©ç¹ïŒã»ãã¥ãªãã£ãäºæž¬å¯èœæ§ãæ確ã«å®çŸ©ããããªã¢ã«ã¿ã€ã ã€ãã³ãã®éä¿¡ãªã©ïŒã¯ãã¢ããªã±ãŒã·ã§ã³ããžãã¯ãæŠå¿µåãããšãã«å¿ èŠãªèãæ¹ã®å€åãå€§å¹ ã«äžåã£ãŠããŸãã
ããªãã®äŸã®ããã«ïŒ
ãªãœãŒã¹ãããŒã¿ããŒã¹ã¬ã³ãŒãã§ããå¿ èŠããããšã¯ã©ãã«ãèšããŸããã ããã¯ãä»»æã®çš®é¡ã®ãªãœãŒã¹ã«ããããšãã§ããŸãïŒéœåžã®çŸåšã®å€©æ°ãããããéä¿¡ããé»åã¡ãŒã«ã®äœæãªã©ïŒã é»åã¡ãŒã«ã®éä¿¡ã¯éåžžãå¥ã®é»åã¡ãŒã«ãµãŒãã¹ã®ããããã䜿çšããŠè¡ãããŸãã
ãŸãã¯ããã¯ã§ã
ããããã§ã¶ãŒããã¯ã®ç®çã§ãã ãããã£ãŠãæ°ãã泚æãäœæãããšãã¯ãæ確ã«å®çŸ©ãããããã¯ãã§ãŒã³ããããŸãã
æåã¯å°ãå¥åŠã«æãããããããŸãããããããã®ãã¿ãŒã³ã«åãããŠã¿ãããšããå§ãããŸãã RPCã¹ã¿ã€ã«ã®ã©ã€ãã©ãªãæ¢ããŠãããªããFeathersã¯æ£ããéžæã§ã¯ãããŸããã