UNPKG

14.3 kBMarkdownView Raw
1# themost
2MOST Web Framework 2.0 **Codename Blueshift**
3
4The new version of [MOST Web Framework](http://github.com/kbarbounakis/most-web)
5comes with a set of new features for building modern data-driven web applications and services.
6
7## Generate a new application
8
9Install [MOST Web Framework CLI](http://github.com/kbarbounakis/most-web-cli) globally:
10
11 npm install @themost/cli -g
12
13and generate a new project by executing:
14
15 themost generate new project <project name>
16
17where [project name] is the name of the project which is going to be generated e.g.
18
19 themost generate new project test-app
20
21MOST Web Framework approaches a web application structure with a wind set of naming conventions.
22So, a classic application structure seems like:
23
24 + app
25 + assets
26 ...
27 + vendor
28 ...
29 + server
30 + controllers
31 root-controller.js
32 + config
33 + models
34 Thing.json
35 User.json
36 Group.json
37 ...
38 app.json
39 routes.json
40 + views
41 + root
42 index.html.ejs
43 + shared
44 master.html.ejs
45
46
47Navigate to new project directory and start application by executing:
48
49 npm run serve
50
51## Use Controllers
52
53Controllers are classes which handle requests and are stored in server/controllers
54directory.
55
56
57 //# server/controllers/hello-controller.js
58
59 import HttpBaseController from '@themost/web/controllers/base';
60 import {httpController,httpGet, httpAction} from '@themost/web/decorators';
61
62 @httpController()
63 export default class RootController extends HttpBaseController {
64
65 constructor(context) {
66 super(context);
67 }
68
69 /**
70 * GET /hello.html
71 * @returns {Promise<any>}
72 */
73 @httpGet()
74 @httpAction('hello')
75 hello() {
76 return Promise.resolve({
77 "message": "Hello World!"
78 });
79 }
80
81 }
82
83Generate a new controller by executing the following command:
84
85 themost generate controller <controller name>
86
87e.g.
88
89 themost generate controller Test
90
91This command will generate a new controller in server/controllers/test-controller.js.
92The new module exports a default class named TestController. TestController class extends HttpBaseController class which
93is one of the available controller classes of @themost.
94The framework uses the above naming convention (test-controller) to identify an HTTP controller available to handle requests.
95
96@themost uses EcmaScript decorators for defining HTTP controllers actions and methods.
97An HTTP controller class has @httpController() decorator to let framework identify it as
98a valid HTTP controller.
99
100
101 @httpController()
102 export default class RootController extends HttpBaseController
103 ...
104
105An instance method of an HTTP controller may be marked as an HTTP action by defining one or more of the
106available decorators for HTTP actions.
107
108 @httpGet()
109 @httpAction('hello')
110 hello() {
111 return Promise.resolve({
112 "message": "Hello World!"
113 });
114 }
115
116These decorators are:
117
118- @httpGet() to handle GET requests
119- @httpPost() to handle POST requests
120- @httpPut() to handle PUT requests
121- @httpDelete() to handle DELETE requests
122- @httpPatch() to handle PATCH requests
123- @httpHead() to handle HEAD requests
124
125@httpAction() decorator is used to define an HTTP action name
126
127 @httpGet()
128 @httpAction('hello')
129 hello() {
130 ...
131 }
132
133#### HTTP results
134
135The result of an HTTP action may be an instance of HttpResult class or any other class which derives from HttpResult class.
136
137
138###### HttpController#json(any)
139
140Returns a application/json result
141
142 @httpGet()
143 @httpAction('hello')
144 hello() {
145 return this.json({
146 "message": "Hello World!"
147 });
148 }
149
150###### HttpController#xml(any)
151
152Returns an application/xml result
153
154 @httpGet()
155 @httpAction('hello')
156 hello() {
157 return this.xml({
158 "message": "Hello World!"
159 });
160 }
161
162###### HttpController#content(string)
163
164Returns a text/html content result
165
166 @httpGet()
167 @httpAction('hello')
168 hello() {
169 return this.view(`
170 <h2>Hello World!</h2>
171 `);
172 }
173
174###### HttpController#view(any)
175
176Returns a text/html result
177
178 @httpGet()
179 @httpAction('hello')
180 hello() {
181 return this.view({
182 "message": "Hello World!"
183 });
184 }
185
186###### HttpController#file(physicalPath, fileName)
187
188Returns a content result based on the mime type of the physical file
189
190 @httpGet()
191 @httpAction('hello')
192 hello() {
193 return this.file(path.resolve(process.cwd(),'./app/assets/hello.pdf'));
194 }
195
196###### HttpController#redirect(url)
197
198Redirects the current HTTP request
199
200 @httpGet()
201 @httpAction('hello')
202 hello() {
203 return this.redirect('/login.html');
204 }
205
206@themost uses a set of view engines for rendering content:
207
208**EJS View Engine**
209
210based on [Embedded JavaScript templates](https://github.com/mde/ejs)
211
212 <div class="container">
213 <div class="row">
214 <div class="col-lg-12 text-center">
215 <h2 class="mt-5"><%=model.message%></h2>
216 </div>
217 </div>
218 </div>
219
220**Vash View Engine**
221
222based on [Vash, Razor syntax, for JavaScript templates](https://github.com/kirbysayshi/vash)
223
224 <html lang="en">
225 <head><title>MOST Web Framework</title></head>
226 <body>
227 <h2>@model.message</h2>
228 </body>
229 </html>
230
231**Jade View Engine**
232
233based on [Pug – robust, elegant, feature rich template engine for Node.js](https://github.com/pugjs/pug)
234
235 doctype html
236 html(lang="en")
237 head
238 title MOST Web Framework
239 body
240 h2= model.message
241
242**AngularJS for Server**
243
244@themost presents an new template engine based on the popular [AngularJS 1.x framework](https://github.com/angular/angular.js)
245This template is running in paraller with other templates engines and allows the use of AngularJS in server-side rendering.
246
247The following example contains an AngularJS server module and a simple directive which includes a hello message in an element:
248
249 //# server/modules/server-app.js
250 /**
251 * Initializes angular server application
252 * @param angular
253 */
254 export function bootstrap(angular) {
255 let serverExtensions = angular.module('server-extensions',[]);
256 serverExtensions
257 .directive('serverHello', function() {
258 return {
259 restrict: 'A',
260 scope: {
261 serverHello: '='
262 },
263 link: function (scope, element) {
264 element.html(scope.serverHello);
265 }
266 };
267 });
268 return angular.module('server',['server-extensions']);
269 }
270
271
272Include the following html markup:
273
274 <p server-hello="'This is a hello message from server application'"></p>
275
276e.g.
277
278 <div class="container">
279 <div class="row">
280 <div class="col-lg-12 text-center">
281 <h2 class="mt-5"><%=model.message%></h2>
282 <p server-hello="'This is a hello message from server application'"></p>
283 </div>
284 </div>
285 </div>
286
287and start using AngularJS directives in any server-side view.
288
289The result of an HTTP action may be also a Promise of any object (including an instance of HttpResult class).
290
291 @httpGet()
292 @httpAction('hello')
293 hello() {
294 return Promise.resolve({
295 "message": "Hello World!"
296 });
297 }
298
299or
300
301 @httpGet()
302 @httpAction('hello')
303 hello() {
304 return new Promise((resolve, reject) => {
305 //...
306 return resolve({
307 "message": "Hello World!"
308 });
309 });
310 }
311
312## Use routing
313
314MOST Web Framework holds application routings in server/config/routes.json file.
315
316 [
317 {
318 "url": "/?",
319 "controller": "root",
320 "action": "index"
321 },
322 {
323 "url": "/:action.html",
324 "controller": "root",
325 "format": "html"
326 },
327 {
328 "url": "/:action.json",
329 "controller": "root",
330 "format": "json"
331 },
332 {
333 "url": "/:action.xml",
334 "controller": "root",
335 "format": "xml"
336 },
337 {
338 "url": "/{controller:plural}/?",
339 "action": "index"
340 },
341 {
342 "url": "/{controller:plural}/:action.html",
343 "format": "html"
344 },
345 {
346 "url": "/{controller:plural}/:action.json",
347 "format": "json"
348 },
349 {
350 "url": "/{controller:plural}/:action.xml",
351 "format": "xml"
352 }
353 ]
354
355An application route may have a set of parameters that are defined with a colon followed by parameter name e.g. /test/:id/edit.html
356
357 {
358 "url": "/:action.html",
359 "controller": "root",
360 "format": "html"
361 }
362
363The example above defines an application route for each action of RootController.
364The static parameter [controller] defines the controller which is going to serve the action. The [action] parameter defines the target action.
365The [format] parameter defines the content-type of the action result.
366
367Any application route may have typed route parameters.
368
369 /users/{id:int}/edit.json
370
371This route defines a parameter named [id] which it must be an integer. Any other value will be ignored. Typed route parameters are:
372
373Format | Type |
374--- | --- |
375{param:int} | Defines an integer parameter (e.g. /users/12450/edit.json )
376{param:boolean} | Defines a boolean parameter
377{param:float} | Defines a float parameter
378{param:guid} | Defines a GUID parameter e.g. /users/2812EAEE-29C5-4810-AD9C-E6A50E97DE40/edit.json is served based on the following route: /users/{id:guid}/edit.json
379{param:plural} | Defines a string parameter that is used with its plural. This typed parameter is used for controller names e.g. /users/100/edit.html is served based on /{controller:plural}/{id:int}/edit.html where finally controller parameter is "user".
380{param:date} | Defines a DateTime parameter wrapped in single quotes e.g. /orders/calculate('2018-02-01') is served based on the following route: /orders/calculate\\({targetDate:date}\\)
381{param:string} | Defines a string parameter wrapped in single quotes e.g. /users('admin@example.com')/edit.json is served based on the following route: /users\\({email:date}\\)/edit.json
382
383Route parameters may be passed as action arguments.
384
385 import HttpBaseController from '@themost/web/controllers/base';
386 import {httpController,httpGet, httpAction} from '@themost/web/decorators';
387
388 @httpController()
389 export default class TestController extends HttpBaseController {
390
391 constructor(context) {
392 super(context);
393 }
394
395 ...
396
397 @httpGet()
398 @httpAction('multiply')
399 multiply(a, b) {
400 return Promise.resolve({
401 result: a * b
402 });
403 }
404
405 ...
406
407 }
408
409The TestController.multiply(a,b) has two float arguments. A route for this action may be:
410
411 {
412 "url": "/test/multiply\\({a:float},{b:float}\\)",
413 "controller": "test",
414 "action": "multiply",
415 "format": "json"
416 }
417
418An HTTP request on /test/multiply(4.5,5.5) will produce the following response:
419
420 {
421 "result": 24.75
422 }
423
424Any other request (like /test/multiply(x,5.5)) will fail with 404 Not Found HTTP result
425
426An HTTP controller action may validate any parameter with @httpParam decorator.
427This powerfull decorator allows a final parameter validation before the execution of an HTTP action.
428
429
430 import HttpBaseController from '@themost/web/controllers/base';
431 import {httpController,httpGet, httpAction} from '@themost/web/decorators';
432
433 @httpController()
434 export default class TestController extends HttpBaseController {
435
436 constructor(context) {
437 super(context);
438 }
439
440 ...
441
442 @httpGet()
443 @httpParam({ name: "b", type:"NonNegativeNumber" })
444 @httpParam({ name: "a", type:"NonNegativeNumber" })
445 @httpAction('multiply')
446 multiply(a, b) {
447 return Promise.resolve({
448 result: a * b
449 });
450 }
451
452 ...
453
454 }
455
456In this case any HTTP request where a or b parameter is a negative number (e.g. /test/multiply(-2.5,5.5)) will fail with 400 Bad Request HTTP error.
457
458Note: @httpParam() decorators must be placed in reverse order.
459
460An @httpParam decorator may have the following attributes
461
462Attribute | Description
463--- | ---
464name | Defines the argument name
465type | Defines the argument type based on application defined types (e.g. Integer, NonNegativeInteger, PositiveInteger, Email, Date, DateTime, Number etc.)
466required | Indicates whether this parameter is required or not even if this is not described in application route
467minLength | Defines the minimum length of a parameter
468maxLength | Defines the maximum length of a parameter
469minValue | Defines the minimum value for the given parameter
470maxValue | Defines the maximum value for the given parameter
471message | Defines a validation message for this parameter
472pattern | Defines a regular expression for the given parameter
473
474
475## Use static content
476
477A @themost web application may serve static files. HttpApplication#useStaticContent(contentPath) enables the serving of static files of the specified directory.
478
479 //# server/server.js
480 import {HttpApplication} from '@themost/web/app';
481 import path from 'path';
482 import {TraceUtils} from '@themost/common/utils';
483 import {AngularServerModule} from "@themost/web/angular/module";
484 import {LocalizationStrategy, I18nLocalizationStrategy} from "@themost/web/localization";
485 //initialize app
486 let app = new HttpApplication(path.resolve(__dirname));
487 ...
488 //use static content
489 app.useStaticContent(path.resolve('./app'));
490 ...
491
492