UNPKG

17.3 kBMarkdownView Raw
1---
2title: Kettle Configs and Applications
3layout: default
4category: Kettle
5---
6
7The top-level structure of a Kettle application can be described by a "config" file in JSON or [JSON5](http://json5.org/) format. A Kettle "config"
8describes the configuration of a number of "Kettle apps" ([grade](http://docs.fluidproject.org/infusion/development/ComponentGrades.html) [`kettle.app`](RequestHandlersAndApps.md#kettle.app))
9hosted in a number of "Kettle servers" (grade [`kettle.server`](Servers.md)).
10The config JSON (or JSON5) file represents an Infusion [component tree](http://docs.fluidproject.org/infusion/development/HowToUseInfusionIoC.html). If you aren't familiar
11with the syntax and meaning of component trees, it is a good idea to browse the documentation, tutorials and examples at the
12Infusion [documentation site](http://docs.fluidproject.org/infusion/development/). Kettle components are currently derived from
13the base grade `fluid.component`, so you can ignore for these purposes the parts of the Infusion documentation relating to model and view components.
14
15Note that Kettle configs can represent any Infusion applications; they are not
16restricted to representing just Kettle applications. Their structure is
17freeform, other than the top level derived from `fluid.component`, and they may
18be used to encode any Infusion application as a component tree.
19
20## A simple Kettle application
21
22In this section, we will construct a simple Kettle application within JavaScript code, to produce a self-contained example. You can find and try out this
23same application represented in two forms in the [examples/simpleConfig](../examples/simpleConfig) directory.
24
25```javascript
26
27fluid.defaults("examples.simpleConfig", {
28 gradeNames: "fluid.component",
29 components: {
30 server: {
31 type: "kettle.server",
32 options: {
33 port: 8081,
34 components: {
35 app: {
36 type: "kettle.app",
37 options: {
38 requestHandlers: {
39 getHandler: {
40 "type": "examples.simpleConfig.handler",
41 "route": "/handlerPath",
42 "method": "get"
43 }
44 }
45 }
46 }
47 }
48 }
49 }
50 }
51});
52
53fluid.defaults("examples.simpleConfig.handler", {
54 gradeNames: "kettle.request.http",
55 invokers: {
56 handleRequest: "examples.simpleConfig.handleRequest"
57 }
58});
59
60examples.simpleConfig.handleRequest = function (request) {
61 request.events.onSuccess.fire({
62 message: "GET request received on path /handlerPath"
63 });
64};
65
66// Construct the server using the above config
67examples.simpleConfig();
68```
69
70The JSON "config" form of the application itself is held at [examples/simpleConfig/examples.simpleConfig.json](../examples/simpleConfig/examples.simpleConfig.json),
71which encodes the same information as in the first `fluid.defaults` call above. The definitions for request handlers such as `examples.simpleConfig.handler` and
72`examples.simpleConfig.handleRequest`, which in our sample are held in [examples/simpleConfig/simpleConfig-config-handler.js](../examples/simpleConfig/simpleConfig-config-handler.js),
73always need to be supplied in standard `.js` files required by the application – although future versions of Kettle
74may allow the defaults for the handler grade to be encoded in JSON. Consult the Infusion framework documentation on [grades](http://docs.fluidproject.org/infusion/development/ComponentGrades.html) if
75you are not familiar with this kind of configuration.
76
77You can try out these samples in [examples/simpleConfig](../examples/simpleConfig) by, for example, from that directory, typing `node simpleConfig-config-driver.js`. The last line of the driver files
78load a common module, `simpleConfig-client.js` which tests the server by firing an HTTP request to it and logging the payload – this uses one of the HTTP client drivers taken from Kettle's
79[testing](KettleTestingFramework.md) definitions. Later on, we will see how to issue formal test fixtures against this application by using the [Kettle testing framework](KettleTestingFramework.md).
80
81## Starting an application encoded by a Kettle config
82
83An application encoded as a Kettle config can be started in a variety of ways,
84both programmatically and from the command line - as well as being easily embedded
85into other applications, whether they are Infusion component trees or raw Express apps.
86
87### Starting a Kettle config programmatically
88
89Kettle includes a driver function, `kettle.config.loadConfig` which will load and run a Kettle application defined as a JSON or JSON5 file in the filesystem. It accepts an `options` structure which includes the
90following fields:
91
92|Member name| Type | Description |
93|-----------|------|-------------|
94|`configName`| `String` | The name of the config (the bare filename, minus any extension) which is to be loaded|
95|`configPath`| `String` | The directory holding the config. This path may start with a symbolic module reference, e.g. of the form `%kettle`, to a module which has been registered using Infusion's module API [`fluid.module.register`](http://docs.fluidproject.org/infusion/development/NodeAPI.html#fluid-module-register-name-basedir-modulerequire-)|
96
97`kettle.config.loadConfig` will return the (Infusion) component instance of the initialised application. You could use this, for example, to terminate the application using its ``destroy()`` method.
98
99An alternative to `kettle.config.loadConfig` is `kettle.config.createDefaults`. This accepts the same arguments but simply loads the config as a [grade](http://docs.fluidproject.org/infusion/development/ComponentGrades.html)
100rather than instantiating it as well. The return value from `kettle.config.loadConfig` is the grade name of the application. You can construct this application later by use of Infusion's [`invokeGlobalFunction`](http://docs.fluidproject.org/infusion/development/CoreAPI.html#fluid-invokeglobalfunction-functionpath-args-) API, or else
101embed it in a wider application as a subcomponent.
102
103### Starting a Kettle config from the command line
104
105Kettle includes a top-level driver file named `init.js` which will accept values from the command line and the environment variable ``NODE_ENV`` in order to determine which application config to start.
106For example, from Kettle's top-level directory you can run
107
108```
109 node init.js <configPath> [<configName>]
110````
111
112The `configPath` argument is required - its meaning is as given in the `configPath` option to `kettle.config.loadConfig` call described in the previous section.
113
114The `configName` argument is optional. If this value is not supplied at the command line, it will be read from the environment variable ``NODE_ENV``.
115The meaning is as given in the `configName` option to `kettle.config.loadConfig` described in the previous section.
116
117For example, you can start the sample app from the [previous section](#a-simple-kettle-application) by running
118```
119 node init.js examples/simpleConfig examples.simpleConfig
120```
121from the root directory of a Kettle checkout.
122
123## Referring to external data via resolvers
124
125Kettle configs may refer to external data, for example encoded in environment
126variables, files, or other sources. This is achieved via Infusion's
127[expander](http://docs.fluidproject.org/infusion/development/ExpansionOfComponentOptions.html#expanders) syntax
128within the config, together with some standard built-in global functions
129representing _resolvers_.
130
131Here is an example of a little config which accepts a `url` property from an
132environment variable named `KETTLE_ENV_TEST`, via Infusion's [compact syntax](http://docs.fluidproject.org/infusion/development/ExpansionOfComponentOptions.html#compact-format-for-expanders):
133
134```
135{
136 "type": "fluid.component",
137 "options": {
138 "url": "@expand:kettle.resolvers.env(KETTLE_ENV_TEST)",
139 }
140}
141```
142
143If you need the ability for the target configuration to retain its default
144value in the case that the resolver value is missing, you should use
145Infusion's [options distributions](http://docs.fluidproject.org/infusion/development/IoCSS.html)
146to target the resolved value rather than writing it at top level within the config.
147
148### kettle.resolvers.env
149
150`kettle.resolvers.env` is a global function which allows the resolution of
151environment variables. It accepts one argument, which is the name of the
152environment variable to be resolved. If the environment variable is not defined,
153the function returns `undefined`.
154
155### kettle.resolvers.file
156
157`kettle.resolvers.file` is a global function which allows the resolution of
158material held in text files. It accepts one argument, which is the name of the
159file to be loaded. The filename may contain <a href="http://docs.fluidproject.org/infusion/development/NodeAPI.html#node-js-module-apis">module-relative path</a> such as <code>%kettle</code> to indicate a path relative to a module registered with Infusion.
160
161The file must contain text in the UTF-8 encoding. The contents of the file will be
162loaded via node's `fs.loadFileSync` API and returned as a string.
163
164### kettle.resolvers.args
165
166`kettle.resolvers.args` is a global function which allows the resolution of
167the command-line arguments that the current node application was started with.
168It accepts zero or one arguments. If supplied no arguments, it will return the
169full value of node's `process.argv` argument array. If supplied one argument,
170it will return the value of using this to index into `process.argv`.
171
172## Structure of a Kettle application's config
173
174In the previous section, we saw a [simple example](../examples/simpleConfig/examples.simpleConfig.json) of a JSON-formatted Kettle config, which declaratively encodes a Kettle application structure.
175In this section we describe the top-level members of this structure, and in the next secion we'll look at the containment structure in terms of [grades](http://docs.fluidproject.org/infusion/development/ComponentGrades.html).
176In the rest of this document we'll describe the options accepted by the various grades which make up a Kettle application (`kettle.server`, `kettle.app`, `kettle.middleware` and `kettle.request`). The structure of our
177minimal application will serve as a general template – the full definition of a Kettle application consists of a config, ***plus*** definitions of request handler grades ***plus*** implementations of request handler functions.
178
179<table>
180 <thead>
181 <tr>
182 <th colspan="3">Top-level members of a Kettle application's "config" configuration file</th>
183 </tr>
184 <tr>
185 <th>Member</th>
186 <th>Type</th>
187 <th>Description</th>
188 </tr>
189 </thead>
190 <tbody>
191 <tr>
192 <td><code>type</code></td>
193 <td><code>String</code> (grade name)</td>
194 <td>The type name for this config. This should be a fully-qualified grade name – it is suggested that it agree with the file name of the config file without the <code>.json</code> extension.</td>
195 </tr>
196 <tr>
197 <td><code>options</code></td>
198 <td><code>Object</code> (component options)</td>
199 <td>The options for the application structure. These should start with the application's <code>gradeNames</code> which will usually just be <code>fluid.component</code>, and then continue with <code>components</code> designating the
200 next level of containment of the application, the <code>kettle.server</code> level – see the next section on <a href="#containment-structure-of-a-kettle-application">containment structure of a Kettle application</a> for the full structure</td>
201 </tr>
202 <tr>
203 <td><code>mergeConfigs</code> (optional)</td>
204 <td><code>String/Array of String</code></td>
205 <td>A filename (or array of these) of other config files which are to be included into this application. These names may begin with a <a href="http://docs.fluidproject.org/infusion/development/NodeAPI.html#node-js-module-apis">module-relative path</a>
206 such as <code>%kettle</code> or else will be interpreted as
207 paths relative to this config's location in the filesystem. The filenames may either end with a <code>.json</code> or a <code>.json5</code> extension representing configuration files in those formats, or the extension may be
208 omitted in which case both of those extensions (in the order <code>.json</code>, <code>.json5</code>) will be tried as possibilities. Each config file will be loaded and resolved as a grade and then merged with the
209 structure of this config (via an algorithm similar to <a href="https://api.jquery.com/jquery.extend/">jQuery.extend</a> – note that because of a current Infusion framework bug <a href="https://issues.fluidproject.org/browse/FLUID-5614">FLUID-5614</a>,
210 all of the semantics of nested <a href="http://docs.fluidproject.org/infusion/development/OptionsMerging.html">options merging</a> will
211 not be respected and the merging will occur in a simple-minded way below top level)</td>
212 </tr>
213 <tr>
214 <td><code>loadConfigs</code> (optional)</td>
215 <td><code>String/Array of String</code></td>
216 <td>A filename (or array of these) of other config files which will be loaded before this config is interpreted. These names may begin with a <a href="http://docs.fluidproject.org/infusion/development/NodeAPI.html#node-js-module-apis">module-relative path</a>
217 such as <code>%kettle</code> or else will be interpreted as
218 paths relative to this config's location in the filesystem. As with <code>mergeConfigs</code>, the filenames may be specified with <code>.json</code>, <code>.json5</code> or no extension. Each filename listed here will be loaded and resolved as a grade. The workflow is similar to that with <code>mergeConfigs</code>, only the grades represented in <code>loadConfigs</code>
219 will not be automatically merged with the current config as parent grades. Instead, the user is free to refer to them as required - for example as the <code>type</code> or <code>gradeNames</code> of a <a href="http://docs.fluidproject.org/infusion/development/SubcomponentDeclaration.html">subcomponent</a></td>
220 </tr>
221 <tr>
222 <td><code>require</code> (optional)</td>
223 <td><code>String/Array of String</code></td>
224 <td>A <a href="https://nodejs.org/api/modules.html">module identifier</a> (or array of these) that will be loaded when this config is loaded. These modules will be loaded as if by the standard node.js API
225 <a href="https://nodejs.org/api/modules.html"><code>require</code></a> operating from the config's directory (the <a href="https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders">global folder rules</a> will be ignored).
226 These names may begin with a <a href="http://docs.fluidproject.org/infusion/development/NodeAPI.html#node-js-module-apis">module-relative path</a> such as <code>%kettle</code> to indicate a path relative to a module registered with Infusion.</td>
227 </tr>
228 </tbody>
229</table>
230
231
232## Containment structure of a Kettle application
233
234The overall structure of a Kettle application within its config shows a 4-level pattern:
235
236* At top level, the application container – this has the simple grade `fluid.component` and does not carry any functionality – it is simply used for grouping the definitions at the next level
237 * At 2nd level, one or more Kettle servers – these have the grade [`kettle.server`](Servers.md) – in the case there is just one server it is conventionally named `server`
238 * At 3rd level, one more Kettle apps – these have the grade [`kettle.app`](RequestHandlersAndApps.md#kettle.app) – this is the level at which independently mountable segments of applications are grouped (an app is a grouping of handlers)
239 * At 4th level, one or more Kettle request handlers – these have the grade [`kettle.request`](RequestHandlersAndApps.md#kettle.request) – each of these handles one endpoint (HTTP or WebSockets) routed by URL and request method
240
241This expression is much more verbose in simple cases than the traditional raw use of express apps, but in larger and more complex applications this verbosity is amortised, with the ability to easily
242customise and reassort groups of handlers and servers from application to application.
243
244Note that the containment relationships between the top 3 levels need not be direct – servers may be nested any number of levels below the config root, and apps may be nested any number of
245levels below a server. However, request handlers must be defined as direct children of their parent apps, in the options section named `requestHandlers`.
246
247## Further reading
248
249Go on to [Kettle servers](Servers.md) to learn about the 2nd level of containment, and [Kettle request handlers and apps](RequestHandlersAndApps.md) to learn about levels 3 and 4.
250
\No newline at end of file