Git Product home page Git Product logo

hxnodejs's Introduction

hxnodejs

Haxe Node.JS

Build Status Haxelib Version Haxelib Downloads Haxelib License

Extern type definitions for Node.JS. Haxe 3.4 or newer is required.

Haxe-generated API documentation is available at http://haxefoundation.github.io/hxnodejs/js/Node.html.

Original node.js documentation can be found at http://nodejs.org/api/index.html.

Features

  • Full node.js API with documentation.
  • Strict typing for everything, fully leveraging Haxe type system.
  • Optionally typed event listeners.
  • Automatic insert of "require" statements for used modules.
  • Clean output.

Quick example

  1. Install hxnodejs with haxelib install hxnodejs (released version) or haxelib git hxnodejs https://github.com/HaxeFoundation/hxnodejs (latest from GitHub).

  2. Write some code and save to Main.hx:

    class Main {
        static function main() {
            var server = js.node.Net.createServer(function(socket) {
                socket.write("Echo server\n\n");
                socket.pipe(socket);
            });
            server.listen(1337, "127.0.0.1");
        }
    }
  3. Compile it with with haxe -lib hxnodejs -main Main -js main.js (optionally add -D js-es=6 for cleaner JavaScript output, since node.js is ES6-compliant)

  4. Look at generated main.js:

    // Generated by Haxe 4.0.0-rc.2+63144f6db
    (function ($global) { "use strict";
    class Main {
        static main() {
            var server = js_node_Net.createServer(function(socket) {
                socket.write("Echo server\n\n");
                socket.pipe(socket);
            });
            server.listen(1337,"127.0.0.1");
        }
    }
    var js_node_Net = require("net");
    Main.main();
    })({});
  5. You're awesome! (See more examples)

Status

This library is considered complete, but testing and contributions are welcome. See current issues and extern guidelines.

hxnodejs's People

Contributors

andyli avatar back2dos avatar cedx avatar ciscoheat avatar clemos avatar clue4gd avatar eduardo-costa avatar fantoine avatar fponticelli avatar gama11 avatar hexonaut avatar jbips avatar jgranick avatar jonasmalacofilho avatar kallekro avatar kevinresol avatar klabz avatar lublak avatar markknol avatar matthijskamstra avatar mikicho avatar nadako avatar ncannasse avatar realyuniquename avatar simn avatar takashiski avatar terurou avatar tobil4sk avatar tong avatar vladimyr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hxnodejs's Issues

hxnodejs distribution

how are we going to distribute this?

as a part of std lib:

  • out-of-the-box support which is very appealing to users (just install haxe and write stuff)
  • more support because (because we have to maintain our std lib)
  • inability to provide timely updates because haxe releases so rarely

as a haxelib:

  • easier to provide small updates and fixes
  • smaller and easier to maintain std lib
  • users have to install the library and thus learn about haxelib first (it could be installed by default tho)
  • possible desync and confusion with haxe/hxnodejs/node versions

also there seems to be some must-have node.js modules that everyone basically have in every app (e.g. express and its dependencies) - maybe we should also provide high-quality officially supported externs for that?

also what about nodejs Sys/sys implementation? it's not possible to implement full support because node.js lacks sync API that is required for haxe, but we could at least provide filesystem and Sys stuff.

consider using type parameters for e.g. EventEmitter

One feature of nodejs EventEmitter are that its methods are chainable, i.e. returning the emitter object itself, however our current externs are somewhat limiting their usage because these methods return EventEmitter instead of original type.

What we could do is something like this:

extern class EventEmitter<T:EventEmitter<T>> {
    function on(event:String, listener:Function):T;
}

extern class Process extends EventEmitter<Process> {
}

accessSync vs existsSync

I had to add the following on CastleDB:

untyped if( js.node.Fs.accessSync == null ) js.node.Fs.accessSync = (js.node.Fs : Dynamic).existsSync;

Not sure if we want to support this kind of backward compatibility or not. The issue in that case is that sys.FileSystem.exists was failing silently because of the catch( Dynamic )

Nodejs crypto methods

Imho crypto methods provided by nodejs should be used instead of the haxe(js) implementation.
I guess they are faster and probably less error prone.

For haxe.crypto.Md5 this would look like:

package haxe.crypto;

import js.node.Crypto;
import haxe.io.Bytes;

class Md5 {

    public static function encode( s : String ) : String {
        var h = Crypto.createHash( "md5" );
        h.update( s );
        return h.digest( "hex" );
    }

    public static function make( b : Bytes ) : Bytes {
        var h = Crypto.createHash( "md5" );
        h.update( b.getData() );
        return Bytes.ofData( h.digest() );
    }
}

What do you think?

Move non-api classes from hxnodejs to hxnodelibs

If we start to add npm stuff in hxnodejs the lib will quickly become bloated and hard to manage.
I think we should keep libraries externs in another repository and keep hxnodejs focused only in the official functionalities.

change "options" classes to struct typedefs

I don't get how these are supposed to be used.

extern class FileIOOption {
    var encoding : String;
    var flag : String;
    /* etc */
}

static function readFileSync(filename : String, options:FileIOOption):Dynamic;

In plain node.js, you just pass an object like {encoding: "utf-8"} to that function, so I think the correct way to map it to haxe would be:

typedef FileIOOption = {
    ?encoding:String,
    ?flag:String,
    /* etc */
}

Importing works, but fails after compiling

  1. After installing with haxelib git hxnodejs [email protected]:HaxeFoundation/hxnodejs.git;
  2. Adding it to the build.hxml file:
-cp src/haxe
-D js-es5
-lib hxnodejs
-main Main
-js main.js

And using the following Main script to test the code:

package;

import js.node.http.*;

class Main {

static function main() {
  new Main();
}

public function new() {
    testRest();
  }

  public function testRest() {
    var http = new Client();
    trace(http.request(Method.Get, 'http://www.google.com'));
  }
}

After compiling and running it with node main.js, I get the following error:

$ node main.js                                                                                                                                                                              [2.2.1]
/Users/fullofcaffeine/workspace/code/projectgtd/main.js:100
        var http = new js.node.http.Client();
                       ^
ReferenceError: js is not defined
    at Object.Main.testRest (/Users/fullofcaffeine/workspace/code//main.js:100:18)
    at Object.Main [as __class__] (/Users/fullofcaffeine/workspace//main.js:92:7)
    at Function.Main.main (/Users/fullofcaffeine/workspace/code/main.js:96:2)
    at /Users/fullofcaffeine/workspace/code//main.js:744:6
    at Object.<anonymous> (/Users/fullofcaffeine/workspace/code//main.js:745:3)
    at Module._compile (module.js:430:26)
    at Object.Module._extensions..js (module.js:448:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:471:10)

The generated javascript: http://pastie.org/private/c8eboqpnrawbxvucolodqa#18

What am I missing?

node 0.12

so, node 0.12 released before hxnodejs and we need to adapt externs for the new version

NodeJS Libraries

Can we create a new repository called hxnodelibs so we can do the same work adapting the most common nodejs libraries?
Some like:

  • mongodb
  • authom (git, google, FB, twitter, OAuth login system)
  • express
  • NW.js (node desktop apps)
  • peerjs (webrtc)
  • socket.io (websockets)
  • ws (websockets)

I have some work done in those libs, so I'm open to share things like I did in the start of hxnodejs
This is something I would advance in the long run. But some help from the community would be cool!

extern testing

we should somehow test these externs.

of course, we don't have resources to port and maintain node.js unit tests, but we at least need to make sure that every module can be parsed and typed and hope we made things right.

we can automate this by writing a macro that recurses into source directory and does Context.getModule(...) similar to what documentation generator does.

Naming conventions

We need to develop a clear package/module/type naming/placing conventions to use for these externs.

For example, right now (as of 681d4bb) we have the node.js fs module available as js.node.fs.File which seems weird.

Another demonstrative example is js.node.Buffer module that contains the BufferConst class that gives access to the INSPECT_MAX_BYTES value of the buffer node.js module.

Also, I believe Haxe std library doesn't capitalize acronyms, while node.js does.

We should sort this out.

Accepting either types in method arguments

Some methods in node.js accept one or another type, e.g. either String or Int. While it is easy to handle using @:overload in a basic case, it's more complicated when that type is used as a type parameter. For example, see: http://nodejs.org/api/process.html#process_process_setgroups_groups. The groups argument there is an Array that can contain both Int and String elements.

One option is to simply use Array<Dynamic>, however this is weak typing we'd like to avoid.

Another option is to introduce an abstract like this:

abstract Either<T1,T2>(Dynamic) from T1 to T1 from T2 to T2 {}

and then type that argument as Array<Either<String,Int>> which will restrict types to Int and String.

I believe this approach is used quite successfully by @andyli in his jQuery externs.

The questions are: do we want to introduce this? if yes, where do we want it to be (as it's quite universal) and how do we want it to be implemented (what about 3 and more Either types?)

Quickstart guide

For a newcomer, it's right now quite confusing to start with hxnodejs. Considering hxnodejs should the official set of Haxe externs for Nodejs and that it's already being used by other libs/frameworks out there (like Franco's Abe) I'm surprised we don't have more documentation, particularly on how to actually set it up for new Haxe nodejs projects.

Also, a quick mention of other externs and their relationship to this one (and why the user should pick this one over the others already available) would be nice.

As a side question - does anyone know why https://github.com/clemos/haxe-js-kit isn't the official nodejs extern repo instead? It seems to be under quite active development.

review/cleanup/rename js.node.NodeJS

It currently has a bunch of untyped __js__ things that are not really safe and can potentially conflict with local vars. To address that, I think we could add e.g. process and/or global to the list of JS pseudo-keywords, like we do for console, window and require.

remove unneeded `@:overload`

There are places where @:overload is used instead of simply making argument optional, i.e.:

@:overload(function():HTTPSServer { } ) 
static function createServer(listener : IncomingMessage -> ServerResponse -> Void):HTTPSServer;

could be reduced to

static function createServer(?listener : IncomingMessage -> ServerResponse -> Void):HTTPSServer;

Sys.args() length inconsistent across target?

In php target, Sys.args() returns only the "arguments", i.e. exclude the executable and the script.
For example it will return ['arg1', 'arg2', 'arg3'] for the command php script.php arg1 arg2 arg3

However, in hxnodejs, Sys.args() returns process.argv; which include the executable and the script.
For example the command node script.js arg1 arg2 arg3 will become ['node', 'script.js', 'arg1', 'arg2', 'arg3']

Ref:
http://php.net/manual/en/reserved.variables.argv.php
https://github.com/HaxeFoundation/haxe/blob/development/std/php/_std/Sys.hx#L34

Headers type in IncomingMessage'

I saw that in recent update, Http.headers had became EitherType<String, Array<String>>, I suppose to support the set-cookie header which is an array.

But I'm wondering why this haven't been changed in IncomingMessage. Was there a compatibility issue? If not, I'll make a PR to change it as well.

Thank you

review `@:overload`s

i added a bunch of @:overloads without knowing that haxe doesn't do return type overload selection (see HaxeFoundation/haxe#3501). now we have to review all @:overloads of this kind and replace them with EitherType return values.

event enum abstracts

Currently our event enumerations is a bit messy because we duplicate SOME (but not ALL) events of parent classes. We have to develop a convention on that.

Some thoughts:

  • Duplicating every parent event creates a lot of noise, but is probably good for documentation.
  • Not duplicating parent events makes externs cleaner, but we have to mention that it also can emit parent class events. Also, it makes switch too restrictive.
  • Maybe we could think of some technical solution to express @:enum abstract inheritance in Haxe itself. E.g. @:forward @:enum abstract ChildEvent(ParentEvent) {} or something. @Simn @ncannasse what do you think?

Working with dynamic objects returned by node API

Subj. See http://nodejs.org/api/os.html#os_os_networkinterfaces, for example.
These don't map to any standard Haxe type and working with them via Reflect is uncomfortable and untyped.

Even with no regard to node.js externs, people are often asking for a convenient and typed way to work with JS/JSON objects in Haxe and we still don't have one.

I wrote a DynamicObject abstract for myself (https://github.com/nadako/haxe-thingies/blob/master/src/DynamicObject.hx), but I remember we decided not to include it in the standard library. However, now that we want to provide "official" node.js externs, we need something like that.

What's our position on that, @Simn, @ncannasse?

standard define for nodejs?

I think we should enforce something like -D nodejs for using hxnodejs externs. That way we could know for sure whether we're on nodejs or not. This could be used in compiler, for example to conditionally add nodejs-specific identifiers to genjs pseudo-keywords (e.g. process or global). Another use is to provide Sys implementation on js using @:require(nodejs).

Thoughts?

TODOs

While working on externs, I've left some unresolved questions marked with TODO in the code. Before we "release" (by either merging into std lib or making a haxelib), we should handle all these.

deprecated node.js API

there are some deprecated API documented in current node.js docs. we could add @:deprecated metadata in haxe to warn user about that. think that's a nice free feature that plain node.js doesn't have.

thoughts?

version warning

produces this :

/home/clemos/Work/hxnodejs/src/_hxnodejs/VersionWarning.hx:9: characters 12-86 : Primitive not found macro@include_file:2
--macro:1: character 0 : Called from
Aborted

using haxe 3.2.1 (installed from official deb) + neko 2.0

method argument naming

I noticed that many (but not all) methods have arguments starting with p_ which is probably is a convention in Haxor engine, but we don't really use those in Haxe std library. Moreover, I think we should name extern methods arguments strictly after ones in node.js API docs

Constructor Functions without "new" keyword

Pending the implementation of HaxeFoundation/haxe#3441 in the Haxe compiler and assuming we get the @:selfCall meta data we should discuss how to implement constructor-without-new-keyword pattern. Here is an example of the pattern which is common in some NodeJS code:

var express = require("express");
var app = express();
express.static(...);

I recommend the following pattern for implementing this:

@:jsRequire("express")
extern class Express {

    ...

    @:selfCall function apply (ctorArgs ...):Express;

    ...

}

Converting the above example to Haxe will look like this:

var app = Express.apply();
Express._static(...);

This will also work for the utility function pattern as well. See here HaxeFoundation/haxe#3441 (comment)

Documentation formatting

It seems that haxe std lib is uses the following format for API docs:

/**
<tab>Return whether `v` is not a zero.
**/
function nonZero(v:Int):Bool;

Notice the comment format and backticks that mark arguments.
I think this style is "official" (@Simn is it?), so we should conform to it.

overriding standard types

I tried to add haxe.io.Bytes implementation, but there's a problem that in a macro it also tries to use the overriden class and then complains about using js.node.Buffer in a macro context.

What can we do with that? One option is to just move nodejs sys stuff into Haxe itself (and fence with #if nodejs), another one is to make it possible to override types only for target output context, not the macro one.

Also, @:coreApi metadata doesn't work on our overriden types.

cc @Simn @ncannasse

implicit conversion from underlying type to @:enum abstracts

For instance, fs.symlink accepts the type parameter that is String with predefined values in JS: dir, file and junction (see http://nodejs.org/api/fs.html#fs_fs_symlink_srcpath_dstpath_type_callback).

For those values, we provide a @:enum abstract SymlinkType (see

@:enum abstract SymlinkType(String) from String to String {
)

The question is: should we add from String to that abstract?

  • if we don't, user won't be able to just copy-paste js code and will have to change strings to enum values
  • if we do, user may pass an invalid string so we lose strict typing

Another option is add a @:from method with validation, but I don't think that's a good idea because that would add runtime cost (we could only add it in -debug mode tho).

exporting node.js inner classes

I wonder if we should add @:jsRequire to e.g. http.Server. In upstream modules they are exported but they are not meant to be created with new. I don't know about extending however. Any thoughts?

Also, currently Haxe generates a lot of requires that are not really used in the code (see HaxeFoundation/haxe#3050). I wonder how big issue is that? My guess that it's negligible for long-running processes (such as servers), but what about one-time scripts? Could the startup time slowdown be significant for those?

extern guidelines

we need to make a guideline document that describes how to write externs for third-party node.js modules so they fit nicely in our official structure.

  • module classes/packages, @:jsRequire
  • event enums
  • structure typing
  • overloading and optional args
  • usage of EitherType and DynamicAccess (when it's finally merged)
  • anything else?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.