Plugins
Plugins allow developers to share pre-built functionality, that can be used in any of your Projects. Or simply to just extend your Coronium 2 system.
How To Make One
A plugin is simply a regular Lua module. A plugin has access to the cloud
and lower-level ngx
namespaces. You can include additional 3rd party modules, by using the libs
folder (see below).
A plugin!
--/plugins/devspace/plugin.lua local plugin = {} function plugin.doSomething( arg ) return 'Better not '..arg..' with me!' end return plugin
Done.
Where They Live
Plugins reside in the /home/cloud/plugins
directory. Unless you don't plan on sharing your Plugin(s), you should place them in a "developer" namespace, like so:
/plugins /develephant eightball.lua
Plugins have full access to the cloud
namespace.
The libs
Folder
Inside the plugins folder is a directory called libs
. Inside this directory, you can place any 3rd party libraries that you are using with your plugins.
/plugins /libs time.lua
You can require these libs in your plugins like so:
--/plugins/develephant/eightball.lua local time = require('time') local m = {} function m.getTime() return time.now() end return m
Using Plugins
You can use any plugins in your project api, like so:
--/projects/super/api.lua local api = cloud.api() --Use the developer namespace for the plugin. local eightball = require('develephant.eightball') function api.get.hello( input ) local answer = eightball.shake() return "Hello" .. input.name .. '. Your answer was ' .. answer end return api
Developing Plugins
A plugin acts much like a controller
and should take in data, process it, and output it back to the original calling user api.lua
. The original calling api should handle all downstream rendering.
Plugins should be reusable across any project, and as such, should be decoupled. In other words, the plugin should know nothing about the api calling it, nor should it store project specific data internally.
REMEMBER: A plugin should never send data downstream on its own. Always pass the data back to the calling api using a return
statement.
Scope
One important piece to building plugins is understanding their scope within a users api.lua
file. Once a plugin has been require
'd into a users api.lua
, the scope of the plugin is the same scope as the api.lua file.
An example to illustrate:
--/projects/demo/api.lua local api = cloud.api() local myplugin = require('namespace.plugin') function api.get.confirm( input ) local res, err = myplugin.doSomething() if not res then return cloud.error( err ) end return res, cloud.HTML end return api
The plugin...
--/plugins/namespace/plugin.lua local _m = {} function _m.doSomething( input ) -- We are in the api.lua "scope" now, we can path tpl directly. -- In this example we are loading /projects/demo/tpl/index.tpl -- as the project is "demo" (see api.lua above). local str, err = cloud.template.render('index.tpl', input) --check our output, and return properly (res, err) if not str then return nil, 'could not render' end return str, nil end return _m
Again, we are not returning data downstream, just back to the calling api.lua file.
Returns and Errors
Every method in Coronium should follow a specific return
pattern. This should be counted on by any developer using your plugin. Do not waiver from this pattern.
It's very simple. Every method must return a result
, or an error
. These are always returned as two values, for example:
-- Example #1 -- Successful result return res, nil -- Example #2 -- Unsuccessful result return nil, 'some type of error message'
So, the result
(if any) is always the first return value, and the error
(if any) is the second value.
At no time should both the result
and error
be populated. One must contain a nil
value, based on the process outcome.
Consuming Data
If your plugin needs access to incoming data, make sure to include this in your method signature. At no time should a plugin directly access any incoming request data.
For example:
--/plugins/namespace/plugin.lua local _m = {} function _m.doSomething( input ) local email = input.email return 'your email is ' .. email, nil --< res, err end return _m
And in api.lua
--/projects/demo/api.lua local api = cloud.api() local myplugin = require('namespace.plugin') function api.post.confirm( input ) -- Be lazy. Pass it all. local res, err = myplugin.doSomething( input ) if not res then return cloud.error( err ) end return res end return api
More Tips
Don't try to be fancy in your plugins. Simply process your data and pass it back to the api.lua
to handle. In other words, don't try to encode, rename, or manipulate the downstream message packet.
You can return any valid Lua type from your plugins.
All content output flags should be handled in the calling api.lua
.