Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@horizon/client in Node.js #571

Closed
hnordt opened this issue Jun 8, 2016 · 15 comments
Closed

@horizon/client in Node.js #571

hnordt opened this issue Jun 8, 2016 · 15 comments

Comments

@hnordt
Copy link
Contributor

hnordt commented Jun 8, 2016

I need to start a Horizon server and create an endpoint that will store a message in Horizon, so here is what I did:

const express = require('express')
const bodyParser = require('body-parser');
const Horizon = require('@horizon/client')
const HorizonServer = require('@horizon/server')

const app = express()
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))

const horizon = Horizon()

app.post('/messages', (req, res) => {
  horizon('messages').store(req.body).subscribe(data => {
    res.send(data)
  }, error => {
    res.status(500).send({ error })
  })
})

const httpServer = app.listen(process.env.HORIZON_PORT || 8181)
const horizonServer = HorizonServer(httpServer, {
  auth: {
    token_secret: 'xyz'
  }
})

The problem is that when I run node server.js I receive an error:

Error: Cannot find module 'imports?this=>global!exports?global.fetch!isomorphic-fetch'

Then I changed const Horizon = require('@horizon/client') to const Horizon = require('@horizon/client/dist/horizon'), but when I run node server.js and dispatch a POST /messages call the server crashes and display the horizon.js code:

~/workspace/horizon (master) $ node server.js 
info: Connecting to RethinkDB: localhost:28015
/Users/hnordt/workspace/healthware_horizon/node_modules/@horizon/client/dist/horizon.js:2
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(function(){try{return require("ws")}catch(t){}}()):"function"==typeof define&&define.amd?define(["ws"],e):"object"==typeof exports?exports.Horizon=e(function(){try{return require("ws")}catch(t){}}()):t.Horizon=e(t.ws)}(this,function(t){return function(t){function e(n){if(r[n])return r[n].exports;var u=r[n]={exports:{},id:n,loaded:!1};return t[n].call(u.exports,u,u.exports,e),u.loaded=!0,u.exports}var r={};return e.m=t,e.c=r,e.p="",e(0)}(function(t){for(var e in t)if(Object.prototype.hasOwnProperty.call(t,e))switch(typeof t[e]){case"function":break;case"object":t[e]=function(e){var r=e.slice(1),n=t[e[0]];return function(t,e,u){n.apply(this,[t,e,u].concat(r))}}(t[e]);break;default:t[e]=t[t[e]]}return t}([function(t,e,r){"use strict";r(130),r(129),r(131),r(132),t.exports=r(118)},function(t,e,r){"use strict";var n=r
~/workspace/horizon (master) $ 

Am I doing something wrong?

@jswhisperer
Copy link
Contributor

jswhisperer commented Jun 9, 2016

Don't include "const Horizon = require('@horizon/client')" on the server.
Then the on the client include a script tag<script src="horizon/horizon.js"> this is dynamically served when you create HorizonServer. Past that there needs more documentation... I'm also stuck since you can't pass any options for authentication.

You also won't need POST routes, this is handled by horizon, and websockets that communicate to the database.

@deontologician
Copy link
Contributor

I think this is what require('@horizon/client/lib') is for. /dist/* are all minified, the lib folder is the individual files, already preprocessed by babel and webpack, but not minified or concatenated.

That being said, this is confusing and we should document how to do this or make the process easier. Our "isomorphic" method right now is not the greatest.

@deontologician deontologician added this to the Triaging... milestone Jun 9, 2016
@deontologician
Copy link
Contributor

@hnordt let me know if including @horizon/lib/index helps, if not this is a bug in the build system

@jswhisperer
Copy link
Contributor

@deontologician const Horizon = require('@horizon/client') is for on the client is it not?
I don't see it as a build system bug, unless I'm wrong.

He can either use webpack, or browserify or include <script src="horizon/horizon.js"> to get the client library... but on the client?

@deontologician
Copy link
Contributor

He's trying to create an rest endpoint that stores something in the database. You should be able to use the horizon client in Node if you want to, it should be importable without problems. The stack trace he's getting with minified code indicates the wrong thing is being imported, since minified code is only for the browser.

Whether the endpoint needs to be set up this way, I can't comment on since I don't know what requirements @hnordt's app has, maybe it needs rest endpoints for other clients. But for the immediate problem he's presented, it seems like he should be able to do it.

@marshall007
Copy link
Contributor

@deontologician it looks like the main entry in the package.json is still pointing at the old lib/index.js which no longer exists. Shouldn't it be dist/horizon.js?

@deontologician
Copy link
Contributor

lib/index.js still exists, it's built by webpack, not checked in. I am not sure how main is used though, it's possible we should change it depending on front/back end to make it less confusing

@marshall007
Copy link
Contributor

@deontologician where/when does the lib directory it get built? When I run npm run build I only see the dist directory created.

main is used by npm to resolve a modules entry point. So currently require('@horizon/client') resolves to @horizon/client/lib/index.js. If dist/horizon.js is bundled as a valid CommonJS module, which it appears to be, also requiring it from Node should be fine. I think it makes sense to point to the same file in both environments if we can.

@hnordt
Copy link
Contributor Author

hnordt commented Jun 9, 2016

@deontologician @marshall007

The feature I need is:

  1. Start a Horizon server and use normally with my React apps
  2. Enable external APIs to store data in my Horizon server (the way I want to do that is exposing a HTTP API)

So I have started a Horizon server with @horizon/server and tried to connect to it using @horizon/client with Node.js, but looks like the @horizon/client doesn't work with Node.js.

@jswhisperer
Copy link
Contributor

Guess it's going to be tricky getting a client side auth (JWT) then adding it to Node, presumably hitting a websocket connection from a REST endpoint.

@theundebruijn
Copy link

theundebruijn commented Jun 10, 2016

@hnordt this works fine for me using something like

const horizon_server = require('@horizon/server');
const horizon_client = require("@horizon/client/dist/horizon");

let http = require('http');
let express = require('express');
let app = express();
let http_server = http.createServer(app).listen(8181, function (err) {});

const my_horizon_client = horizon_client({host: 'localhost:8181', secure: false, path: 'horizon'});
my_horizon_client.connect();

@deontologician as I understand this "isomorphic" approach should be a valid way of interacting with Horizon. While this is awesome! 🎉, I'm having issues getting this to work over https/ssl/wss.

The node process running the horizon client (in my setup this is a client separate from the node process running the horizon server - not like the example above), fails to handshake/connect when the horizon server is only available over https. This is the output I'm seeing from node.js:

Received an error: Error: Websocket wss://localhost:8181 experienced an error

To be clear, browser clients connecting to the same wss endpoint work fine. (the self signed cert has been loaded in the OS X keychain and is used by the browser)

If this is a separate issue, feel free to branch 😃

@flipace
Copy link
Contributor

flipace commented Jun 10, 2016

@deontologician @dalanmiller the workaround with the webpack import/export loader for fetch should not be needed anymore thanks to a fix in the fetch-everywhere package!

It should be removed with the next version..

lucasfeliciano/fetch-everywhere@a4b5408

@deontologician
Copy link
Contributor

beautiful!

On Fri, Jun 10, 2016, 02:25 Patrick Neschkudla notifications@github.com
wrote:

@deontologician https://github.com/deontologician @dalanmiller
https://github.com/dalanmiller the workaround with the webpack
import/export loader for fetch should not be needed anymore thanks to a fix
in the fetch-everywhere package!

It should be removed with the next version..

lucasfeliciano/fetch-everywhere@a4b5408
lucasfeliciano/fetch-everywhere@a4b5408


You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
#571 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AAAFVmhZSfm7Wmq23tc6cDhylLtOr4CAks5qKS2EgaJpZM4IwpZv
.

@dalanmiller
Copy link
Contributor

@flipace I've been watching that other issue unfold. I'm glad it worked out!

deontologician pushed a commit that referenced this issue Jun 15, 2016
…#477, #420) (#593)

* remove isomorphic-fetch and imports/exports loaders, use whatwg-fetch, replace webpack specific syntax in fetch.js and move it to webpack config

* remove deprecated loaders

* Revert "remove deprecated loaders"

This reverts commit 90bc2d0.
deontologician pushed a commit that referenced this issue Jun 16, 2016
…#477, #420) (#593)

* remove isomorphic-fetch and imports/exports loaders, use whatwg-fetch, replace webpack specific syntax in fetch.js and move it to webpack config

* remove deprecated loaders

* Revert "remove deprecated loaders"

This reverts commit 90bc2d0.
@deontologician
Copy link
Contributor

This was fixed by be83b22

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

No branches or pull requests

7 participants