Adding extensibility to atom-shell apps


#1

I am developing an app using atom-shell, and I’d like to add atom-like extensibility using node.js packages… How am I supposed to provide such a feature? Is there a feature in Node that allows dynamic loading of non in-app packages? I’m trying to look at Atom’s source but the fact that it’s not very well documented together with my sub-optimal knowledge of CoffeeScript makes it a harder task than it seemed…

For instance, I’d like to load a package and execute it, and in the package I’d like to use, for example, require('myapp') to load APIs and such.


Extending a base class
#2

I read a bit of Atom’s source code in the meantime, and I got some of the details, but I still don’t grasp all of it completely. Basically, before Atom starts loading packages, it caches exports/atom.coffee, so that the file is already loaded when other packages require it. It then proceeds to load all the packages simply by requireing folders. What I don’t understand is how can the packages do require 'atom'. Imagine in my app I have these files:
myapp.js:

module.exports.myval = "Hello, World!"

main.coffee:

# ...do initializing stuff...
require './myapp.js' # I cache the exported globals file like Atom does
packageName = "mypack"
pack = require './' + packageName

Then in a folder mypack:
package.json

{
  "name": "mypack",
  "version": "0.1.0",
  "main": "./main.js"
}

main.js:

myapp = require('myapp');
alert(myapp.myval);

By executing this code I expected to see a happy alert greeting the world, instead a get a sad error telling me that no such module ‘myapp’ has been found… How can I specify to require where to search for modules? Can any of the devs give some insights?


#3

You should be able to do that by adding the directory path of where your myapp module resides in the require.paths array.

If you want to know more about node modules loading this post is quite clear and concise:


#4

As of now, node throws an error when accessing require.paths:

Error: require.paths is removed. Use node_modules folders, or the NODE_PATH environment variable instead.

Also, you article clearly states that modifying require.paths is a bad idea… Moreover, I found no trace of require.paths in the package.coffee and package-manager,coffee files in Atom’s source code. Maybe it is a deprecated property?


#5

Sorry, I should have tried that myself before posting.

I’m not sure to see a solution right now.


#6

No problem! :smiley: I investigated some more and found that Atom does a bit of hacking with Node’s own module module (@src/module-cache.coffee). Man, is that meta! I’m in dire need of help, still, because I really have no idea what’s going on there :frowning: May I ask support from @kevinsawicki or @zcbenz? (Sorry guys for bothering you, but I only found you as the contributors for that file :wink:)


#7

It looks like doing

Module = require 'module'
Module.globalPaths.push 'your-globals-here'

does the trick!


#8

Thank you for sharing what you have learned here. Did you figure out what atom is exporting in:
atom.coffee
exportsPath = path.join(resourcePath, ‘exports’)
require(‘module’).globalPaths.push(exportsPath)

I’m looking at the node js modules api and there is no globalPaths. Have you seen any docu on that?


#9

To be honest, I learnt most of that using electron’s inspector and JavaScript console, so that I could enumerate the members. Also, all of this should be considered a hackish solution, you won’t find much support for it.

PS: Look into atom’s exports directory to see how you can export globals into your plugins.


#10

Hey everyone,
I really want to create an app with that feature too, i’ve been trying to guide me by atom’s source but i had some problems, so at the moment i’m reviewing another editor with that feature too.

I’ll be posting my progress


#11

Cool. let us know what you are able to find out.


#12

Do you know how Atom is able to require Node’s module? I encounter an error when I do the line below.

require('module')

I saw that there is a (@src/module-cache.coffee) but that file also requires module at the 1st line so it is getting ‘module’ from somewhere.


#13

What exactly is the error? You should be able yo use node modules right away, actually. I used the snippet above as it is in my app.


#14

When I use it in my js file and run webpack hot reload it says "Cannot resolve module ‘module’ "

Weird thing is I can access that code when I put it in my webpack.config.js. I have not used electron yet so I am running this in a browser. Will that cause this error?


#15

Definitely. All of this is supposed to work in a node environment. Webpack (never used it, fwiw) is not required to implement all of node’s modules.


#16

Yeah. I need to put this all in electron now. Reason why I still run it via webpack is because in my electron app I provide an index.html. The index html has the code below. It loads a running site. I have not yet figured out how to run an html in electron without running a site first. I have not seen much in atom on how they run the html. I will take a look now so I do not need to run a site first that electron can use.

<script src="http://localhost:3000/dist/main.entry.js"></script>

#17

See electron’s quick start tutorial. From the guide: mainWindow.loadUrl('file://' + __dirname + '/index.html');


#18

Yeah I already looked at that but I cannot just put the html. I am transpiling es6 to 5 and I also have react jsx files which needs to be translated to js.

Looking at atom’s code it loads the html via: atom/src/browser/atom-application.coffee. When I run atom --dev I could not find any atom-application.js to debug. Did you debug the part of atom before that loads the html? If not it’s okay; I’ll try to figure this out.


#19

I have not skimmed through atom’s source, but I think it precompiles all of the files for enhanced speed of execution.