nikhilk / scriptsharp

Script# Project - a C# to JavaScript compiler, to power your HTML5 and Node.js web development.
http://scriptsharp.com
Other
660 stars 182 forks source link

Node.js modules #260

Closed fshost closed 12 years ago

fshost commented 12 years ago

I'm very enthusiastic to see support being added for Node.js. It would be great if there were references for Connect, Express, Jade, EJS, and Socket.IO. Being that this is a Windows environment tool, support for IISNode module might also be expedient.

It would also be very good to have some sort of way to handle 3rd party modules in general in a generic sort of way (or perhaps there is already?) Or if there were some documentation on how to go about it, I'd be willing to contribute in writing support for existing modules and perhaps others would also.

Anyhow thanks for your work in adding this support and making it available to the community.

nikhilk commented 12 years ago

Some comments -

theoutlander commented 12 years ago

I'm not sure where to ask about these questions (SO vs. bug vs. somewhere else)? I'm creating some SS modules to be used in NodeJS. First one is a SS import module for the Node-Neo4J REST connector. I'm facing two problems:

While I'm developing, I'd like to be able to test my driver in NodeJs. The ScriptDependency attribute doesn't allow me to specify a path. Instead of require('GraphDatabase'), I'd like require('./GraphDatabase'). The former tries to load the module from NodeJS installed modules, which I don't won't to while I'm testing. Is the latter possible? It would be nice if I could do something like [ScriptDependency("GraphDatabase", Path="./")]. I also tried [assembly: ScriptReference("GraphDatabase", Path = "./")], but that didn't work. I'm not sure if I used it correctly.

Secondly, NodeJS requires that I export my classes through the export module. Instead of $exports = ss.module('My.API', null, {...}); return $exports;, I'd like to specify: exports.API = ss.module('My.API', null, {...}); Is that possible?

nikhilk commented 12 years ago

ScriptReference is your friend.

[assembly:ScriptReference("GraphDatabase", Path = "./GraphDatabase")]

You can also see this covered in the test cases (https://github.com/nikhilk/scriptsharp/blob/cc/tests/TestCases/Basic/Dependencies/Code4.cs).

That said, I don't see why your test scenarios can't follow the general node.js pattern of dependencies in the node_modules directory. Anyway, you can specify the path if you don't like the convention.

Exporting... ScriptTemplate will do the job. See AssemblyInfo.cs in your project. You can change it to what you like. The default node.js module project template has a line in the script template that does this:

ss.extend(exports, call_function_that_returns_$exports);

However, note that the most recent build has some changes, so as to enable you to get pretty much the node.js module pattern, i.e. using the CommonJS pattern. The generated script will no longer be encapsulated in a function. It generates the following:

var $exports = ss.module(...);

And the default script template now contains:

ss.extend(exports, $exports);

You can change the script template as much as you'd like to get exactly the output you're after. That is what it is for.

Hopefully you'll create the import assemblies for node modules in a way that can be shared with the community.

theoutlander commented 12 years ago

The reason I'm not following the general NodeJS pattern is because I'm not sure how to create NPM packages yet. I'm going to look into that once my library is complete. Perhaps have SS project create it.

After I reference the module specified in ss.module(...), I cannot see any classes that are part of it.

However, when I change it to exports.API = ss.module(...); I can do something like this:

var module = require('./ModuleName') var graph = new module.API.GraphDatabase()

How I can do the same with the current exports syntax that's in the template?

nikhilk commented 12 years ago

Get the latest download from yesterday first. Use either the node app or node module template. For your Neo4J module, you'll want to build an import library, so use that as the template to get started. That will be the easiest way to get this going.

I think the default setup should work for you.

The types in your module will get defined via a call to ss.module, which will return a module object. The script template will extend the exports object with those types so they're accessible to anyone who requires your module. You shouldn't have to change how APIs are exported.

So for example, if you defined a type such as GraphStore in a module named GraphDatabase, the resulting module can be used in manually written node code as such:

var graphDB = require('GraphDatabase');
var db = new graphDB.GraphStore();

You don't have to get into npm or building node packages to get started.

In fact if you build a node module and then a node app referencing that node module, the script# compiler will do everything to place things in the right place so you can simply start your app by running (assuming your app was call App)

node App.js
theoutlander commented 12 years ago

Thanks. I was struggling because the code I download from "yesterday as mentioned in your earlier message" was from right before your checkin with the fix. After I built and installed the latest verson of SS, I failed to update the packages folder in my existing project. Applying the fix correctly along with creating a NodeApplication to consume the NodeModule worked!

I've found a couple of minor issues that I'll open separate bugs on.

As for the SS library for Neo4J, should I create a separate project or add it to the SS Libraries\Node and send a pull request? Thanks!

nikhilk commented 12 years ago

We should add under Libraries\Node, but it would be good to model it similar to other libraries. I'll hopefully be committing the Express one soon, so hopefully it will match that.

Specifically, there are a few deltas between how project files are setup within the script# repository compared to what the import library template gives you when you're only using script#.

theoutlander commented 11 years ago

Do you know when ExpressJS will be committed? We want to expose a REST API and figured we'd use Express since it'll be available in S# in the near future instead of RestifyJS.

Also, when you're done I can look at how it's done and send a pull request for the Node-Neo4J library.

nikhilk commented 11 years ago

Just did - see 5e3f715a685f460515bbe23874faa4045a6b965d - it is (along with the core nodejs apis) a work in progress. So if you find things wrong or missing and needed, let me know.

Restify would actually be interesting as well. I imagine if you're primarily creating an API, it might be more appropriate than ExpressJS.

theoutlander commented 11 years ago

FYI, I'm porting Restify.

nikhilk commented 11 years ago

Sounds great. I suspect there will be some similarities with express, given the nature of things, so it should hopefully be an interesting reference.

theoutlander commented 11 years ago

Sorry, it's taken me a bit long. I've been very busy with multiple projects. I've ported several things that I need to do a second pass through and ensure that they follow the coding guidelines and that functionality is fairly accurate before I send pull requests.

So far I have the following libraries that I'm using in my projects:

  1. Restify
  2. Simile Timeline
  3. Highcharts (possibly might end up doing Stockcharts as well at some point)
  4. A a couple of micro JS (http://microjs.com) libraries and JSBeautify, but I'm not sure how to introduce them.

Since these libraries are working fine for basic scenarios, it would be easier if they made it into the repo and we continued to fill pending stubs or fix bugs. Issues can only be found by using the libraries in real projects. I'm not sure how you feel about that.

nikhilk commented 11 years ago

I think Restify is most interesting from that list... from a general applicability perspective, and hence make sense out-of-the-box.

Which microframework are you specifically alluding to above?

theoutlander commented 11 years ago

Sent a pull request for Restify. In microframeworks, I'm using Accounting.js. And BeautifyJS which is not part of MicroJS.com.

I'll create another repo for all the other libraries that I've ported over as they're current and super useful for creating charts, timelines and other random/micro stuff. As long as I have Nuget packages, they should still be discoverable. If you'd still like them here, let me know otherwise I'll create the branch in the next week.