We recommend familiarising yourself with how the Forms CLI works before writing your own plugin.
What is a Forms CLI Plug-in?
The Forms CLI uses a plug-in to turn a JSON definition of a Blink form into source code for a specific framework. It deals only with forms and their functionality, however you could write a plug-in pack that could build an entire project.
A plug-in consists of an entry point that exposes four functions that are called at various points by the Forms CLI. The Forms CLI must explose an object of the following structure:
{ build: (cfg) => Promise, init: (cfg) => Promise, processForm: (formDefinition) => Promise, writeTemplates: (destinationPath) => Promise }
Plug-ins can define a set of templates for a front end framework (AngularJS, Vue, React etc), and then combine those templates with a form definition provided by the Forms CLI to create the "source" for your Forms in the framework of your choice.
The plug-in can optionally define a build step to build the source files into a bundled module.
Forms CLI and plugin interaction Overview
The Forms CLI works with plug-ins that are specific to certain frameworks. These plug-ins are installed into your projects folder, like gulp or babel plug-ins.
The Forms CLI is lightweight and the bulk of the work is done via the plug-ins installed into your projects folder.
processForm is called by the command bm forms create. bm forms create will handle the job of getting the definition from its source, normalizing the structure into a specific JSON structure. Then it will iterate over each form, passing the whole form definition to your processForm function. processForm needs to return an array of functions that the Forms CLI will iterate over. Normally these functions would use the template-helper functions to return a function which runs lazyWriteFile to write the source files for the framework you are building for. The AngularJS plugin makes extensive use of the template helper.
build is called from bm forms build will take the source files made by bm forms create and run the build command from the installed plugin. The AngularJS plugin uses gulp to build a distribution file and setup a simple index.html, however you may elect to leave the build function empty (by passing back Promise.resolve()) and include the building of your forms library in your app's build step.
Sample plugin for AngularJS:
'use strict' const path = require('path') const build = require('./lib/build/build.js') const processForm = require('./lib/transform/process-form.js') const templateHelper = require('@blinkmobile/forms-template-helper') const templateService = templateHelper.service const writeTemplates = templateHelper.writeTemplates module.exports = { build, init: (cfg) => templateService.load(cfg.templatePath), processForm, writeTemplates: (dest) => writeTemplates(path.join(__dirname, 'templates'), dest) }
The properties on the exports are required for your plugin to work. The two functions that relate to the template helper are init and writeTemplates.
Developing a custom plug in
Currently we only support plug-ins installed in a node_modules
folder in your projects folder. To develop a plugin we recommend making a new project folder for the plug in (that is not in the project that will be using forms components built with the Forms CLI), and then use npm link to link your plugin to a project using the forms transformer.
Plugin API
A Forms CLI plug-in must expose an object of the following structure:
{ build: (cfg) => Promise, init: (cfg) => Promise, processForm: (formDefinition) => Promise, writeTemplates: (destinationPath) => Promise }
Your plug-in is a node module. You should be familiar with setting up your package.json correctly.
ProcessForm Function
processForm(definition) => Array<() => Promise>
The Forms CLI does the job of getting a forms definition from your definition source (answerSpace or JSON files currently supported), normalizing it, then passing each form to your plug-in, collecting the results.
processForm is called by the Forms CLI and passed a single form definition in normalized JSON. Its job is to do whatever is needed to prepare the definition, and then return a function (or array of functions) that return a Promise. As such there is no rules to what you do with the definition, as frameworks vary, the job of processForm varies from framework to framework.
It is recommended to use the template-helper module, which provides functions to load templates from a folder, create "primed" mustache templates and a lazyWriter function that is used by the AngularJS plug-in as the return value of processForm.
For a full implementation example, see the AngularJS or JSON plug-ins.