<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dan T.</title>
    <description>The latest articles on DEV Community by Dan T. (@dantsk).</description>
    <link>https://dev.to/dantsk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F124363%2Fec19aa5d-2dc7-4380-8041-3727fb8352a9.png</url>
      <title>DEV Community: Dan T.</title>
      <link>https://dev.to/dantsk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dantsk"/>
    <language>en</language>
    <item>
      <title>Threads without efforts in Odi (Node.js)</title>
      <dc:creator>Dan T.</dc:creator>
      <pubDate>Tue, 05 Feb 2019 15:48:31 +0000</pubDate>
      <link>https://dev.to/dantsk/threads-without-efforts-in-odi-nodejs-4hmo</link>
      <guid>https://dev.to/dantsk/threads-without-efforts-in-odi-nodejs-4hmo</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Multithreading is a process of executing two or more threads simultaneously.The most programming languages provide an API for convenient work with threads and parallelism. The developer can focus on application logic, not on the communication channel, synchronization or architecture setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node 10.5&lt;/strong&gt; added support for &lt;code&gt;worker_threads&lt;/code&gt; module with an experimental flag. But starting from &lt;strong&gt;Node 11.7&lt;/strong&gt; this feature is available out of the box. It’s a good start for multithreading paradigm in Node.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;worker_threads&lt;/code&gt; has a huge potential, so support for this module was added to Odi from early stages. As always, Odi goal is to provide convenient, clean and minimalistic API (with magic 🧙‍♂️), so developers can focus on development, not on setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;From the last article, Odi got new CLI command which initializes project,&lt;br&gt;
defines scripts and installs all required dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    odi init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Currently, there are only a few options:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nt"&gt;-j&lt;/span&gt;, &lt;span class="nt"&gt;--jsx-templating&lt;/span&gt;  add jsx templates
    &lt;span class="nt"&gt;-d&lt;/span&gt;, &lt;span class="nt"&gt;--database&lt;/span&gt;        add typeorm integration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;p&gt;By default, the project will have the following structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2ArM0JN4xIll0-ZkYHi2-9Jw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2ArM0JN4xIll0-ZkYHi2-9Jw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All required dependencies will be installed during command execution based on the template type. Also if &lt;code&gt;-j&lt;/code&gt; flag was provided, &lt;strong&gt;views&lt;/strong&gt; folder will be added in the project root directory.&lt;/p&gt;
&lt;h3&gt;
  
  
  Source Files
&lt;/h3&gt;

&lt;p&gt;There are 2 predefined source files in the basic template.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;index.ts&lt;/code&gt; file that contains basic Odi configuration. By default, the&lt;br&gt;
server port is set to &lt;code&gt;8080&lt;/code&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;And the &lt;code&gt;home.controller.ts&lt;/code&gt; file with a simple controller definition.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;That’s enough to start with Odi and development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scripts
&lt;/h3&gt;

&lt;p&gt;For now, the only &lt;code&gt;npm start&lt;/code&gt; script is available out of the box. In the next&lt;br&gt;
release, &lt;code&gt;npm test&lt;/code&gt; command will be available using Mocha and Chai.&lt;/p&gt;

&lt;p&gt;Simply run the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This script includes compilation and actual running, so after completion, you can easily open the browser and check &lt;code&gt;http://localhost:8080&lt;/code&gt; URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2Ar57qiTH3VLPszvUJit3S2g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2Ar57qiTH3VLPszvUJit3S2g.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Threads
&lt;/h2&gt;

&lt;p&gt;By design, Node is single threaded with non-blocking I/O. Such approach has many pros and cons. The main advantage is simplicity. The developer does not need to care about threads manipulations, data synchronization and etc. But any resource-intensive tasks will block the event loop.&lt;/p&gt;

&lt;p&gt;Worker threads can process resource-intensive operations, so the main thread is always available. It’s really important for Server-Side applications, as any blocking task will delay accepting and processing of new client requests.&lt;/p&gt;
&lt;h3&gt;
  
  
  Task
&lt;/h3&gt;

&lt;p&gt;Let’s create the resource-intensive (blocking) function for getting an answer&lt;br&gt;
(&lt;em&gt;Yes&lt;/em&gt; or &lt;em&gt;No&lt;/em&gt;) based on random values generation.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Mathematical operations in most cases CPU intensive, so it’s a great example for our goals. Running this function with &lt;code&gt;200_000_000&lt;/code&gt; factor takes ~&lt;strong&gt;5 sec&lt;/strong&gt; for execution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Blocking
&lt;/h3&gt;

&lt;p&gt;As mentioned above, any blocking operation won’t allow other tasks to execute until it’s finished.&lt;/p&gt;

&lt;p&gt;The best way to understand blocking is UI. Let’s add simple CLI loader to our application using &lt;code&gt;Ora&lt;/code&gt; library, just for example.&lt;/p&gt;

&lt;p&gt;First of all, we need to install it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    npm &lt;span class="nb"&gt;install &lt;/span&gt;ora @types/ora
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And change the Controller method in the following way. When the handler is triggered, the loader will appear in the terminal and will be spinning until our calculations are finished. Also, the time that was used for request processing will be printed.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Let’s start our server and trigger handler from the browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2Angdqa4ZF_i26RfR2PS3plA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2Angdqa4ZF_i26RfR2PS3plA.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The loader is not spinning, as our calculation blocked the process. The loader must have the possibility to re-render frames every &lt;code&gt;80&lt;/code&gt; milliseconds but can’t do it, as the event loop is blocked by &lt;code&gt;getAnswer&lt;/code&gt; call.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consequences
&lt;/h3&gt;

&lt;p&gt;Let’s imagine that we have this code in the real application. The handler will block accepting and processing new clients requests. It will seriously affect the client experience. Such operations must be placed into other application or in the other thread.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workers
&lt;/h2&gt;

&lt;p&gt;Odi provides convenient API for multithreading. The developer does not need to think about any type of setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Definition
&lt;/h3&gt;

&lt;p&gt;It’s really easy to define &lt;code&gt;Worker&lt;/code&gt; in Odi application and container. There are&lt;br&gt;
some similarities with &lt;code&gt;Service&lt;/code&gt; definition. Let’s wrap &lt;code&gt;getAnswer&lt;/code&gt; function.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Only &lt;code&gt;Worker&lt;/code&gt; decorator is required for definition. Now we can inject it in the&lt;br&gt;
controller as other dependencies.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Note, &lt;code&gt;await&lt;/code&gt; keyword must be added before the worker method call, even if it’s not async, as communication between threads is done in an asynchronous way.&lt;/p&gt;

&lt;p&gt;That’s all! 🧙‍♂️ The method will be executed in another thread and the result will be returned to the main.&lt;/p&gt;

&lt;h3&gt;
  
  
  Review
&lt;/h3&gt;

&lt;p&gt;Now, example with UI loader can be tested.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2A5vuSyhjwYUO5jS9T3ZX7OQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2A5vuSyhjwYUO5jS9T3ZX7OQ.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything is working. The loader is spinning, as the code is running in another thread, so UI can re-render frames.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check
&lt;/h3&gt;

&lt;p&gt;To be sure that the method was processed in another thread, simply change &lt;code&gt;getAnswer&lt;/code&gt; in the next way.&lt;/p&gt;

&lt;p&gt;Information about thread will be available right in the console.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparison
&lt;/h3&gt;

&lt;p&gt;As you can see above, zero configuration is required for workes setup and processing.No event emitters, event handlers, filename and etc are required like in the official &lt;a href="https://nodejs.org/api/worker_threads.html#worker_threads_worker_threads" rel="noopener noreferrer"&gt;example&lt;/a&gt;. Odi cares about initialization, messaging, method calls and errors handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;p&gt;There are no limitations in addition to basic ones. Remember that the worker is something like another application, so runtime instances can’t be accessed between different threads. Also, &lt;strong&gt;Dependency Injection&lt;/strong&gt; container can’t be accessed over the threads, so every single thread will have its own container.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases
&lt;/h2&gt;

&lt;p&gt;Basically, workers threads can be used in next approaches:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Background and scheduled tasks&lt;/li&gt;
&lt;li&gt; Resource-intensive operations&lt;/li&gt;
&lt;li&gt; Queue-based processing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Those approaches can be easily improved and adapted for each particular need, but all of them leads to performance improvements and application flexibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  More
&lt;/h2&gt;

&lt;p&gt;Thanks for reading! Feel free to &lt;a href="https://odi.nolt.io/" rel="noopener noreferrer"&gt;leave&lt;/a&gt; any feedback, ideas or questions.&lt;/p&gt;

&lt;p&gt;If you like Odi, simply support us with start on GitHub. 🌟✨&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Odi-ts" rel="noopener noreferrer"&gt;
        Odi-ts
      &lt;/a&gt; / &lt;a href="https://github.com/Odi-ts/odi" rel="noopener noreferrer"&gt;
        odi
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🌪🌌 Opinionated, Declarative, Idiomatic framework for building scalable, supportable and reliable enterprise applications. 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/01bf9d17bbf6b805a5bfd13d4157705a579a9bb557dd0e4a8ada2779722061cc/68747470733a2f2f692e696d6775722e636f6d2f345a66334f33352e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/01bf9d17bbf6b805a5bfd13d4157705a579a9bb557dd0e4a8ada2779722061cc/68747470733a2f2f692e696d6775722e636f6d2f345a66334f33352e706e67" height="94"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;
    &lt;a href="https://codeclimate.com/github/Odi-ts/odi/maintainability" rel="nofollow noopener noreferrer"&gt;
        &lt;img src="https://camo.githubusercontent.com/93022d56042a57abde03b77499ac64b88aa7ea391b395e31173e903910224a1d/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f35633733366563306663353966343331313238632f6d61696e7461696e6162696c697479"&gt;
    &lt;/a&gt;
    &lt;a href="https://codeclimate.com/github/Odi-ts/odi/test_coverage" rel="nofollow noopener noreferrer"&gt;
        &lt;img src="https://camo.githubusercontent.com/7d7ba32cbe19d043ae4221c56094c20c805bb01e8c2faf5be79b4d6d3f51d5ec/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f35633733366563306663353966343331313238632f746573745f636f766572616765"&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/58dee0fd4cbaa766d0f34f62b2e4cbe28ca2a79443e30743e10ebeb64073efb7/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f6f64692e737667"&gt;&lt;img src="https://camo.githubusercontent.com/58dee0fd4cbaa766d0f34f62b2e4cbe28ca2a79443e30743e10ebeb64073efb7/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f6f64692e737667"&gt;&lt;/a&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/1814eb6b9147243a9c6aa767c79a3b17889234be5d37d529fb2571c37444815b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f4f64692d74732f4f64692e737667"&gt;&lt;img src="https://camo.githubusercontent.com/1814eb6b9147243a9c6aa767c79a3b17889234be5d37d529fb2571c37444815b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f4f64692d74732f4f64692e737667"&gt;&lt;/a&gt; 
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/5aa8135f8ccd2dedae71dc4d9c04e4ba7a956e6a1902a22a3450a633f77cb38d/68747470733a2f2f696d672e736869656c64732e696f2f64657066752f4f64692d74732f6f64692e737667"&gt;&lt;img src="https://camo.githubusercontent.com/5aa8135f8ccd2dedae71dc4d9c04e4ba7a956e6a1902a22a3450a633f77cb38d/68747470733a2f2f696d672e736869656c64732e696f2f64657066752f4f64692d74732f6f64692e737667"&gt;&lt;/a&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/ccf24912b14477c6490de0fc74adb7e5bcc8f7bea91bab01934edf17d36ab359/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f4f64692d74732f4f64692e737667"&gt;&lt;img src="https://camo.githubusercontent.com/ccf24912b14477c6490de0fc74adb7e5bcc8f7bea91bab01934edf17d36ab359/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f4f64692d74732f4f64692e737667"&gt;&lt;/a&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/572a9feed58d7b065e9fb1304298eabf3d65be1a60e0c535d1ab1dc3b70fc696/68747470733a2f2f7472617669732d63692e636f6d2f4f64692d74732f6f64692e7376673f6272616e63683d6d6173746572"&gt;&lt;img src="https://camo.githubusercontent.com/572a9feed58d7b065e9fb1304298eabf3d65be1a60e0c535d1ab1dc3b70fc696/68747470733a2f2f7472617669732d63692e636f6d2f4f64692d74732f6f64692e7376673f6272616e63683d6d6173746572"&gt;&lt;/a&gt;
    &lt;a href="https://gitter.im/odiland/community" rel="nofollow noopener noreferrer"&gt;
        &lt;img src="https://camo.githubusercontent.com/5e3106bdac78e60b3a04d1258cda8a09760d64109354cc31eafc26dea7c6edbb/68747470733a2f2f696d672e736869656c64732e696f2f6769747465722f726f6f6d2f6e776a732f6e772e6a732e737667"&gt;
    &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;TypeScript framework for creating enterprise-grade (web) applications with simple and minimalistic API, that allows you to focus on business logic. Based on declarative and imperative programming, inspiried by &lt;a href="https://www.asp.net/" rel="nofollow noopener noreferrer"&gt;ASP.NET&lt;/a&gt; / &lt;a href="https://spring.io/" rel="nofollow noopener noreferrer"&gt;Spring&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check &lt;a href="https://odi.gitbook.io/core/basics/getting-started" rel="nofollow noopener noreferrer"&gt;Docs&lt;/a&gt; for more details.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Odi provides feature set for creation of easy supportable and scalable web applications.&lt;/p&gt;

&lt;p&gt;Features Overview:&lt;/p&gt;

&lt;ul class="contains-task-list"&gt;
&lt;li class="task-list-item"&gt;
 MVC&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Full-typed DI / IoT&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Authentication&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 WebSockets&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 TypeORM integration&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 GraphQL&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 AOP&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 SSR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For future updates check &lt;a href="https://github.com/Odi-ts/Odi/wiki/Roadmap" rel="noopener noreferrer"&gt;Roadmap&lt;/a&gt; &lt;br&gt;
Got an idea, proposal or feature request? Feel free to &lt;a href="https://odi.nolt.io/" rel="nofollow noopener noreferrer"&gt;Submit&lt;/a&gt; it!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://codesandbox.io/s/pjov89947x" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/ecd139ba9847d0c77607c86339eb8ee6939ca85143a92ae16ebf20f58325e1b6/68747470733a2f2f636f646573616e64626f782e696f2f7374617469632f696d672f706c61792d636f646573616e64626f782e737667" alt="Edit Odi"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Getting Started&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install npm package&lt;br&gt;
&lt;code&gt;npm install odi --save&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install reflect-metadata &lt;br&gt;
&lt;code&gt;npm install reflect-metadata --save&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Import reflect-metadata (for example in  &lt;code&gt;index.ts&lt;/code&gt;):&lt;br&gt;
&lt;code&gt;import "reflect-metadata";&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enabled the following settings in &lt;code&gt;tsconfig.json&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;"emitDecoratorMetadata"&lt;/span&gt;:  &lt;span class="pl-c1"&gt;true&lt;/span&gt;, 
&lt;span class="pl-ent"&gt;"experimentalDecorators"&lt;/span&gt;:  &lt;span class="pl-c1"&gt;true&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🌪 Overview&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Controller&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;Controllers serve as a simple yet powerful routing mechanism in a minimalistic style.&lt;/p&gt;
&lt;div class="highlight highlight-source-ts notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;@&lt;span class="pl-smi"&gt;Controller&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'foo'&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;
&lt;span class="pl-k"&gt;export&lt;/span&gt; &lt;span class="pl-k"&gt;class&lt;/span&gt; &lt;span class="pl-smi"&gt;FooController&lt;/span&gt; &lt;span class="pl-k"&gt;extends&lt;/span&gt; &lt;span class="pl-smi"&gt;IController&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;      
        
    @&lt;span class="pl-smi"&gt;RoutePatch&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'{id}'&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Odi-ts/odi" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Keep reading, much more interesting things will be shipped in the next updates!&lt;br&gt;
😉🧙‍♂️&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>node</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building chat with Odi (Node.js)</title>
      <dc:creator>Dan T.</dc:creator>
      <pubDate>Fri, 18 Jan 2019 21:06:19 +0000</pubDate>
      <link>https://dev.to/dantsk/building-chat-with-odi-nodejs-2am1</link>
      <guid>https://dev.to/dantsk/building-chat-with-odi-nodejs-2am1</guid>
      <description>&lt;h1&gt;
  
  
  Republish
&lt;/h1&gt;

&lt;p&gt;Sorry for republishing the same story. My teammate accidentally deleted the previous publication. He thought that we published it before the release date 😢 Thanks for understanding 😜&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;The chat application is the very common example that used to show simple real-time communication between client and server. This tutorial describes how it can be easily done with Odi,TypeScript server-side framework for&lt;br&gt;
Node.js.&lt;/p&gt;
&lt;h1&gt;
  
  
  Project Setup
&lt;/h1&gt;

&lt;p&gt;We are going to develop the application that not only establishes the real-time communication channel but also renders frontend to the client, including required assets.&lt;/p&gt;
&lt;h2&gt;
  
  
  Basic Settings
&lt;/h2&gt;

&lt;p&gt;Let’s set up the Odi project. First of all, we should initialize &lt;code&gt;package.json&lt;/code&gt;&lt;br&gt;
and &lt;code&gt;tsconfig.json&lt;/code&gt; files. We can do it with two simple commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
    tsc &lt;span class="nt"&gt;--init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And install &lt;strong&gt;Odi&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    npm &lt;span class="nb"&gt;install &lt;/span&gt;odi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Also, we need to modify &lt;code&gt;tsconfig.json&lt;/code&gt; file, as there are few options that must be edited. Odi actively uses decorators and metadata, so we need to enable these features.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"experimentalDecorators"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"emitDecoratorMetadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Another thing is &lt;code&gt;target&lt;/code&gt; option. By default, it set to&lt;code&gt;es5&lt;/code&gt; but there are&lt;br&gt;
several things that are not supported in is this specification. As we are&lt;br&gt;
progressive, let’s set it to the latest version&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ES2018"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;We are going to have different folders for views, assets and server source code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F880%2F1%2A2jLFB3kGBqfnLp3YfUWvXQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F880%2F1%2A2jLFB3kGBqfnLp3YfUWvXQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;src&lt;/strong&gt;— server source code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;views&lt;/strong&gt;— JSX templates that will be rendered to clients.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;assets&lt;/strong&gt;— client-side &lt;em&gt;JS&lt;/em&gt; and &lt;em&gt;CSS&lt;/em&gt; files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JSX templates are &lt;em&gt;tsx&lt;/em&gt; files that must be compiled. Add &lt;strong&gt;views&lt;/strong&gt; folder to&lt;br&gt;
&lt;em&gt;rootDirs&lt;/em&gt; in &lt;code&gt;tsconfig.json&lt;/code&gt; file and setup &lt;em&gt;outDir&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./build"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rootDirs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./src"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./views"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Gettings started
&lt;/h1&gt;

&lt;p&gt;Odi is based on the &lt;em&gt;Dependency Injection&lt;/em&gt; pattern, so every application component will be automatically imported, instantiated and injected.&lt;/p&gt;

&lt;p&gt;Only folder with source files must be specified, then Odi can scan it for importing application components (Controllers, Services, Repositories and etc).&lt;/p&gt;
&lt;h2&gt;
  
  
  Main File
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;index.ts&lt;/code&gt; file in &lt;code&gt;src&lt;/code&gt; folder. It will be the server entry point file.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Core&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;odi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;join&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Core&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;static&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../assets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/assets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Server successfully started!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We just need to instantiate &lt;code&gt;Core&lt;/code&gt; class. &lt;code&gt;Core&lt;/code&gt; constructor accepts a single argument, settings object. There are a lot of possible options, but for now, we need only several of them.&lt;/p&gt;

&lt;p&gt;First of all, we need to specify &lt;code&gt;sources&lt;/code&gt; property. It’s required setting for Odi application. As &lt;code&gt;index.ts&lt;/code&gt; file in &lt;code&gt;src&lt;/code&gt; folder, which we choose for server-side code, we can use &lt;code&gt;__dirname&lt;/code&gt; to set current directory.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;port&lt;/code&gt; property is also required. It binds the server on the specified port.&lt;/p&gt;

&lt;p&gt;Now about the following part:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nl"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../assets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
         &lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/assets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We must enable sockets and set options for serving static files All files from the &lt;strong&gt;assets&lt;/strong&gt; folder are available by URL with &lt;code&gt;/assets&lt;/code&gt; prefix.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing Dependencies
&lt;/h2&gt;

&lt;p&gt;Odi framework automatically includes only several packages that are required. All other dependencies for different features are optional, so they need to be installed only if you use a certain feature.&lt;/p&gt;

&lt;p&gt;For example, if you are going to build a simple REST server, you don’t need GraphQL, WebSockets, SSR and other packages.&lt;/p&gt;

&lt;p&gt;We want to have WebSockets and Templating (JSX) in our chat application. So, let’s install missing packages:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    npm &lt;span class="nb"&gt;install &lt;/span&gt;socket.io react react-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That’s all, Odi will automatically import it. As you can see, &lt;a href="http://socket.io" rel="noopener noreferrer"&gt;socket.io&lt;/a&gt;is used under the hood for real-time functionality. Also React packages is required for templates processing.&lt;/p&gt;

&lt;p&gt;Now we can start writing our code :)&lt;/p&gt;
&lt;h1&gt;
  
  
  Application
&lt;/h1&gt;

&lt;p&gt;We are going to create a web server, that renders HTML to the client, using&lt;br&gt;
templates, serves files for the client (JS, CSS) and set up a real-time&lt;br&gt;
communication channel using WebSockets for chat. Let’s add history to our chat. So, the last 10 messages will be saved in our system.&lt;/p&gt;
&lt;h2&gt;
  
  
  Message and History
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Message&lt;/code&gt; will be pretty simple, only &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;text&lt;/code&gt; fields. We can do it&lt;br&gt;
with a simple interface, as we are not going to use a database.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And history service&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HistoryService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

        &lt;span class="nf"&gt;getMessages&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nf"&gt;addMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Our store is a simple array of messages. And few methods for store management. If we get more than 10 messages, we simply remove the first message from the array.&lt;/p&gt;

&lt;p&gt;As you can see, &lt;code&gt;Service&lt;/code&gt; decorator was used for &lt;code&gt;HistoryService&lt;/code&gt; class to set is as a service component. Service is singleton in Dependency Injection Container. Now it can be injected into others application components.&lt;/p&gt;

&lt;p&gt;Put all this code in &lt;code&gt;history.ts&lt;/code&gt; file in &lt;code&gt;src/services&lt;/code&gt; folder.&lt;/p&gt;
&lt;h2&gt;
  
  
  Web Socket
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;chat.socket.ts&lt;/code&gt; file in the &lt;code&gt;src/sockets&lt;/code&gt; directory with the following&lt;br&gt;
code.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ISocket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Autowired&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;odi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;HistoryService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../services/history&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ChatSocket&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ISocket&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Autowired&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HistoryService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;OnEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;massage:send&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="nf"&gt;onmessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
           &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message:new&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We defined &lt;code&gt;/chat&lt;/code&gt; namespace with handler for &lt;code&gt;message:send&lt;/code&gt; event. If&lt;br&gt;
&lt;code&gt;message:send&lt;/code&gt; event is fired, all clients that connected to this namespace will be notified with &lt;code&gt;message:new&lt;/code&gt; event and message data.&lt;/p&gt;

&lt;p&gt;As you can notice &lt;code&gt;Socket&lt;/code&gt; decorator defines namespaces. Leading slash is not required. To set up method as the handler for certain event, use &lt;code&gt;OnEvent&lt;/code&gt;&lt;br&gt;
decorator, that accepts event name as the argument.&lt;/p&gt;

&lt;p&gt;Also, we injected &lt;code&gt;HistoryService&lt;/code&gt; using &lt;code&gt;Autowired&lt;/code&gt; decorator. &lt;code&gt;history&lt;/code&gt; field&lt;br&gt;
of &lt;code&gt;ChatSocket&lt;/code&gt; class will be initialized by Odi, so you don’t need to do&lt;br&gt;
anything additional.&lt;/p&gt;

&lt;p&gt;The only thing, you can see such error from TypeScript&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    [ts] Property 'history' has no initializer and is not definitely assigned in the constructor.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Odi automatically initializes injected fields, so just disable this check in&lt;br&gt;
&lt;code&gt;tsconfig.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"strictPropertyInitialization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Templating (JSX)
&lt;/h1&gt;

&lt;p&gt;There a lot of templating processors  —  EJS, Jade, Pug. But there are a lot of&lt;br&gt;
limitations and inconveniences with those technologies. In most cases, to have IntelliSense and code highlight for templates, you need to install an extension for IDE/Editor. &lt;/p&gt;

&lt;p&gt;In Odi, JSX powered by React is used for templating. You can simply create components with JSX. But remember, it’s only for templates, any logic, listeners or client-side code will be ignored during rendering. &lt;br&gt; &lt;em&gt;(Currently, we are working on full SSR.Hope it will be released soon)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We need to tell TypeScript compiler, that we are going to use React JSX.&lt;br&gt; In &lt;code&gt;tsconfig.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"jsx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Layout
&lt;/h2&gt;

&lt;p&gt;Let’s create our layout component &lt;code&gt;layout.view.tsx&lt;/code&gt; that will be a wrapper for all pages. As was mentioned above, all templates will be in &lt;strong&gt;views&lt;/strong&gt; folder.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SFC&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SFC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;charSet&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;httpEquiv&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"X-UA-Compatible"&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ie=edge"&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/assets/index.css"&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text/css"&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Simple chat &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"path/to/socket.io"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/assets/index.js"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For &lt;em&gt;socket.io-client&lt;/em&gt; library we can use CDN. So simply replace&lt;br&gt;
&lt;code&gt;path/to/socket.io&lt;/code&gt; in the script tag with the following link&lt;br&gt;
&lt;code&gt;https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Client js file was specified in the second script tag. We will create it a&lt;br&gt;
little bit later in &lt;strong&gt;assets&lt;/strong&gt; folder.&lt;/p&gt;
&lt;h2&gt;
  
  
  Chat Components
&lt;/h2&gt;

&lt;p&gt;Actually, we need 3 components for our chat:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Message representation&lt;/li&gt;
&lt;li&gt; Controls (Send button, message input, username input)&lt;/li&gt;
&lt;li&gt; Chat container&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I think we can put all these components in 1 file, &lt;code&gt;chat.view.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./services/history.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ChatMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;b&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;: &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;b&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We can use &lt;code&gt;Message&lt;/code&gt; interface as props type for &lt;code&gt;ChatMessage&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Let’s add chat controls. &lt;code&gt;id&lt;/code&gt; attribute was used for convenience, as we are&lt;br&gt;
going to use js on the client side without any libs or frameworks.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ChatControlls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"message-box"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"User"&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"user-input"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Message"&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"message-input"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Send &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And the last thing, chat wrapper.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ChatProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Chat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ChatProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"chat"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ChatMessage&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
             &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ChatControlls&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This component accepts an array of messages (our history) in props to render it on page load. &lt;/p&gt;

&lt;p&gt;Now we can put everything together and define our page component &lt;code&gt;page.view.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Chat&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./chat.view&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./layout.view&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./services/history.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ChatPageProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ChatPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;history&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ChatPageProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Chat&lt;/span&gt; &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;        
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That’s all about templating for our chat application. I have several lines of&lt;br&gt;
CSS that I will include it in the source code, that you can find at the end of&lt;br&gt;
the article. &lt;/p&gt;

&lt;p&gt;We can move to controllers. &lt;/p&gt;
&lt;h1&gt;
  
  
  Controllers
&lt;/h1&gt;

&lt;p&gt;Controllers serve as a simple yet powerful routing mechanism. Controller methods are mapped to web server paths. The value returned by the method is sent as the response.&lt;/p&gt;

&lt;p&gt;In order to create a Controller, you must use the &lt;code&gt;@Controller&lt;/code&gt; decorator and inherit the &lt;code&gt;IController&lt;/code&gt; class. The decorator sets the component type, so the DI (dependency injection) container can detect what the class will be used for.&lt;/p&gt;

&lt;p&gt;For our chat, we need only one controller to render a template to the client. As we are going to use JSX inside the controller file, it must have &lt;code&gt;tsx&lt;/code&gt; file&lt;br&gt;
extension. &lt;/p&gt;

&lt;p&gt;So, let’s create &lt;code&gt;render.controller.tsx&lt;/code&gt; in &lt;code&gt;src/controllers&lt;/code&gt; folder.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Autowired&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;odi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ChatPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../views/page.view&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;HistoryService&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../services/history.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RenderController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Autowired&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HistoryService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ChatPage&lt;/span&gt; &lt;span class="na"&gt;history&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getMessages&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As you can see, we injected our &lt;code&gt;HistoryService&lt;/code&gt; into &lt;code&gt;history&lt;/code&gt; property. Also, the handler for &lt;code&gt;/&lt;/code&gt; path with &lt;code&gt;Get&lt;/code&gt; method was defined. We can simply return our JSX component as a result, Odi automatically detects that it’s a template and renders it as simple HTML for the client (web browser).&lt;/p&gt;
&lt;h1&gt;
  
  
  Starting Application
&lt;/h1&gt;

&lt;p&gt;Now, we can start our application and see what we got. Let’s specify &lt;code&gt;start&lt;/code&gt; script in &lt;code&gt;package.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc &amp;amp;&amp;amp; node build/src/index.js"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Running &lt;code&gt;npm start&lt;/code&gt; command compile our source code and run server entry file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F880%2F1%2AMOMjK0wTD3qdXbVLot83qQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F880%2F1%2AMOMjK0wTD3qdXbVLot83qQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s open the browser and check &lt;code&gt;localhost:8080&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F880%2F1%2AFW2ep25-HbxJQCpewczhPQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F880%2F1%2AFW2ep25-HbxJQCpewczhPQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, we have just empty chat without any functionality, as we did not specify the client &lt;code&gt;index.js&lt;/code&gt; into &lt;strong&gt;assets&lt;/strong&gt; folder.&lt;/p&gt;
&lt;h1&gt;
  
  
  Client
&lt;/h1&gt;

&lt;p&gt;First of all, let’s get references for chat container and controls.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messageInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#message-input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usernameInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#user-input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.container&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When a new message comes, we need to append it as a child in &lt;code&gt;container&lt;/code&gt;&lt;br&gt;
element. We need the function for creating elements that represent messages.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
            &amp;lt;b&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &amp;lt;/b&amp;gt;
            &amp;lt;span&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/span&amp;gt;
        `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then, let’s connect to our &lt;code&gt;chat&lt;/code&gt; namespace and add the event handler for &lt;code&gt;message:new&lt;/code&gt; event. When this event is fired, the message element will be appended to the container.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;io&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/chat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message:new&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messageElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And the last step, &lt;code&gt;onclinck&lt;/code&gt; handler for our button.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;massage:send&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;messageInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;usernameInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nx"&gt;messageInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We are collecting data from inputs and sending it as &lt;code&gt;message:send&lt;/code&gt; event. Also, the message input text will be cleared after every send. &lt;/p&gt;

&lt;p&gt;Now we can refresh the page, and see what we have got.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F880%2F1%2AeUyiuOZdH4Fe55QAHhb5yQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F880%2F1%2AeUyiuOZdH4Fe55QAHhb5yQ.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After refreshing the page, we will have history our messaging.&lt;/p&gt;
&lt;h2&gt;
  
  
  Sandbox
&lt;/h2&gt;

&lt;p&gt;You can check the source code and interact with the application right here:&lt;br&gt;
&lt;iframe src="https://codesandbox.io/embed/30n2y702m"&gt;
&lt;/iframe&gt;
&lt;/p&gt;
&lt;h2&gt;
  
  
  PS
&lt;/h2&gt;

&lt;p&gt;Thanks for the reading! If you like Odi, please support us with a simple start on GitHub&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Odi-ts" rel="noopener noreferrer"&gt;
        Odi-ts
      &lt;/a&gt; / &lt;a href="https://github.com/Odi-ts/odi" rel="noopener noreferrer"&gt;
        odi
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🌪🌌 Opinionated, Declarative, Idiomatic framework for building scalable, supportable and reliable enterprise applications. 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/01bf9d17bbf6b805a5bfd13d4157705a579a9bb557dd0e4a8ada2779722061cc/68747470733a2f2f692e696d6775722e636f6d2f345a66334f33352e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/01bf9d17bbf6b805a5bfd13d4157705a579a9bb557dd0e4a8ada2779722061cc/68747470733a2f2f692e696d6775722e636f6d2f345a66334f33352e706e67" height="94"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;
    &lt;a href="https://codeclimate.com/github/Odi-ts/odi/maintainability" rel="nofollow noopener noreferrer"&gt;
        &lt;img src="https://camo.githubusercontent.com/93022d56042a57abde03b77499ac64b88aa7ea391b395e31173e903910224a1d/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f35633733366563306663353966343331313238632f6d61696e7461696e6162696c697479"&gt;
    &lt;/a&gt;
    &lt;a href="https://codeclimate.com/github/Odi-ts/odi/test_coverage" rel="nofollow noopener noreferrer"&gt;
        &lt;img src="https://camo.githubusercontent.com/7d7ba32cbe19d043ae4221c56094c20c805bb01e8c2faf5be79b4d6d3f51d5ec/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f35633733366563306663353966343331313238632f746573745f636f766572616765"&gt;
    &lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/58dee0fd4cbaa766d0f34f62b2e4cbe28ca2a79443e30743e10ebeb64073efb7/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f6f64692e737667"&gt;&lt;img src="https://camo.githubusercontent.com/58dee0fd4cbaa766d0f34f62b2e4cbe28ca2a79443e30743e10ebeb64073efb7/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f6f64692e737667"&gt;&lt;/a&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/1814eb6b9147243a9c6aa767c79a3b17889234be5d37d529fb2571c37444815b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f4f64692d74732f4f64692e737667"&gt;&lt;img src="https://camo.githubusercontent.com/1814eb6b9147243a9c6aa767c79a3b17889234be5d37d529fb2571c37444815b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f4f64692d74732f4f64692e737667"&gt;&lt;/a&gt; 
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/5aa8135f8ccd2dedae71dc4d9c04e4ba7a956e6a1902a22a3450a633f77cb38d/68747470733a2f2f696d672e736869656c64732e696f2f64657066752f4f64692d74732f6f64692e737667"&gt;&lt;img src="https://camo.githubusercontent.com/5aa8135f8ccd2dedae71dc4d9c04e4ba7a956e6a1902a22a3450a633f77cb38d/68747470733a2f2f696d672e736869656c64732e696f2f64657066752f4f64692d74732f6f64692e737667"&gt;&lt;/a&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/ccf24912b14477c6490de0fc74adb7e5bcc8f7bea91bab01934edf17d36ab359/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f4f64692d74732f4f64692e737667"&gt;&lt;img src="https://camo.githubusercontent.com/ccf24912b14477c6490de0fc74adb7e5bcc8f7bea91bab01934edf17d36ab359/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f4f64692d74732f4f64692e737667"&gt;&lt;/a&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/572a9feed58d7b065e9fb1304298eabf3d65be1a60e0c535d1ab1dc3b70fc696/68747470733a2f2f7472617669732d63692e636f6d2f4f64692d74732f6f64692e7376673f6272616e63683d6d6173746572"&gt;&lt;img src="https://camo.githubusercontent.com/572a9feed58d7b065e9fb1304298eabf3d65be1a60e0c535d1ab1dc3b70fc696/68747470733a2f2f7472617669732d63692e636f6d2f4f64692d74732f6f64692e7376673f6272616e63683d6d6173746572"&gt;&lt;/a&gt;
    &lt;a href="https://gitter.im/odiland/community" rel="nofollow noopener noreferrer"&gt;
        &lt;img src="https://camo.githubusercontent.com/5e3106bdac78e60b3a04d1258cda8a09760d64109354cc31eafc26dea7c6edbb/68747470733a2f2f696d672e736869656c64732e696f2f6769747465722f726f6f6d2f6e776a732f6e772e6a732e737667"&gt;
    &lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;TypeScript framework for creating enterprise-grade (web) applications with simple and minimalistic API, that allows you to focus on business logic. Based on declarative and imperative programming, inspiried by &lt;a href="https://www.asp.net/" rel="nofollow noopener noreferrer"&gt;ASP.NET&lt;/a&gt; / &lt;a href="https://spring.io/" rel="nofollow noopener noreferrer"&gt;Spring&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Check &lt;a href="https://odi.gitbook.io/core/basics/getting-started" rel="nofollow noopener noreferrer"&gt;Docs&lt;/a&gt; for more details.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Odi provides feature set for creation of easy supportable and scalable web applications.&lt;/p&gt;
&lt;p&gt;Features Overview:&lt;/p&gt;
&lt;ul class="contains-task-list"&gt;
&lt;li class="task-list-item"&gt;
 MVC&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Full-typed DI / IoT&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Authentication&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 WebSockets&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 TypeORM integration&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 GraphQL&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 AOP&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 SSR&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For future updates check &lt;a href="https://github.com/Odi-ts/Odi/wiki/Roadmap" rel="noopener noreferrer"&gt;Roadmap&lt;/a&gt; &lt;br&gt;
Got an idea, proposal or feature request? Feel free to &lt;a href="https://odi.nolt.io/" rel="nofollow noopener noreferrer"&gt;Submit&lt;/a&gt; it!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://codesandbox.io/s/pjov89947x" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/ecd139ba9847d0c77607c86339eb8ee6939ca85143a92ae16ebf20f58325e1b6/68747470733a2f2f636f646573616e64626f782e696f2f7374617469632f696d672f706c61792d636f646573616e64626f782e737667" alt="Edit Odi"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Getting Started&lt;/h2&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install npm package&lt;br&gt;
&lt;code&gt;npm install odi --save&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install reflect-metadata &lt;br&gt;
&lt;code&gt;npm install reflect-metadata --save&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Import reflect-metadata (for example in  &lt;code&gt;index.ts&lt;/code&gt;):&lt;br&gt;
&lt;code&gt;import "reflect-metadata";&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enabled the following settings in &lt;code&gt;tsconfig.json&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;"emitDecoratorMetadata"&lt;/span&gt;:  &lt;span class="pl-c1"&gt;true&lt;/span&gt;, 
&lt;span class="pl-ent"&gt;"experimentalDecorators"&lt;/span&gt;:  &lt;span class="pl-c1"&gt;true&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🌪 Overview&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Controller&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;Controllers serve as a simple yet powerful routing mechanism in a minimalistic style.&lt;/p&gt;

&lt;div class="highlight highlight-source-ts notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;@&lt;span class="pl-smi"&gt;Controller&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'foo'&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;
&lt;span class="pl-k"&gt;export&lt;/span&gt; &lt;span class="pl-k"&gt;class&lt;/span&gt; &lt;span class="pl-smi"&gt;FooController&lt;/span&gt; &lt;span class="pl-k"&gt;extends&lt;/span&gt; &lt;span class="pl-smi"&gt;IController&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;      
        
    @&lt;span class="pl-smi"&gt;RoutePatch&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'{id}'&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Odi-ts/odi" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Also, if you are looking for more information, you can check previous articles and docs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;a href="https://odi.gitbook.io" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://medium.com/@dantsk/odi-ddd54848c1c3" rel="noopener noreferrer"&gt;First Article&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://medium.com/@dantsk/odi-jsx-openapi-and-more-ca67555527b" rel="noopener noreferrer"&gt;Second
Article&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have any ideas or questions, feel free to leave them! Thanks a lot! :)&lt;/p&gt;



</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>node</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Odi - server-side framework</title>
      <dc:creator>Dan T.</dc:creator>
      <pubDate>Thu, 27 Dec 2018 23:58:33 +0000</pubDate>
      <link>https://dev.to/dantsk/odi---server-side-framework-2ep7</link>
      <guid>https://dev.to/dantsk/odi---server-side-framework-2ep7</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hi guys!&lt;/p&gt;

&lt;p&gt;I am currently working on the server-side TypeScript framework. My team already widely use this framework in various e-commerce and ERP projects. Structure and semantic were inspired by other popular frameworks like &lt;a href="https://spring.io/" rel="noopener noreferrer"&gt;Spring&lt;/a&gt; and &lt;a href="https://ASP.NET" rel="noopener noreferrer"&gt;ASP.NET&lt;/a&gt;&lt;a href="https://asp.net/" rel="noopener noreferrer"&gt;.&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;List of main goals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Testable, supportable, scalable&lt;/li&gt;
&lt;li&gt;Minimalistic, idiomatic, clear&lt;/li&gt;
&lt;li&gt;Intuitive, readable, understandable&lt;/li&gt;
&lt;li&gt;Powerful&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;​&lt;br&gt;
Currently, there are a lot of possibilities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Describing routing using controllers and decorators&lt;/li&gt;
&lt;li&gt;Powerful, full-typed Dependency Injection&lt;/li&gt;
&lt;li&gt;Incoming data validation (using AJV) with various set of decorators&lt;/li&gt;
&lt;li&gt;TypeORM integration (Repositories injection, Transactional support using CLS)&lt;/li&gt;
&lt;li&gt;Extendable JWT-based authentication&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All parts of the framework are fully typed and integrated with the whole infrastructure.&lt;/p&gt;

&lt;p&gt;For the best performance, under the hood, &lt;a href="https://www.fastify.io/" rel="noopener noreferrer"&gt;Fastify&lt;/a&gt; is used. The framework is declarative, but also avoids using decorators were it's possible. So, it's keep everything simple, clean and minimalistic.&lt;/p&gt;
&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Controller
&lt;/h3&gt;

&lt;p&gt;Controllers serve as a simple yet powerful routing mechanism in a minimalistic style.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FooController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;      

        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;RoutePatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{id}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     
        &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FooDTO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;         
            &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;some&lt;/span&gt; &lt;span class="nx"&gt;updates&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;          
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;     
        &lt;span class="p"&gt;}&lt;/span&gt; 

        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So, as you see, there no need to provide any additional param decorators for injection data from the HTTP request. It's just a small controller overview, there are a lot of other possibilities.You can read more in &lt;a href="https://odi.gitbook.io/core/basics/controller" rel="noopener noreferrer"&gt;docs&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Dependency Injection
&lt;/h3&gt;

&lt;p&gt;Odi has powerful dependency injection mechanism out of the box. &lt;br&gt;
(Let's imagine that we already have &lt;code&gt;FooRepository&lt;/code&gt;)&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;//foo.service.ts&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FooService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;​&lt;/span&gt;
        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Autowired&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FooRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;​&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;getFoo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="c1"&gt;//foo.controller.ts&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;​&lt;/span&gt;
        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Autowired&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nx"&gt;fooService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OrderService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;​&lt;/span&gt;
        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{id}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fooService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFoo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;NotFound&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As you can see, all dependencies will be automatically provided to all application components.&lt;/p&gt;

&lt;p&gt;Currently, Odi support 3 ways of injection: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By constructor&lt;/li&gt;
&lt;li&gt;By property&lt;/li&gt;
&lt;li&gt;By method&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Classes that are not Odi components can participate in DI. You can simply define behaviour with preset properties and constructor args.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;​&lt;/span&gt;
    &lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;constructorArgs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...],&lt;/span&gt;        
            &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{...},&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;singleton&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;special&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;constructorArgs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...],&lt;/span&gt;        
            &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{...},&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scoped&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  DTO
&lt;/h3&gt;

&lt;p&gt;It's a common scenario when web server should validate data before processing. DTO can optimize and automate this process.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoDTO&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;​&lt;/span&gt;
        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;MaxLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;​&lt;/span&gt;
        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;IsOptional&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;MaxLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;desctiption&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then, DTO class should be added as an argument for the controller method&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;todo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;IController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Autowired&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nx"&gt;todoService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TodoService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   

        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Post&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TodoDTO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;​&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And it's all! Odi will automatically inject the validated request body in this argument. If there are some errors during validation, 400 status code will be sent with errors description.&lt;/p&gt;

&lt;p&gt;Odi provides a wide set for DTO description, supporting nested DTOs, arrays, enums and etc.&lt;/p&gt;
&lt;h3&gt;
  
  
  To Sum up
&lt;/h3&gt;

&lt;p&gt;It was a small overview of some features. If you interested in more, check the &lt;a href="https://odi.gitbook.io/core/" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Coming Soon
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;AOP&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://grpc.io/" rel="noopener noreferrer"&gt;GRPC&lt;/a&gt; integration&lt;/li&gt;
&lt;li&gt;GraphQL&lt;/li&gt;
&lt;li&gt;CLI&lt;/li&gt;
&lt;li&gt;OpenAPI&lt;/li&gt;
&lt;li&gt;and more...&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Odi-ts" rel="noopener noreferrer"&gt;
        Odi-ts
      &lt;/a&gt; / &lt;a href="https://github.com/Odi-ts/odi" rel="noopener noreferrer"&gt;
        odi
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🌪🌌 Opinionated, Declarative, Idiomatic framework for building scalable, supportable and reliable enterprise applications. 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/01bf9d17bbf6b805a5bfd13d4157705a579a9bb557dd0e4a8ada2779722061cc/68747470733a2f2f692e696d6775722e636f6d2f345a66334f33352e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/01bf9d17bbf6b805a5bfd13d4157705a579a9bb557dd0e4a8ada2779722061cc/68747470733a2f2f692e696d6775722e636f6d2f345a66334f33352e706e67" height="94"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;
    &lt;a href="https://codeclimate.com/github/Odi-ts/odi/maintainability" rel="nofollow noopener noreferrer"&gt;
        &lt;img src="https://camo.githubusercontent.com/93022d56042a57abde03b77499ac64b88aa7ea391b395e31173e903910224a1d/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f35633733366563306663353966343331313238632f6d61696e7461696e6162696c697479"&gt;
    &lt;/a&gt;
    &lt;a href="https://codeclimate.com/github/Odi-ts/odi/test_coverage" rel="nofollow noopener noreferrer"&gt;
        &lt;img src="https://camo.githubusercontent.com/7d7ba32cbe19d043ae4221c56094c20c805bb01e8c2faf5be79b4d6d3f51d5ec/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f35633733366563306663353966343331313238632f746573745f636f766572616765"&gt;
    &lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/58dee0fd4cbaa766d0f34f62b2e4cbe28ca2a79443e30743e10ebeb64073efb7/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f6f64692e737667"&gt;&lt;img src="https://camo.githubusercontent.com/58dee0fd4cbaa766d0f34f62b2e4cbe28ca2a79443e30743e10ebeb64073efb7/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f6f64692e737667"&gt;&lt;/a&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/1814eb6b9147243a9c6aa767c79a3b17889234be5d37d529fb2571c37444815b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f4f64692d74732f4f64692e737667"&gt;&lt;img src="https://camo.githubusercontent.com/1814eb6b9147243a9c6aa767c79a3b17889234be5d37d529fb2571c37444815b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f4f64692d74732f4f64692e737667"&gt;&lt;/a&gt; 
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/5aa8135f8ccd2dedae71dc4d9c04e4ba7a956e6a1902a22a3450a633f77cb38d/68747470733a2f2f696d672e736869656c64732e696f2f64657066752f4f64692d74732f6f64692e737667"&gt;&lt;img src="https://camo.githubusercontent.com/5aa8135f8ccd2dedae71dc4d9c04e4ba7a956e6a1902a22a3450a633f77cb38d/68747470733a2f2f696d672e736869656c64732e696f2f64657066752f4f64692d74732f6f64692e737667"&gt;&lt;/a&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/ccf24912b14477c6490de0fc74adb7e5bcc8f7bea91bab01934edf17d36ab359/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f4f64692d74732f4f64692e737667"&gt;&lt;img src="https://camo.githubusercontent.com/ccf24912b14477c6490de0fc74adb7e5bcc8f7bea91bab01934edf17d36ab359/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f4f64692d74732f4f64692e737667"&gt;&lt;/a&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/572a9feed58d7b065e9fb1304298eabf3d65be1a60e0c535d1ab1dc3b70fc696/68747470733a2f2f7472617669732d63692e636f6d2f4f64692d74732f6f64692e7376673f6272616e63683d6d6173746572"&gt;&lt;img src="https://camo.githubusercontent.com/572a9feed58d7b065e9fb1304298eabf3d65be1a60e0c535d1ab1dc3b70fc696/68747470733a2f2f7472617669732d63692e636f6d2f4f64692d74732f6f64692e7376673f6272616e63683d6d6173746572"&gt;&lt;/a&gt;
    &lt;a href="https://gitter.im/odiland/community" rel="nofollow noopener noreferrer"&gt;
        &lt;img src="https://camo.githubusercontent.com/5e3106bdac78e60b3a04d1258cda8a09760d64109354cc31eafc26dea7c6edbb/68747470733a2f2f696d672e736869656c64732e696f2f6769747465722f726f6f6d2f6e776a732f6e772e6a732e737667"&gt;
    &lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;TypeScript framework for creating enterprise-grade (web) applications with simple and minimalistic API, that allows you to focus on business logic. Based on declarative and imperative programming, inspiried by &lt;a href="https://www.asp.net/" rel="nofollow noopener noreferrer"&gt;ASP.NET&lt;/a&gt; / &lt;a href="https://spring.io/" rel="nofollow noopener noreferrer"&gt;Spring&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Check &lt;a href="https://odi.gitbook.io/core/basics/getting-started" rel="nofollow noopener noreferrer"&gt;Docs&lt;/a&gt; for more details.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Odi provides feature set for creation of easy supportable and scalable web applications.&lt;/p&gt;
&lt;p&gt;Features Overview:&lt;/p&gt;
&lt;ul class="contains-task-list"&gt;
&lt;li class="task-list-item"&gt;
 MVC&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Full-typed DI / IoT&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Authentication&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 WebSockets&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 TypeORM integration&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 GraphQL&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 AOP&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 SSR&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For future updates check &lt;a href="https://github.com/Odi-ts/Odi/wiki/Roadmap" rel="noopener noreferrer"&gt;Roadmap&lt;/a&gt; &lt;br&gt;
Got an idea, proposal or feature request? Feel free to &lt;a href="https://odi.nolt.io/" rel="nofollow noopener noreferrer"&gt;Submit&lt;/a&gt; it!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://codesandbox.io/s/pjov89947x" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/ecd139ba9847d0c77607c86339eb8ee6939ca85143a92ae16ebf20f58325e1b6/68747470733a2f2f636f646573616e64626f782e696f2f7374617469632f696d672f706c61792d636f646573616e64626f782e737667" alt="Edit Odi"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Getting Started&lt;/h2&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install npm package&lt;br&gt;
&lt;code&gt;npm install odi --save&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install reflect-metadata &lt;br&gt;
&lt;code&gt;npm install reflect-metadata --save&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Import reflect-metadata (for example in  &lt;code&gt;index.ts&lt;/code&gt;):&lt;br&gt;
&lt;code&gt;import "reflect-metadata";&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enabled the following settings in &lt;code&gt;tsconfig.json&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;"emitDecoratorMetadata"&lt;/span&gt;:  &lt;span class="pl-c1"&gt;true&lt;/span&gt;, 
&lt;span class="pl-ent"&gt;"experimentalDecorators"&lt;/span&gt;:  &lt;span class="pl-c1"&gt;true&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🌪 Overview&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Controller&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;Controllers serve as a simple yet powerful routing mechanism in a minimalistic style.&lt;/p&gt;

&lt;div class="highlight highlight-source-ts notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;@&lt;span class="pl-smi"&gt;Controller&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'foo'&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;
&lt;span class="pl-k"&gt;export&lt;/span&gt; &lt;span class="pl-k"&gt;class&lt;/span&gt; &lt;span class="pl-smi"&gt;FooController&lt;/span&gt; &lt;span class="pl-k"&gt;extends&lt;/span&gt; &lt;span class="pl-smi"&gt;IController&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;      
        
    @&lt;span class="pl-smi"&gt;RoutePatch&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'{id}'&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Odi-ts/odi" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://odi.gitbook.io/core/" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, we aim to support &lt;a href="https://github.com/denoland/deno" rel="noopener noreferrer"&gt;Deno&lt;/a&gt; in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Difference between Nestjs
&lt;/h2&gt;

&lt;p&gt;Basically, there only a few common things with Nestjs: MVC Pattern and declarative style. But there are a lot of differences, like the whole infrastructure, decorators use, dependency injection and many others. To sum up differences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nestjs is heavily using decorators, Odi reduces this usage to the minimum (To keep code clean and readable).&lt;/li&gt;
&lt;li&gt;Odi provides built-in validation out of the box for HTTP data via AJV.&lt;/li&gt;
&lt;li&gt;DI/IoT behavior is very different. There is much more magic in Odi, in few words :)&lt;/li&gt;
&lt;li&gt;Authentication out of the box, that fully integrated with other framework modules.&lt;/li&gt;
&lt;li&gt;Controller and WebSockets processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the future, it will be the big difference between all integrations and technologies, as Odi was designed from the beginning in another way than Nest.&lt;/p&gt;

&lt;p&gt;In my sight, Nestjs is more about &lt;a href="https://www.spring.io/" rel="noopener noreferrer"&gt;Spring&lt;/a&gt;, but our framework is more &lt;a href="https://asp.net/" rel="noopener noreferrer"&gt;ASP&lt;/a&gt; :)&lt;/p&gt;

&lt;h2&gt;
  
  
  P.S
&lt;/h2&gt;

&lt;p&gt;From the beginning, the framework was designed as opensource. I really need your feedback, it's very important for me! &lt;/p&gt;

&lt;h3&gt;
  
  
  P.P.S
&lt;/h3&gt;

&lt;p&gt;My small kitten Nancy asking for stars on github 😄😄&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcn1kw8wols3n60824kr4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcn1kw8wols3n60824kr4.png"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>typescript</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
