mean-expert-official / fireloop.io

Modern Real-Time Platform by MEAN Expert
Other
172 stars 36 forks source link

Community Questions #22

Closed jonathan-casarrubias closed 6 years ago

jonathan-casarrubias commented 7 years ago

Use this thread for community questions

tobibrandenberg commented 7 years ago

How to implement route changes with realtime? If I change route, data will be displayed for the first time, but if I call the route again, nothing appears... Only after doing reload.

kattsushi commented 7 years ago

How to migrate callbacks from loopback methods to models and that work reactively with the rxjs? Library, and that return observables in an automated process, the thought that with a sdk fork could generate those scripts in typescript, but I think Which should be at the moment of generating the model with fireloop

jonathan-casarrubias commented 7 years ago

Hey @tobibrandenberg thanks for reaching out,

I recently had that issue reported on this so I need to verify and send a fix asap.

But I'm working in a major milestone so it can take some days before I send a fix included for this issue.

jonathan-casarrubias commented 7 years ago

Hi @kattsushi, for loopback methods you refer to remote methods?

kattsushi commented 7 years ago

hi @jonathan-casarrubias nop to genarate Model.ts with fireloop, i refer methods of the model example Model.find( ) Model.findById() Model.updateAtr... etc. each model in my api loopback, the remote methods are resolved with the decorator @Model({..})

jonathan-casarrubias commented 7 years ago

Ok so these are the PersistedModel inherited methods, so you are asking about the callback for these?

I think Im understanding the case, so since -almost- everything is an asynchronous process, I usually use async in the backend for my flows.

For instance

import * as async from 'async';

@Model()
class MyModel {
     // operation before save hook
     beforeSave(param1, next) {
        // waterfall, parallel, series or the required async flow
        async.waterfall([
          (next: Function) => this.model.app.OtherModel.find(next),
          (result: Array<any>, next: Function) => this.model.update(..., next)
        ], next);
    }
}

So I have been historically doing this, about changing the PersistedModel method to return observables that can be done if we create a new persistedModel that replaces these methods and then inherit from that.

That my friend does not sounds like a bad Idea

kattsushi commented 7 years ago

@jonathan-casarrubias yes thanks for clear out this, yes i think good one idea, in fact it also happens that when generating the Model.ts with fireloop when changing PersistedModel methods to return observable they can be injected something similar to what happens with the decorator @Inyectable ({}),

I try to contribute with this, I am not an expert in typescript I've been with him for 4 months and he seems excellent on the client side and I'm implementing it on the server side and every day I like it more, but I think it's possible to do it for a fork and You will soon have news of this! Thank you!

jonathan-casarrubias commented 7 years ago

Hey @kattsushi this is what I like of community effort, I believe a decorator to inject these methods would be super cool.

At the beginning the idea was more likely to create facades for LoopBack but many great ideas are coming and seems that maybe I will need to create an actual directory here similar to the loopback repository that holds our new PersistedModel with observables and including the @Model, @BootScript, @Inject because it starting to seem like an actual framework.

If you want it, fork this repository and then create a core/Inject directory and write your decorator inside, similar to the @Model or @BootScript decorators. I will also migrate those to this repository.

By the moment we reach release candidate, I will be publishing under the @fireloop scope instead of the mean expert one.

So by that moment we would import as follows:

import { Model, Inject } from '@fireloop/core';
jonathan-casarrubias commented 7 years ago

hey @tobibrandenberg I have fixed the issue within the SDK Builder repository, since the bug was found in there. https://github.com/mean-expert-official/loopback-sdk-builder/issues/223

The fix will be landed within the next release

brannon-darby commented 7 years ago

What's the best way to send a LoopBack email using FireLoop? Can you provide an example?

jonathan-casarrubias commented 7 years ago

Hey @bdarby86 I don't see a way to directly send emails from FireLoop, but I'm pretty sure that if you send the emails from hooks, these hooks will be executed after you run FireLoop operations.

Example;

Think in a EmailNotification entity, if you add an after save hook that sends an email, after you create with your FireLoop Reference a emailNotification instance, then the email would be sent.

At this point it would be the only option for what you are asking.

I hope this helps you clarify this topic.

Cheers Jon

brannon-darby commented 7 years ago

@jonathan-casarrubias

Yes, that's exactly what I ended up doing - thanks for your help. The question was mainly due to my lack of experience with LoopBack - I was able to find an example in their docs and leverage the beforeSave operation hook auto-generated by FireLoop:

  beforeSave(ctx: any, next: Function): void {
    console.log(ctx.instance);
    let emergency = 'No';
    if (ctx.instance.isEmergency) {
      emergency = 'Yes';
    };
    let emailSubject = 'New Service Request | ' + ctx.instance.firstName + ' ' + ctx.instance.lastName;
    let emailBody = `
    <strong>Name:</strong>
    ${ctx.instance.firstName} ${ctx.instance.lastName} <br>
    <strong>Address:</strong>
    ${ctx.instance.address}, ${ctx.instance.city}, ${ctx.instance.state} ${ctx.instance.zipCode} <br>
    <strong>Phone Number:</strong>
    ${ctx.instance.phoneNumber} <br>
    <strong>Email:</strong>
    ${ctx.instance.email} <br>
    <strong>Primary Damage Type:</strong>
    ${ctx.instance.damageType} <br>
    <strong>Property Type:</strong>
    ${ctx.instance.propertyType} <br>
    <strong>Insurance Provider:</strong>
    ${ctx.instance.insuranceProvider} <br>
    <strong>Emergency?:</strong>
    ${emergency} <br>
    <strong>Timestamp:</strong>
    ${ctx.instance.createdAt} <br>
    `;
    this.model.app.models.Email.send({
      to: emailTo,
      from: emailFrom,
      subject: emailSubject,
      html: emailBody
    }, function(err) {
      if (err) {
        return console.log(err);
      }
    });
    next();
  }

At this point, I have a basic app built, but I've been struggling for several days attempting to serve it from an Amazon EC2 Ubuntu 16 instance. Which leads to my next question... what's the best way to serve this stack in Production? My FireLoop project includes common, server, and webapp. I've tried several methods using both apache2 and nginx, and the following seems to be getting me pretty close with apache2:

With this setup, I was able to successfully execute api calls when using explorer via port 3000, but requests from the client were receiving a connection refused error.

Any guidance would be greatly appreciated.

Cheers, Brannon

jonathan-casarrubias commented 7 years ago

Hey @bdarby86 that is exactly what I do, I install nginx then I create a block -virtual host- and with proxy pass as gateway for my applications, this way you set a domain for your project serving in port 80 and redirected to any 3000, 3001, etc. ports

brannon-darby commented 7 years ago

@jonathan-casarrubias Would you mind sharing a sample nginx config? I may just be configuring it incorrectly.

brannon-darby commented 7 years ago

Here's an nginx config that seems to be working well for me - figured I'd share in case it might be useful for anyone else:

#  this first block is specifically to support aws health checks
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        server_name "";
        location /health {
                access_log off;
                return 200;
        }
}

#  everything else to the static files in the /var/www/html directory
server {
        listen 80;
        listen [::]:80;

        server_name "";
        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;

        #  if the browser request is http, redirect to https
        location / {
                if ($http_x_forwarded_proto != 'https') {
                        return 301 https://$server_name$request_uri;
                }
                #  allows ng2 to control routing
                try_files $uri$args $uri$args/ /index.html;
        }
}
#  api server listening directly on port 5000
#  on port 3000 via nginx
server {
        listen 3000;
        listen [::]:3000;

        location / {
                proxy_pass http://127.0.0.1:5000;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
        }

}

Some notes around my specific setup:

lamquangphuc commented 7 years ago

I have just read API. Sometime, I need to subscribe once data. How can I get it (such as 'once' in Firebase)?

jonathan-casarrubias commented 7 years ago

@phuclam85 thanks for reaching out.

The FireLoop platform provides 2 types of API

1.- FireLoop API (provides hot observables) 2.- LoopBack API (provides cold observables)

Within the FireLoop API there is no once call, since we don't want cold observables within the FireLoop API, but by using the LoopBack API you can get the data once from any of your models.

Lets say you have a model Account, and you want to get the Account data once...

import { Account } from './shared/sdk/models';
import { AccountApi } from './shared/sdk/services';

.....

  constructor(accountApi: AccountApi) {
    accountApi.findOne({ where: { name: { 'Cookie Monster' }}}).subscribe((account: Account) => {
      console.log(account); // This will be received once
    })
  }

As you can see, in combination FireLoop + LoopBack APIs you get a really robust platform to do literally anything [For Free!].

http://loopback.io/doc/en/lb3/Working-with-data.html (LB API Reference)

Again when you create a project using FireLoop you will get Both of the APIs, you don't need to integrate or to take an extra step or something, It is just all is out of the box.

I hope this information helps to clarify your question.

Cheers Jon

sinjinn commented 7 years ago

Hi All,

I wanted to move away from Firebase and through some searches found your project. I've only been playing with it for a bit today, so please forgive me if I've missed something obvious. I not having any luck though getting realtime updates working. My 'find' and 'value' work fine, but when I add another item, I'm not receiving the update through 'value' or 'child_added'. Any thoughts on what I might be missing? I tried searching through the issues, but nothing popped up. Thanks!

    this.realTime.onReady().subscribe(() => {
      this.artistRef = this.realTime.FireLoop.ref<Artist>(Artist);

      this.artistApi.find()
        .subscribe((artist: any) => {
          console.log('Artist found!');
          console.log(artist);
        });
      this.artistRef.on('value')
        .subscribe((artists: Array<Artist>) => {
          console.log('Artist Value?');
          console.log(artists);
      });
      this.artistRef.on('child_added')
        .subscribe((artist) => {
          console.log('Another artist');
          console.log(artist);
      });
    });
  }
jonathan-casarrubias commented 7 years ago

@sinjinn just make sure that when you create your new item, you create it using the fireloop realtime reference and not the loopback REST Api

This should be good:

  this.artistRef.create(data).subscribe();

This is not good for realtime, this is only a regular REST Call

 this.artistApi.create(data).subscribe();
Alexej-Gorelik commented 7 years ago

Hello everyone.

Recently I try to use fireloop but have problems serving an "Angular 2 Ionic" app. It would be great if you could help me :) I use windows command promt, which could be the reoson for my troubles.

If I type serve, I get this error message:

`C:\A\tasks>fireloop serve

...

? What application do you want to serve? ionicapp events.js:160 throw er; // Unhandled 'error' event ^

TypeError: Cannot read property 'cmd' of undefined at C:\Users\Alexej Gorelik\AppData\Roaming\npm\node_modules\@mean-expert\fireloop\node_modules\generator-fireloop\generators\serve\index.js:46:27 at Array.forEach (native) at constructor. (C:\Users\Alexej Gorelik\AppData\Roaming\npm\node_modules\@mean-expert\fireloop\node_modules\generator-fireloop\generators\serve\ index.js:42:26)

I created the same model like in the "webapp" tutorial which works great for me. Maybe I should create a differnt kind of Model instead?

Do I need to post some more detailed information about something?

Thank you for answers `

sinjinn commented 7 years ago

Thank you @jonathan-casarrubias. I will try that. That must be it. I was testing things out with "Postman" and just posting items through the REST interface. Just for my own understanding, why are items not published if they come in through REST? Thanks again and great work on this.

jonathan-casarrubias commented 7 years ago

@sinjinn in the latests versions, the real-time component does update the client if the changes come either from the REST interface or the NodeJS Api..

The downside is that in order to achieve that you now need to register the FireLoop mixing,

{
  "name": "ModelName",
  ......
  "mixins":  {
     "FireLoop": true
   }
}