Skip to content

Instantly share code, notes, and snippets.

@MadcapJake
Last active August 29, 2015 14:15
Show Gist options
  • Save MadcapJake/a8b59a2ec665b809d009 to your computer and use it in GitHub Desktop.
Save MadcapJake/a8b59a2ec665b809d009 to your computer and use it in GitHub Desktop.
Ceylon Express Typesafe Interface
"Run the module `my.blog`."
shared void run() {
Application app;
app = Application();
dynamic server = app.js.listen(3000, void () {
dynamic {
console.log(
"Express is listening to http://localhost:3000"
);
}
});
}
shared dynamic AppInterface {
shared formal void listen(Integer port, Anything() callback);
}
shared class Application() {
"Encapsulates express logic that works when not interfaced"
dynamic dynRequire() {
dynamic {
dynamic required = require("express");
//must call here; otherwise gets "type not callable" errors
dynamic calledRequired = required();
return calledRequired;
}
}
"Should apply interface to javascript code"
AppInterface dynInit() {
dynamic {
return dynRequire();
}
}
"Contains the actual js object."
shared AppInterface js = dynInit();
}
@MadcapJake
Copy link
Author

I think this is actually quite different from the new JavaScript pattern as this is calling a constructor function in js and ceylon-js code just keeps giving undefined errors.

@chochos
Copy link

chochos commented Feb 11, 2015

What exactly does require("express") return? Is it really a function? Do you need to invoke that function with new or just a normal invocation?

@MadcapJake
Copy link
Author

just a normal invocation but I've run into two problems getting it to invoke:

  1. If I apply an interface to its return, i try to call it and i get a "not callable" error. (Maybe you could add dynamic() Application { ... } where the parens indicate a callable dynamic interface)
  2. If I try to call it as shown (within a dynamic block) I get this error:
if(type.t.$$.T$name in obj.getT$all()){
                           ^
TypeError: Cannot use 'in' operator to search for 'my.blog::AppInterface' in undefined
    at is$ (C:\Users\madca_000\.eclipse\org.eclipse.platform_4.4.1_1167611518_win32_win32_x86_64\plugins\com.redhat.ceylon.dist.repo_1.1.1.v20150208-2150\repo\ceylon\language\1.1.1\ceylon.language-1.1.1.js:340:28)
    at Object.dre$$ (C:\Users\madca_000\.eclipse\org.eclipse.platform_4.4.1_1167611518_win32_win32_x86_64\plugins\com.redhat.ceylon.dist.repo_1.1.1.v20150208-2150\repo\ceylon\language\1.1.1\ceylon.language-1.1.1.js:698:5)
    at $init$Application.application$.$5 (C:\Users\madca_000\eclipse\ceylon-express-attempt\modules\my\blog\1.0.0\my.blog-1.0.0.js:93:28)
    at Application (C:\Users\madca_000\eclipse\ceylon-express-attempt\modules\my\blog\1.0.0\my.blog-1.0.0.js:65:35)
    at run (C:\Users\madca_000\eclipse\ceylon-express-attempt\modules\my\blog\1.0.0\my.blog-1.0.0.js:14:8)
    at [eval]:1:283
    at Object.<anonymous> ([eval]-wrapper:6:22)
    at Module._compile (module.js:456:26)
    at evalScript (node.js:536:25)
    at startup (node.js:80:7)

@MadcapJake
Copy link
Author

Here is the express.js code from the main export file:

exports = module.exports = createApplication;

/**
 * Create an express application.
 *
 * @return {Function}
 * @api public
 */

function createApplication() {
  var app = function(req, res, next) {
    app.handle(req, res, next);
  };

  mixin(app, proto);
  mixin(app, EventEmitter.prototype);

  app.request = { __proto__: req, app: app };
  app.response = { __proto__: res, app: app };
  app.init();
  return app;
}

It's the same way that koa.js handles it too.

@chochos
Copy link

chochos commented Feb 12, 2015

OK there were a couple of issues with some of the core functions when dealing with a native function with additional stuff; I've just fixed that. And now I've just started a little express server with this:

dynamic Response {
  shared formal void send(String text);
}

dynamic ExpressApp {
  shared formal void listen(Integer port, Anything() callback=()=>null);
  shared formal void get(String url, Anything(Anything,Response) callback);
}

shared void run() {
  ExpressApp app;
  dynamic {
    app=require("express")();
  }
  print(app);
  app.get("/", (req,resp) {
    print("Responding...");
    return resp.send("YEAH!");
  });
  app.listen(3000,
    ()=>print("OK, listening on port 3000"));
}

@MadcapJake
Copy link
Author

Excellent! I'll pull ceylon-js later this afternoon then and give it a go!

@chochos
Copy link

chochos commented Feb 12, 2015

Don't forget to pull ceylon.language as well, since the latest fixes were in native JS code.

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