How To Write A Plugin
Use
svrx-create-plugin
to help you create plugins more easily
First Plugin
Let's create our first plugin —— svrx-plugin-hello-world
File Structure
Only
package.json
andindex.js
are required
package.json
Only two fields are required by package.json
name
: package name must be a string beginning withsvrx-plugin
, to helpsvrx
find it in npm.engines.svrx
: Define the runnable svrx version of this plugin,svrx will automatically load the latest matching plugin engines.svrx can be a valid semver,like0.1.x
or~0.1
- index.js
index.js
Where
configSchema
Plugin param definition based on JSON Schema ,checkout JSON Schema for more detail. Here we just set auser
field, it is a stringassets
: client resource setting,they will be automatically injected into the pagestyle
: css resource injectionscript
: script resource injectionAll resources will be merged into a single file.
hook.onCreate
: a function invoke when plugin been creating, we can control it by injected service in this example, we only use two serviceslogger
: logger serviceconfig
: config service
Check out setion service to find out other services that available in hook.onCreate
- client.js
client.js
There is a global variable named svrx
will be injected into all pages, it has some built-in services
svrx
is only accessible inside the plugin script, don't worry about global pollution
You will see Hello svrx from browser
in console panel
Unlike in server side, config in client is passed through websocket, so api is async, and return a promise
svrx also provide other client services, please check out client api for help
publish && running
There'll be a failure when trying to publish it by npm publish
. Because svrx-plugin-hello-world
has been published by official team
So we skip this step and try the plugin directly
Check the terminal and browser console log, we will find Hello svrx from browser
, which means plugin has worked successfully.
You can also run it in programmatical way
Further reading: How to test plugin?
Server Side Service
You can use service in two places
hooks.onCreate
plugin
event
We will explain these 7 services in turn
middleware
Middleware is used for adding koa-style middleware to implement backend logic injection
- middleware.add(name, definition)
middleware.add(name, definition)
Adding koa-style middleware
Usage
Param
name
[String]: A unique middleware namein debug mode, it can be used to track the middleware call process
definition.priority
[Number]: default is10
. Svrx will assemble the middleware according to the priority from high to low, that is, the request will be passed to the high priority plugin first.definition.onRoute
[Function]: A koa-style middleware .Ifdefinition
is a function, it will automatically becomedefinition.onRoute
- middleware.del(name)
middleware.del(name)
Delete a middleware with the specified name
Usage
Param
name
: middleware name
injector
injector
is used for rewriting the response and inject client resources.
- injector.add(type, resource)
injector.add(type, resource)
Add a resource for injection , only js and css has been supported.
The rule as follow.
The style will be merged into
/svrx/svrx-client.css
and injected before the closinghead
tagThe script will be merged into
/svrx/svrx-client.js
and injected before the closingbody
tag
Usage
The content
will be merged into bundle script
Param
type
: Only supportscript
andstyle
resource.content
[String]: resource contentresource.filename
[String]: the path of resource file, must be a absolute path
Content has a higher priority than filename, so you can take one of them.
- injector.replace(pattern, replacement)
injector.replace(pattern, replacement)
injector.replace
will transform response body with some or all matches of a pattern replaced by a replacement.
Usage
The above example replace all svrx
with server-x
Param
pattern
[String|RegExp]replacement
[String|Function]
The usage of
injector.replace
is exactly the same asString.prototype.replace
resource injection is based upon
injector.replace
events
Built-in event listener, support async&sorted emitter, , which can call the listen function in turn, and can terminate the event delivery at any time.
- events.on(type, fn)
events.on(type, fn)
Usage
Param
type
[String]: event namefn(payload, ctrl)
: callback that has two paramspayload
[String]: event data that pass throughemit
ctrl
[Object]: control object, callctrl.stop()
to stop 'sorted emit'
If the callback returns a
Promise
(such as async function), it will be treated as an asynchronous watcher.
- events.emit(type, param, sorted)
events.emit(type, param, sorted)
Usage
Param
type
[String]: event namepayload
: event datasorted
[Boolean]: default isfalse
, whether to pass events serially
Return
Promise
- events.off(name, handler)
events.off(name, handler)
Remove event watcher
Usage
builtin events
plugin
: triggered after plugin building.file:change
: triggered when any file changesready
: triggered when server starts, if you need to handle logic after server startup (such as getting the server port), you can register this event
config
Config service used to modify or query the options passed by user;
- config.get(path)
config.get(path)
Get the config of this plugin.
Config is based on immutable data , you must always use config.get
to ensure getting the latest config.
Usage
if you need to get global config,just add prefix $.
Param
field
: field path,deep getter must be separated by.
, such asuser.name
Return
The value of the field
- config.set(field, value)
config.set(field, value)
Modify the config
Usage
Param
field
: field path,deep setter must be separated by.
, such asuser.name
value
: field value
- config.watch(field, handler)
config.watch(field, handler)
Listening for configuration changes, change digest will be triggered after the set
, del
, splice
method calls
Param
field
: field path,deep watcher must be separated by.
, such asuser.name
handler(evt)
: watch handlerevt.affect(field)
[Function]: detect whether specific field has been changed
- config.del(field)
config.del(field)
Remove some field
Usage
- config.splice(field, start[, delCount[, items...])
config.splice(field, start[, delCount[, items...])
The Array.prototype.slice
Except for field
,params are identical to Array.prototype.splice
Example
router
Extending Routing DSL
- router.route(register)
router.route(register)
Register route,as same as Routing DSL
Usage
Param
register({...methods}):
methods: corresponding to HTTP methods
- router.action(name, builder)
router.action(name, builder)
Register an action , like proxy
or json
Usage
Param
name
[String]: action namebuilder(payload)
payload: payload that passed to action,like
'svrx'
in above exampleReturn: builder must return a koa style middleware
- router.load(filename)
router.load(filename)
Load routing file manually ,Same as options --route
Also support hot reloading
Usage
Param
filename
: absolute path for routing file
Return
Promise
logger
Logger module, who's level can be controlled by logger.level
(default is warn
)
Or cli way
Above example will output log that more than warn
, such as notify
, error
logger[level](msg)
logger[level](msg)
Svrx provides multiple levels of logging: silent
, notify
, error
, warn
(default), info
, debug
Usage
logger.log
is an alias forlogger.notify
io
io is used for the communication between server and client. Please check it out in client-side io
- io.on( type, handler )
io.on( type, handler )
Listening for client messages (send by client side io.emit
)
Param
type
: message typehandler(payload)
: handler for messagepayload
: message data
- io.emit(type, payload)
io.emit(type, payload)
Send message to client
Usage
Server side
Client side
Param
type
: message typepayload
: message data
Message payload must be serializable because they are transmitted over the network
- io.off(type[, handler])
io.off(type[, handler])
Remove the message watcher
Usage
- io.register(name, handler)
io.register(name, handler)
Register io service, which can be invoked by io.call
in client and server.
Usage
Param
name
[String]: service name used byio.call
handler
: a Function return Promise, implement service logic
- io.call(name, payload)
io.call(name, payload)
Invoke registered service
Usage
Param
name
[String]: service namepayload
[Any]: service payload will passed to service handler
Return
Promise
Client API
The client APIs are uniformly exposed through global variable svrx
io
Responsible for communicating with the server
- io.on(type, handler)
io.on(type, handler)
Listening server-side message
Usage
Server side
Client side
Note that the
io.emit()
in server-side is a broadcast and all pages will receive a message for server.
Param
type
: message typehandler(payload)
: message handlerpayload
: message payload passed byio.emit
- io.emit(type, payload)
io.emit(type, payload)
Send client message to server side
Usage
Client side
Server side
Param
type
: message typepayload
: message data passed to message handler
payload
must be serializable because it is transmitted over the network.
- io.off(type[, handler])
io.off(type[, handler])
Remove io watcher
Usage
- io.call(name, payload)
io.call(name, payload)
io.call on the client side is exactly the same as the server, but make sure the payload is serializable** because it will be transmitted over the network
Usage
Param
name
[String]: service namepayload
[Any]: service payload
Return
Promise
events
This part is exactly the same as server events, no retelling
Usage
The difference between events and io is that io is used for the communication between the server and the client, but events is a single-ended communication.
config
config
in client is almost identical to the server, the only difference is: the client version is asynchronous (because of network communication)
- config.get(field)
config.get(field)
Usage
if you need to get global config,just add prefix
$.
- config.set
、config.splice
、config.del
config.set
、config.splice
、config.del
The above three methods are the same as get
, which is consistent with the server, but the return value becomes Promise.
Usage
config schema
Svrx config schema is based on JSON Schema
Usage
Field Details
type
[String]: JSON-Schema field type ,can be anarray
,string
,number
,boolean
,object
ornull
default
[Any]: default valuerequired
[Boolean]: whether it is required, default isfalse
properties
[Object]: child fieldsui
: svrx extension ,whether show the config in svrx-uianyOf
: Choose one of the items, such asFor further understanding, please refer to Official Documentation
How to test plugin?
It is not recommended that you publish the test plugin to npm. You can do local testing in the following ways.
After specifying the path parameter, svrx loads the local package instead of installing it from npm
More easier plugin development
Use Official svrx-create-plugin
to help you create plugins more easily
Last updated
Was this helpful?