kevinresol / hxgenjs

Extensible JS generator for Haxe
57 stars 16 forks source link

Use together with ufront nodejs target #2

Closed varadig closed 7 years ago

varadig commented 7 years ago

I need to use hxgenjs with ufront (and some other lib) nodejs target.

build.hxml:

genjs.hxml

-lib hxgenjs

--macro allowPackage("sys")
-lib ufront-mvc
-lib hxnodejs
-lib js-kit
-lib smtpmailer
-lib record-macros
-lib gotocorehaxe
-lib gotocorehxnode
-lib erazor
-lib haxe-crypto
-lib hxnodejs-jsonwebtoken
-lib express
-lib tink_streams
-lib dotenv
-lib exceljs-hx
-js genjs/www/index.js
-dce full

genjs.hxml:

-cp src
-main Server

haxe build.hxml

src/model/api/AuthApi.hx:128: characters 63-67 : Unknown identifier : auth
src/model/api/AuthApi.hx:128: characters 63-67 : For function argument 'value'
/Volumes/Work/Haxe/libs/ufront-mvc/git/src/ufront/api/UFAsyncApi.hx:95: characters 2-67 : Missing return: tink.Surprise<_makeApiCall.A, tink.TypedError<ufront.remoting.RemotingError<_makeApiCall.B>>>
/Volumes/Work/Haxe/libs/ufront-mvc/git/src/ufront/web/result/CallJavascriptResult.hx:99: characters 16-24 : Unknown identifier : document
/Volumes/Work/Haxe/libs/ufront-mvc/git/src/ufront/web/result/CallJavascriptResult.hx:106: characters 17-25 : Unknown identifier : document
/Volumes/Work/Haxe/libs/ufront-mvc/git/src/ufront/web/result/CallJavascriptResult.hx:112: characters 4-12 : Unknown identifier : document
/Volumes/Work/Haxe/libs/ufront-mvc/git/src/ufront/web/result/CallJavascriptResult.hx:113: characters 4-12 : Unknown identifier : document
varadig commented 7 years ago

Ok I think, solved this too :) I forgot to add this compiler definition

-D server

varadig commented 7 years ago

Ok, now everything is compiled, but when I wanted to run node index.js I got this:

ReferenceError: $hxClasses is not defined at Object. (/Volumes/Work/Haxe/besocial/otponkentesseg/genjs/www/Std.js:25:31)

varadig commented 7 years ago

The Std.js line 25:

String.prototype.__class__ = $hxClasses["String"] = String

varadig commented 7 years ago

Ok I'm pretty shure the problem is with the ufront-mvc because if I build Main class with this:

package ;
import controller.ControllerTest;
import model.ModelTest;
import ufront.MVC;
import view.ViewTest;
class Main {
    static function main() {
        new ViewTest();
        new ModelTest();
        new ControllerTest();

        var ufApp:UfrontApplication = new UfrontApplication({
            indexController:HomeController
        });
        ufApp.listen(8080);
    }
}

class HomeController extends Controller {
    @:route(GET, "") public function index() {
        return new ViewResult({title:"asdasd"});
    }
}

I got this error:

Varadis-iMac:server varadig$ node server.js 
Test View
Test Model
Test Controller
/Volumes/Work/Haxe/hxgenjs/www/server/Type.js:44
        var cl = $hxClasses[name];
                           ^

ReferenceError: $hxClasses is not defined
    at Function.Type.resolveClass (/Volumes/Work/Haxe/hxgenjs/www/server/Type.js:44:21)
    at Function.CompileTimeClassList.initialise (/Volumes/Work/Haxe/hxgenjs/www/server/CompileTimeClassList.js:59:33)
    at Function.CompileTimeClassList.get (/Volumes/Work/Haxe/hxgenjs/www/server/CompileTimeClassList.js:30:24)
    at Function.DefaultUfrontConfiguration.get (/Volumes/Work/Haxe/hxgenjs/www/server/ufront/app/DefaultUfrontConfiguration.js:36:288)
    at Object.UfrontApplication (/Volumes/Work/Haxe/hxgenjs/www/server/ufront/app/UfrontApplication.js:42:73)
    at Function.Main.main (/Volumes/Work/Haxe/hxgenjs/www/server/Main.js:33:14)
    at Object.<anonymous> (/Volumes/Work/Haxe/hxgenjs/www/server/server.js:3:18)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)

ths Type.js:


// Class: Type

var $global = typeof window != "undefined" ? window : typeof global != "undefined" ? global : typeof self != "undefined" ? self : this

$global.Object.defineProperty(exports, "__esModule", {value: true});

var __map_reserved = {};

// Imports

var $import = require("./import_stub").default;
function js__$Boot_HaxeError() {return require("./js/_Boot/HaxeError");}
function Reflect() {return require("./Reflect");}
function HxOverrides() {return require("./HxOverrides");}
function ValueType() {return require("./ValueType");}
function js_Boot() {return require("./js/Boot");}

// Definition

var Type = function(){}

Type.__name__ = true;
Type.prototype = {

};

Type.getSuperClass = function(c) {
    return c.__super__;
}
Type.getClassName = function(c) {
    var a = c.__name__;
    if(a == null) {
        return null;
    }
    return a.join(".");
}
Type.getEnumName = function(e) {
    var a = e.__ename__;
    return a.join(".");
}
Type.resolveClass = function(name) {
    var cl = $hxClasses[name];
    if(cl == null || !cl.__name__) {
        return null;
    }
    return cl;
}
Type.resolveEnum = function(name) {
    var e = $hxClasses[name];
    if(e == null || !e.__ename__) {
        return null;
    }
    return e;
}
Type.createInstance = function(cl,args) {
    var _g = args.length;
    switch(_g) {
    case 0:
        return new cl();
    case 1:
        return new cl(args[0]);
    case 2:
        return new cl(args[0],args[1]);
    case 3:
        return new cl(args[0],args[1],args[2]);
    case 4:
        return new cl(args[0],args[1],args[2],args[3]);
    case 5:
        return new cl(args[0],args[1],args[2],args[3],args[4]);
    case 6:
        return new cl(args[0],args[1],args[2],args[3],args[4],args[5]);
    case 7:
        return new cl(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
    case 8:
        return new cl(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
    case 9:
        return new cl(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
    case 10:
        return new cl(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
    case 11:
        return new cl(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
    case 12:
        return new cl(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
    case 13:
        return new cl(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
    case 14:
        return new cl(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
    default:
        throw new (js__$Boot_HaxeError().default)("Too many arguments");
    }
}
Type.createEmptyInstance = function(cl) {
    function empty() {}; empty.prototype = cl.prototype;
    return new empty();
}
Type.createEnum = function(e,constr,params) {
    var f = (Reflect().default).field(e,constr);
    if(f == null) {
        throw new (js__$Boot_HaxeError().default)("No such constructor " + constr);
    }
    if((Reflect().default).isFunction(f)) {
        if(params == null) {
            throw new (js__$Boot_HaxeError().default)("Constructor " + constr + " need parameters");
        }
        return f.apply(e,params);
    }
    if(params != null && params.length != 0) {
        throw new (js__$Boot_HaxeError().default)("Constructor " + constr + " does not need parameters");
    }
    return f;
}
Type.getInstanceFields = function(c) {
    var a = [];
    for(var i in c.prototype) a.push(i);
    (HxOverrides().default).remove(a,"__class__");
    (HxOverrides().default).remove(a,"__properties__");
    return a;
}
Type.typeof = function(v) {
    var _g = typeof(v);
    switch(_g) {
    case "boolean":
        return (ValueType().default).TBool;
    case "function":
        if(v.__name__ || v.__ename__) {
            return (ValueType().default).TObject;
        }
        return (ValueType().default).TFunction;
    case "number":
        if(Math.ceil(v) == v % 2147483648.0) {
            return (ValueType().default).TInt;
        }
        return (ValueType().default).TFloat;
    case "object":
        if(v == null) {
            return (ValueType().default).TNull;
        }
        var e = v.__enum__;
        if(e != null) {
            return (ValueType().default).TEnum(e);
        }
        var c = (js_Boot().default).getClass(v);
        if(c != null) {
            return (ValueType().default).TClass(c);
        }
        return (ValueType().default).TObject;
    case "string":
        return (ValueType().default).TClass(String);
    case "undefined":
        return (ValueType().default).TNull;
    default:
        return (ValueType().default).TUnknown;
    }
}

exports.default = Type;

If I comment out the ufApp:

package ;
import controller.ControllerTest;
import model.ModelTest;
import ufront.MVC;
import view.ViewTest;
class Main {
    static function main() {
        new ViewTest();
        new ModelTest();
        new ControllerTest();

        var ufApp:UfrontApplication = new UfrontApplication({
            indexController:HomeController
        });
        ufApp.listen(8080);
    }
}

class HomeController extends Controller {
    @:route(GET, "") public function index() {
        return new ViewResult({title:"asdasd"});
    }
}

the error is gone, and the Type.js file is the following:

// Class: Type

var $global = typeof window != "undefined" ? window : typeof global != "undefined" ? global : typeof self != "undefined" ? self : this

$global.Object.defineProperty(exports, "__esModule", {value: true});

var __map_reserved = {};

// Imports

var $import = require("./import_stub").default;
function Reflect() {return require("./Reflect");}
function js__$Boot_HaxeError() {return require("./js/_Boot/HaxeError");}
function ValueType() {return require("./ValueType");}
function js_Boot() {return require("./js/Boot");}

// Definition

var Type = function(){}

Type.__name__ = true;
Type.prototype = {

};

Type.getClassName = function(c) {
    var a = c.__name__;
    if(a == null) {
        return null;
    }
    return a.join(".");
}
Type.getEnumName = function(e) {
    var a = e.__ename__;
    return a.join(".");
}
Type.createEmptyInstance = function(cl) {
    function empty() {}; empty.prototype = cl.prototype;
    return new empty();
}
Type.createEnum = function(e,constr,params) {
    var f = (Reflect().default).field(e,constr);
    if(f == null) {
        throw new (js__$Boot_HaxeError().default)("No such constructor " + constr);
    }
    if((Reflect().default).isFunction(f)) {
        if(params == null) {
            throw new (js__$Boot_HaxeError().default)("Constructor " + constr + " need parameters");
        }
        return f.apply(e,params);
    }
    if(params != null && params.length != 0) {
        throw new (js__$Boot_HaxeError().default)("Constructor " + constr + " does not need parameters");
    }
    return f;
}
Type.typeof = function(v) {
    var _g = typeof(v);
    switch(_g) {
    case "boolean":
        return (ValueType().default).TBool;
    case "function":
        if(v.__name__ || v.__ename__) {
            return (ValueType().default).TObject;
        }
        return (ValueType().default).TFunction;
    case "number":
        if(Math.ceil(v) == v % 2147483648.0) {
            return (ValueType().default).TInt;
        }
        return (ValueType().default).TFloat;
    case "object":
        if(v == null) {
            return (ValueType().default).TNull;
        }
        var e = v.__enum__;
        if(e != null) {
            return (ValueType().default).TEnum(e);
        }
        var c = (js_Boot().default).getClass(v);
        if(c != null) {
            return (ValueType().default).TClass(c);
        }
        return (ValueType().default).TObject;
    case "string":
        return (ValueType().default).TClass(String);
    case "undefined":
        return (ValueType().default).TNull;
    default:
        return (ValueType().default).TUnknown;
    }
}

exports.default = Type;

Here is a minimal sample project: hxgenjs.zip

varadig commented 7 years ago

Hi @kevinresol, thanks for the fix, but now i got this:

/Volumes/Work/Haxe/hxgenjs/www/minject/Injector.js:233
        throw new (js__$Boot_HaxeError().default)("Could not determine type name of " + (Std().default).string(value));
        ^
Error: Could not determine type name of {
        __name__ : [ufront,app,DefaultUfrontController], 
        __meta__ : {
                fields : {
                        showMessage : {
                                wrapResult : [<...>]
                        }
                }
        }
}
    at Function.Injector.getValueType (/Volumes/Work/Haxe/hxgenjs/www/minject/Injector.js:233:8)
    at Object.mapRuntimeTypeOf (/Volumes/Work/Haxe/hxgenjs/www/minject/Injector.js:39:32)
    at Object.UfrontApplication [as __class__] (/Volumes/Work/Haxe/hxgenjs/www/ufront/app/UfrontApplication.js:67:17)
    at Function.Main.main (/Volumes/Work/Haxe/hxgenjs/www/Main.js:35:14)
    at Object.<anonymous> (/Volumes/Work/Haxe/hxgenjs/www/server.js:3:18)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
kevinresol commented 7 years ago

Can you try 0.2.4?

varadig commented 7 years ago

Yes, now I can run the node UFrontApp, but I got this error:

[GET /] from [::1 The Boss], response: [500 text/html]
  Log: ufront.app.HttpApplication.executeModules(422): Caught error TypeError: Cannot read property 'actionContext' of undefined while executing module ufront.web.MVCHandler.handleRequest in HttpApplication.executeModules()
  Error: ufront.web.ErrorPageHandler.handleError(44): Handling error: Error#500: Internal Server Error @ ufront.web.MVCHandler.handleRequest:-1 (TypeError: Cannot read property 'actionContext' of undefined)

I made two hxml (basic.hxml && hxgen.hxml). The basic.hxml does not throw error.

hxgenjs.zip

kevinresol commented 7 years ago

This is harder to fix then I expected. Mostly because ufront is too complex in terms of its structure and it tends to reports error positions incorrectly. So my advice for now is, don't use ufront with hxgenjs.

So you can either use ufront alone, without hxgenjs. Or if you really need hxgenjs you can consider try using other web frameworks such as tink_web.

Btw, may I know why you want to split a server app into individual js files?

varadig commented 7 years ago

I wanted to split the code, because there is a lot of update on server side, and I don't wanted to upload/update any part.

kevinresol commented 7 years ago

if you could locate the actual line of js code where the error Cannot read property 'actionContext' of undefined occurs, it would be good...

varadig commented 7 years ago

In the HomeController.js, execute method:

...
    execute: function() {
        console.log("context:"+this.context);//context:undefined
...
// Class: HomeController

var $global = typeof window != "undefined" ? window : typeof global != "undefined" ? global : typeof self != "undefined" ? self : this

$global.Object.defineProperty(exports, "__esModule", {value: true});

var __map_reserved = {};

// Imports

var $hxClasses = require("./hxClasses_stub").default;
var $import = require("./import_stub").default;
var $extend = require("./extend_stub").default;
function ufront_web_Controller() {return require("./ufront/web/Controller");}
function ufront_web_result_ViewResult() {return require("./ufront/web/result/ViewResult");}
function ufront_view__$TemplateData_TemplateData_$Impl_$() {return require("./ufront/view/_TemplateData/TemplateData_Impl_");}
function haxe_rtti_Meta() {return require("./haxe/rtti/Meta");}
function js__$Boot_HaxeError() {return require("./js/_Boot/HaxeError");}
function ufront_web_HttpError() {return require("./ufront/web/HttpError");}
function ufront_core_SurpriseTools() {return require("./ufront/core/SurpriseTools");}
function Std() {return require("./Std");}

// Constructor

var HomeController = function() {
    (ufront_web_Controller().default).call(this);
}

// Meta

HomeController.__name__ = ["HomeController"];
HomeController.__super__ = ufront_web_Controller;
HomeController.prototype = $extend((ufront_web_Controller().default).prototype, {
    index: function() {
        var obj = { };
        var this1 = obj != null ? obj : { };
        return new (ufront_web_result_ViewResult().default)((ufront_view__$TemplateData_TemplateData_$Impl_$().default).setObject(this1,{ title : "asdasd"}));
    },
    execute: function() {
        console.log("context:"+this.context);//context:undefined
        var uriParts = this.context.actionContext.get_uriParts();
        var params = this.context.request.get_params();
        var method = this.context.request.get_httpMethod();
        this.context.actionContext.controller = this;
        this.context.actionContext.action = "execute";
        try {
            if(method.toLowerCase() == "get" && 0 == uriParts.length) {
                this.context.actionContext.action = "index";
                this.context.actionContext.args = [];
                this.context.actionContext.get_uriParts().splice(0,0);
                var this1 = (haxe_rtti_Meta().default).getFields(HomeController).index.wrapResult[0];
                var wrappingRequired = this1;
                var result = this.wrapResult(this.index(),wrappingRequired);
                this.setContextActionResultWhenFinished(result);
                return result;
            }
            throw new (js__$Boot_HaxeError().default)((ufront_web_HttpError().default).pageNotFound({ fileName : "Main.hx", lineNumber : 19, className : "HomeController", methodName : "execute"}));
        } catch( e ) {
            if (e instanceof (js__$Boot_HaxeError().default)) e = e.val;
            return (ufront_core_SurpriseTools().default).asSurpriseError(e,"Uncaught error while executing " + (Std().default).string(this.context.actionContext.controller) + "." + this.context.actionContext.action + "()",{ fileName : "Main.hx", lineNumber : 19, className : "HomeController", methodName : "execute"});
        }
    }
});
HomeController.prototype.__class__ = $hxClasses["HomeController"] = HomeController;

// Init

// Statics

HomeController.__meta__ = { fields : { index : { wrapResult : [3]}}}

// Export

exports.default = HomeController;
varadig commented 7 years ago

I think the Controller.js injectContext is not invoked:

Controller.prototype = {
    injectContext: function(context) {
        console.log("Controller::injectContext:"+context);
kevinresol commented 7 years ago

This bug should be fixed by v0.2.5

But you will encounter another bug about view template not found. That is because ufront trying to look for view template files relative to the "script directory" which could be a folder buried down the way for each individual js files. But I think that can be fixed by manually specifying a view folder

varadig commented 7 years ago

Thanks, the bug is gone! If I specify viewfolder in UfAppConfig like this:

 var ufApp:UfrontApplication = new UfrontApplication({
            indexController:HomeController,
            viewPath:"viewFolder"
        });
        ufApp.listen(8080);

screen shot 2017-09-05 at 11 11 28

the ViewEngine not found the viewFolder:

Unable to load view template: Error#500: No template found for home/index with extensions [html,tpl] @ ufront.view.UFViewEngine.getTemplate:165

Or this is a wrong way to setup viewPath?

kevinresol commented 7 years ago

as I said, the path is relative to the script directory, (See source code here: https://github.com/ufront/ufront-mvc/blob/bf4465c/src/ufront/view/FileViewEngine.hx#L55)

and "script directory" is where the running js file resides, which is now inside some folders according to the package structure.

So you can specify it as absolute path, or modify the path resolving logic.

But seems this is no longer issue of this library. Closing for now.

varadig commented 7 years ago

Thanks (y)