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