Home » Nodejs » Modular programming and node

Modular programming and node

Posted by: admin November 30, 2017 Leave a comment

Questions:

UPDATE 1: I made a lot of progress on this one. I pretty much gave up (at least for now, but maybe long term) on the idea of allowing user-uploaded modules. However, I am developing a structure so that several modules can be defined and loaded. A module will be initialised, set its own routes, and have a ‘public” directory for Javascript to be served. The more I see it, the more I realise that I can (should) also move the calls that are now system-wide in a module called “system”.

UPDATE 2: I have made HUGE progress on this. I am about to commit tons of code on GitHub which will allow people to do really, really good modular programming (with modules exposing both client and server side code) using Node and Express. Please stay tuned.

UPDATE 3: I rewrote this thing as a system to register modules and enable them to communicate via a event/hooks system. It’s coming along extremely nicely. I have tons of code already good to go — I am just porting it to the new system. Feel free to have a look at the project on GitHub: https://github.com/mercmobily/hotplate )

UPDATE 4: This is good. It turns out that my idea about a module being client AND server is really working.

UPDATE 5: The module is getting closer to something usable. I implemented a new loader which will take into account what an init() function will invokeAll() — and will make sure that modules providing that hook will be loaded first. This opens up hotplate to a whole new level.

UPDATE 6: Hotplate is now close to 12000 lines of code. By the time it’s finished, sometime in February, I imagine it will be close to 20000 lines of code. It does a lot of stuff, and it all started here on StackOverflow! I need it to develop my own SaaS, so I really need to get it finished by February (so that I can sprint to July and finish the first version of BookingDojo). Thanks everybody!

I am writing something that will probably turn into a pretty big piece of software. The short story is that it’s nodejs + Express + Mongodb/Mongoose + Dojo (client side).

NOTE: Questions in this text are marked as [Q1], [Q2], etc.

Coming from a Drupal background (and knowing how coooomplex it has evolved, something I would like to avoid), I am a bit of a module freak. At the moment, I’ve done the application’s boilerplate (hotplate: https://github.com/mercmobily/hotplate ). It does all of the boring stuff (users, workspaces, password reminder, etc.) and it’s missing quite a few pieces.

I would like to come up with a design that will allow modules in a similar fashion as Drupal (but possibly better). That is:

  • Modules can define new routes, and handle them
  • Modules are installed system-wide, and then each workspace can enable a set list of them

The initial architecture could be something along those lines:

  • A “modules” directory, where there is one directory per module
  • Each module has a directory for “public” files for the Javascript side of things
  • Each module would have public/startup.js which would be included in the app’s javascript
  • Each module would have server/node.js which would be included on the fly by the server if/when needed
  • There would be one route defined, something like /app/:workspaceid/modules/MODULE_NAME/.* with a middleware that checks if that workspace has MODULE_NAME enabled — and if it does, calls a module’s function with the passed parameter
[Q1]: Does this some vaguely sane?

Issues:

  • I want to make this dynamic. I would like modules to be required when needed on the spot. This should be easy enough to do, by requiring things on the fly.

  • server/node.js would have a function called, but that function feels/looks an awful lot like a router itself

[Q2] Do you have any specific hints about this one?

These don’t seem to be too much of a concern. However, the real question comes when you talk about security.

  • Privacy. This is a nasty one. At the moment, all the calls will make the right queries to mongoDb filtering by workspaceId. I would like to enforce some way so that there is no clear access to the database by the modules, so that each module doesn’t have access to data that belongs to other workspaces

  • User-defined modules. I would love to give users the ability to upload their own modules (and maybe make them available to other users). But, this effectively means allowing people to upload code that will be executed by node itself! How would you go about this?

[Q3] How would you go about these privacy/security issues? Is there any way for example to run the user-uploaded code in a sort of node sandbox? What about access to file system etc.?

Thanks!

Answers:

In the end, I answered this myself — the hard way.
The answer: hotplate, https://github.com/mercmobily/hotplate

It does most of what I describe above. More importantly, with hotPlate (using hotPage and hotClientPages, available by default), you can write a module which

  1. Defines some routes
  2. Defines a “public” directory with the UI
  3. Defines specific CSS and JS files that must be loaded when loading that module
  4. Is able to add route-specific JSes if needed

Status:
I am accepting this answer as I am finished developing Hotplate’s “core”, which was the point of this answer. I still need to “do” things (for example, once I’ve written docs, I will make sure “hotplate” is the only directory in the module, without having an example server there). However, the foundation is there. In terms of “core”, it’s only really missing the “auth” side of the story (which will require a lot of thinking, since I want to make it so that it’s db agnostic AND interfacing with passport). The Dojo widgets are a great bonus, although this framework can be used with anything (and in fact backbone-specific code would be sweeeeet).

What hotplate DOESN’T do:

What hotplate DOESn’T do, is give users the ability to upload modules which will then be loaded in the application. This is extremely tricky. The client side wouldn’t be so bad (the user could define Javascript to upload, and there could be a module to do that, no worries). The server side, however, is tricky at best. There are just too many things that can go wrong (the client might upload a blocking piece of code, or they could start reading the file system, they would have access to the full database, and so on).
The solution to these issues are possible, but none of them are easy (you can cage the user’s node environment and get it to run on a different port, for example, and so on) but some problems will stay. But, there is always hope.