Skip to content

Instantly share code, notes, and snippets.

@hdd42

hdd42/feather.js

Last active Oct 17, 2019
Embed
What would you like to do?
/* anladigim kadariyla, soyle bisey yapmak istiyorsunuz,
Sizin backend servisiniz (feather ile yazilmis) , Backend-Service diyelim,
bir de baska bir external service endpoint var , Backend-external diyelim.
Son olarak birde front-end olacak bunada front-end-client.
Sizin yapmak istediginizde , eger yanlis anlamadiysam,
1 - Backend-Service ve front-end-client in birebir bagli olmasi ve real-time olarak bagli kalmasi
2- Backend-external in da bu surecte ilgili oldugu kisimlari update olarak alabilmesi.
Burda, sizin backend-service iniz, olusturdugunuz feathers service araciligiyla aslinda bir proxy gorevi yapmis olacak,
sizin gonderdiginiz 1.yazida ki sekliyle yazmaniz yeterli.
(backend-external da, sizin disinizda yapilan degisikleri dinleyip, onlarida backend-service ve front-end-client a
aktarmak biraz farkli bi durum, cunku backend-external a erisimiz, nasil bilmiyorum. ordan her guncelleme icin size bir,
bildirim yapiliyormu mesela? event, web socket, web hook call vs gibi. Yoksa sadece o endpointe http request gonderme imkaniniz mi var?)
1.kisim kolay, zaten feathers size gerekli alt yapiyi sunuyor,
Sizin feather ile yazdiginiz backend e bagli olan tum istemciler feather client araciligiyla, backend e baglanip,
butun default(create, delete vs) eventlerini ve sizin ekleyeceginiz custom eventleri dinleyebilirler.
(belirli client lara yada sadece, belirli kullanicilara gondermek icinde channel lari kullanabilirsiniz.)
https://docs.feathersjs.com/api/events.html#eventemitters
feathers, bu eventleri siz bilerek kapatmadiginiz surece, otomatik olarak tum bagli istemcilere yayinlar(publish/broadcast)
siz sadece feather client araciligiyla bunlari dinlersiniz,
https://docs.feathersjs.com/api/client.html , client olarak websocket veya rest adapater den birini veya ikisinide beraber kullanabilirsiniz.
(@feathersjs/socketio-client' ve/veya @feathersjs/rest-client )
ornegin front-end de dinlemek icin
feathers client i initialize ettik den sonra, ilgili service i service.event.callback signature ile dinleyebilirsiniz,
const messageService = client.service('messages');
messageService.on('created', message => console.log('Created a message', message));
burdaki linkden bakabilirsiniz. https://docs.feathersjs.com/api/client.html
2.kisim icin biraz daha bilgiye ihtiyac var, tam olarak bisey soyleyebilmek icin.
external-service deki sizin disinizda yapilan degisiklikleri de dinlemek istiyormusunuz?
bu external-service e sadece siz veri gondermek lemi ilgineyiorsunuz
eger dogru anladiysam ve ikinci soruya biraz daha aciklik getirirseniz, bir ornek olusturabilirim.
*/
// Eger, authantication i ayarlamadiysaniz henuz, socket eventlerini dinlemek icin
// channel.js deki asagidaki satiri simdilik yoru mhaline getirip
// //return app.channel('authenticated');
// bunu ekleyin,
// return app.channel('anonymous');
// boylece baglantili tum istemciler, oturum acip acmadikalrina bakmadan
// eventleri dinleyebilirler.
//
/** Ornek external service ve custom event*/
const httpClient = require("axios");// request modulu yerine, axios u tercih edebilirsiniz, daha hizli ve kolaydir.
/* eslint-disable no-unused-vars */
exports.ExternalProduct = class ExternalProduct {
constructor (options) {
this.options = options || {};
this.events = ['newProductAdded'];
httpClient.defaults.baseURL = 'https://api.example.com/api';
// httpClient.defaults.headers.common['Authorization'] = "AUTH_TOKEN";
httpClient.defaults.headers.common['Content-Type'] = "application/json";
this.httpAuthOptions = {
username: 'admin_email',
password: 'auto-generated API key'
};
this.startPolling()
}
async find (params) {
return httpClient.get("/products",{auth:this.httpAuthOptions});
}
async get (id, params) {
return httpClient.get(`/products/${id}`,{auth:this.httpAuthOptions});
}
async create (data, params) {
return httpClient.post(`/products`,data,{auth:this.httpAuthOptions});
/* if (Array.isArray(data)) {
return Promise.all(data.map(current => this.create(current, params)));
}
return data;
*/
}
async update (id, data, params) {
return httpClient.put(`/products/${id}`,data,{auth:this.httpAuthOptions});
}
async patch (id, data, params) {
return httpClient.patch(`/products`,data,{auth:this.httpAuthOptions});
}
async remove (id, params) {
return httpClient.delete(`/products/${id}`,{auth:this.httpAuthOptions});
// return { id };
}
startPolling() {
// her 10 dakikada bir external service i sorgula ve
// eger bir guncelleme varsa, bunu istemcileri ilet.
let lastUpdated = Date.now();
let queryUrl = `/products?lastUpdated=${lastUpdated}`;
httpClient
.get(queryUrl,{auth:this.httpAuthOptions})
.then(data =>{
this.emit('newProductAdded',{data});
setTimeout(()=> this.startPolling(), 600000 )//10 minutes in miliseconds
})
.catch(err =>{
console.log("error polling", err);
setTimeout(()=> this.startPolling(), 600000 )
})
}
};
/** **/
<!DOCTYPE html>
<html lang="en">
<head>
<title>A FeathersJS application</title>
<meta name="description" content="A FeathersJS server">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<style>
body {
padding: 20px;
}
</style>
</head>
<body >
<main id="app">
<div class="container">
<div class="row">
<div class="col-6">
<h3>My products</h3>
<table class="table table-striped table-hover">
<thead>
<tr>
<th>#</th>
<th>Id</th>
<th>Title</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr v-for="(product, index) in myProducts">
<td>{{index}}</td>
<td>{{product._id}}</td>
<td>{{product.title}}</td>
<td>{{product.price}}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-6">
<h3>External products </h3>
<table class="table table-striped table-hover table-dark">
<thead>
<tr>
<th>#</th>
<th>Id</th>
<th>Title</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr v-for="(product, index) in externalProducts">
<td>{{index}}</td>
<td>{{product.id}}</td>
<td>{{product.title}}</td>
<td>{{product.price}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<footer>
</footer>
</div>
</main>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/core-js/2.1.4/core.min.js"></script>
<script src="//unpkg.com/@feathersjs/client@^3.0.0/dist/feathers.js"></script>
<script src="//unpkg.com/socket.io-client@1.7.3/dist/socket.io.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const feathersClient = feathers();
const socket = io('http://localhost:3030');
feathersClient.configure(feathers.socketio(socket));
//app.configure(feathers.authentication());
const app = new Vue({
el: '#app',
data: {
myProducts:[],
externalProducts:[],
socketClient:undefined
},
mounted () {
axios
.get('/my-product')
.then(response => {
this.myProducts = response.data.data;
})
.catch(err => {
console.log(err);
});
axios
.get('/demo-external-products')
.then(response => {
this.externalProducts = response.data.data;
console.log(response.data)
})
.catch(err => {
console.log(err);
});
feathersClient.service('my-product').on('created', (data) => {
console.log(data);
this.myProducts.push(data)
});
feathersClient.service('my-product').on('removed', (data) => {
console.log("Deleted:",data)
this.myProducts = this.myProducts.filter(p => p._id!=data._id)
});
feathersClient.service('my-product').on('updated', (data) => {
console.log("Deleted:",data)
this.myProducts = this.myProducts.map(p =>{
if (p._id==data._id) return data
return p;
})
});
feathersClient.service('external-product').on('created', (data) => {
console.log(data)
this.externalProducts.push(data)
})
feathersClient.service('external-product').on('newProductAdded', (data) => {
console.log(data)
})
}
})
</script>
</body>
</html>
/** Ornek fronted
*//
@Nrhn

This comment has been minimized.

Copy link

@Nrhn Nrhn commented Oct 9, 2019

1 - Backend-Service ve front-end-client in birebir bagli olmasi ve real-time olarak bagli kalmasi

Bu kısım yaptım ve çalışır halde fakat eksikler çok :) event listenerlar yine burda da eksik henüz.

Benim şuan yapmak istediğim aşama tam olarak bu.

2- Backend-external in da bu surecte ilgili oldugu kisimlari update olarak alabilmesi.
Burda, sizin backend-service iniz, olusturdugunuz feathers service araciligiyla aslinda bir proxy gorevi yapmis olacak,
sizin gonderdiginiz 1.yazida ki sekliyle yazmaniz yeterli.
(backend-external da, sizin disinizda yapilan degisikleri dinleyip, onlarida backend-service ve front-end-client a
aktarmak biraz farkli bi durum, cunku backend-external a erisimiz, nasil bilmiyorum. ordan her guncelleme icin size bir,
bildirim yapiliyormu mesela? event, web socket, web hook call vs gibi. Yoksa sadece o endpointe http request gonderme imkaniniz mi var?)

API hakkında genel bilgi:

  • Uses Basic HTTP authentication, with admin e-mail as login and auto-generated API key as password

  • Relies on user group-defined privileges. User group assignment is defined directly in the objects

  • Uses HTTP 1.1 to implement REST.

  • 4 methods are available to view and modify objects:

  • GET—get object data

  • PUT—update object data

  • POST—create new object

  • DELETE—delete object

  • Accepts and returns data in JSON format

Create Object (POST):

  • To create an object, send a POST HTTP request to the URL that refers to the according object type.

  • Only URLs referring to a whole object type (without ID) can be used.

  • The submitted data must be a JSON array of keys and values for the object fields (e.g. {'fieldName1: value1, fieldName2: value2}.)

  • Some fields are mandatory for object creating. Refer to the API objects page for a complete list of supported fields for all supported objects.

  • The header Content-Type must be declared and set to application/json, otherwise the default text/plain is assumed and the request will fail.

Request Example

  1. Create a new product with the name “My Awesome Product”:

curl --user admin@example.com:APIkey --header 'Content-Type: application/json' -d '{"product": "My Awesome Product"}' -X POST 'http://example.com/api/products'

  1. Response
    Created object ID, e.g. {"product_id":"1"}, or an error.

Developer guide'da sadece http requestler için REST API başlığı bulabildim. çok saçma gelebilir bu soru ama bu API websocket gibi realtime olanakları sağlamıyorsa yapmak istediğim işlemi REST ile realtime bir çözüme ulaştırabilir miyim?

"2.kisim icin biraz daha bilgiye ihtiyac var, tam olarak bisey soyleyebilmek icin.
external-service deki sizin disinizda yapilan degisiklikleri de dinlemek istiyormusunuz?
bu external-service e sadece siz veri gondermek lemi ilgineyiorsunuz"

Bu iki soru çok iyi oldu gerçekten, tşk ederim. Bunu hiç düşünmemiştim çünkü şuan farkediyorum. Benim yaptığım değişiklikleri kesinlikle dinlemek istiyorum diye aklımdaydı fakat benim dışımdaki değişiklikleri dinlemekte mümkünse ve yapılabılıyorsa yapıp öğrenmek isterim.

@hdd42

This comment has been minimized.

Copy link
Owner Author

@hdd42 hdd42 commented Oct 10, 2019

Merhaba,

  1. kisim icin backend servici i yazdiysaniz, sadece client larda listener lari yazmak kaldi ozaman. Yapmaniz gereken tek sey istemcilerinize gore ilgili client kutuphanesini kullanmak, https://docs.feathersjs.com/api/client.html
    ben bi feathers projesi olusuturup, web icin bi istemci ornegini vue.js ile yazdim. fakat baska bir front-end kutuphanesi kullanirsaniz da mantik bire bir ayni, yukariya ornegi ekledim. Bakabilirsiniz.

Yine external service icinde ayni mantik gecerli, servisinizi, feathers signature daki gibi yazarsaniz, onun icinde otomatik olarak event ler publish edilecegi icin, yine 1.de oldugu gibi bagli tum istemcilerden dinleyebilirsiniz. external service orneginde , feathers in eventleri otomatik publish etmesi icin ilgili methodlarin calismasi yeterli olacaktir.

Bir baska secenekte eger direkt olarak dinleyen degilde sizin bildirim gondermeniz gerekenler varsa, en kolay yolu, service hook lar ile yapmaktir bunu. her service methodu icin ayri ayri hook yazbailirsiniz, bunun icinde bir ornek ekledim.

  1. durumda eger size bir websocket baglantisi saglamiyorlarsa, yada bir web hook register edemiyorsaniz karsi tarafa (ornegin bir cok sistem, sizin bir endpointinizi i web hook olarak yeni bir islem den sonra cagirip, sizi haberdar eder "yeni bir urun eklendi, bir sey silindi, guncellendi vs gibi.") boyle bir sey saglamiyorsa, web socket de olmadigi icin, tek secenek "Polling" kaliyor,

yani berlirli bir aralikla external servisi sorgulayip yeni bisey varmi yok mu sizin kendiniz kontrol etmeniz gerekiyor. Ornegin benim sorguladigim bir cok external api da bunun icin query ye 'lastUpdated={timestap|fulldate}' benzeri bir field eklemenize imkan veriyor boylelikle 100% real time olmasada belirli araliklarla sorgulama yapip guncellemeleri almaniza imkan veriyor, Tabi tarz bi sorgunun , sizin hedefinizde olan, external service tarafindan desteklenip, desteklenmedigini bilmiyorum

Kolay gelsin

@hdd42

This comment has been minimized.

Copy link
Owner Author

@hdd42 hdd42 commented Oct 10, 2019

@Nrhn , bu arada yukaridakileri yazarken sizin, Fetahers cli i kullanarak projenizi olsturdugunuzu varsaydim.
https://docs.feathersjs.com/guides/basics/generator.html

@Nrhn

This comment has been minimized.

Copy link

@Nrhn Nrhn commented Oct 14, 2019

@hdd42

This comment has been minimized.

Copy link
Owner Author

@hdd42 hdd42 commented Oct 17, 2019

Merhaba,
bu repo dan kodlari edinebilirsiniz

https://github.com/hdd42/feathers-demo

client => vue client , cd client && npm install && npm run serve
server => feathers server . cd server && npm install && npm run dev
external-service-demo => sizin baglanmaya calistiginiz , external servisi simule eden bir node/express server(in memory bir products arrrayi tutuyor)

bayadir , vue js ile calismadigim icin, bazi seyleri unutmusum, ama sanirim size fikir verecek kadar olmustur.
iki ayri servis ornegi yazmaya calistim, biri kendi servisiniz, digeride external api a baglanan service.
ornek olmasi acisindan, created ve removed eventlerini dinleyip ui a yansitmis olduk product servisiniz icin.
external servis icinde sadece removed eventinin ornegini yaptim cunku ztaen signature ayni digerlerini siz kolaylila yapabilirisniz buna bakarak.

3 uygulmayida calistirdiktan sonra, (vue client, feathers api ve external demo) , bir den fazla tarayici acip real time iletisimi test edip izleyebilirsiniz,

ornek ekran goruntusu :
https://vimeo.com/366917070

insallah yardimci olur
kolay gelsin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment