<?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: Pavel Litkin</title>
    <description>The latest articles on DEV Community by Pavel Litkin (@bfunc).</description>
    <link>https://dev.to/bfunc</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%2F565795%2Fee034adf-4522-4f09-8b03-979c997010fa.JPG</url>
      <title>DEV Community: Pavel Litkin</title>
      <link>https://dev.to/bfunc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bfunc"/>
    <language>en</language>
    <item>
      <title>Ultimate Node.js starter that scales with DI, native TypeScript, super fast unit tests and all batteries included</title>
      <dc:creator>Pavel Litkin</dc:creator>
      <pubDate>Sun, 10 Jul 2022 16:03:13 +0000</pubDate>
      <link>https://dev.to/bfunc/bulletproof-nodejs-starter-that-scales-with-di-native-typescript-super-fast-unit-tests-and-all-batteries-included-1a85</link>
      <guid>https://dev.to/bfunc/bulletproof-nodejs-starter-that-scales-with-di-native-typescript-super-fast-unit-tests-and-all-batteries-included-1a85</guid>
      <description>&lt;h2&gt;
  
  
  TOC
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Quick start&lt;/li&gt;
&lt;li&gt;Tooling&lt;/li&gt;
&lt;li&gt;Unit tests&lt;/li&gt;
&lt;li&gt;Project structure&lt;/li&gt;
&lt;li&gt;Dependency injection&lt;/li&gt;
&lt;li&gt;Automatic module loading&lt;/li&gt;
&lt;li&gt;Swagger documentation generator&lt;/li&gt;
&lt;li&gt;Final words&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Ultimate Node.js Starter that Scales with Native TypeScript, Super Fast Unit Tests, DI and more Batteries Included
&lt;/h1&gt;

&lt;p&gt;The purpose of this post is to provide you with a tool to start your new node.js projects with an emphasis on scalability and developer experience.&lt;/p&gt;

&lt;p&gt;The main idea is to use minimum dependencies, easier maintenance, better re-compiling times, faster testing, less boilerplate.&lt;/p&gt;

&lt;h1&gt;
  
  
  Quick Start &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Clone the repository with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone --depth=1 https://github.com/bfunc/nodejs-ulitmate-template.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the dependencies with you favorite package manager&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the application in development mode with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;ts-node-dev&lt;/code&gt; will effectively restart node process on files change&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Access&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:4000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Map of example routes:&lt;br&gt;
&lt;code&gt;/docs&lt;/code&gt; - swagger docs&lt;br&gt;
&lt;code&gt;/orders&lt;/code&gt; - sample api route&lt;br&gt;
&lt;code&gt;/products&lt;/code&gt; - example api route&lt;br&gt;
&lt;code&gt;/products/:id&lt;/code&gt; - example api route&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;└── /
    ├── docs (GET)
    │   docs (HEAD)
    │   └── / (GET)
    │       / (HEAD)
    │       ├── * (GET)
    │       │   * (HEAD)
    │       ├── uiConfig (GET)
    │       │   uiConfig (HEAD)
    │       ├── initOAuth (GET)
    │       │   initOAuth (HEAD)
    │       ├── json (GET)
    │       │   json (HEAD)
    │       ├── yaml (GET)
    │       │   yaml (HEAD)
    │       └── static/
    │           └── * (GET)
    │               * (HEAD)
    ├── orders (GET)
    │   orders (HEAD)
    └── products (GET)
        products (HEAD)
        └── /
            └── :id (GET)
                :id (HEAD)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the application in production mode&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;You're ready to go!&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional commands
&lt;/h3&gt;

&lt;p&gt;Run unit tests&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run test coverage&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run coverage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Auto format all project files with &lt;code&gt;prittier&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run format
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run ESlint on all project files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run lint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Tooling &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Native TypeScript
&lt;/h2&gt;

&lt;p&gt;We can avoid cumbersome compiling step with intermediate artifacts and get native TypeScript execution for node.js with &lt;a href="https://typestrong.org/ts-node/docs/performance"&gt;ts-node&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With ts-node you can run any _.ts directly as you are running regular _.js script with node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ts-node index.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It comes with a price of small performance overhead on first file read at runtime, so if this is a concern for your application in production you can use ts-node together with SWC (in order of magnitude faster TypeScript transpiler implemented in Rust) without typechecking.&lt;/p&gt;

&lt;p&gt;Path mapping&lt;br&gt;
Very handy &lt;a href="https://github.com/dividab/tsconfig-paths"&gt;tsconfig-paths&lt;/a&gt; library&lt;br&gt;
allows to import modules from the filesystem without prefixing them with "./".&lt;/p&gt;

&lt;p&gt;Watch Mode&lt;br&gt;
We are going to use &lt;code&gt;ts-node-dev&lt;/code&gt; to watch files and restart application on change, &lt;code&gt;ts-node-dev&lt;/code&gt; is tweaked version of &lt;code&gt;node-dev&lt;/code&gt; that uses &lt;code&gt;ts-node&lt;/code&gt; under the hood. It restarts target node process but shares Typescript compilation process between restarts. This significantly increases speed of restarting comparing to &lt;code&gt;node-dev&lt;/code&gt; or &lt;code&gt;nodemon&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  ESLint
&lt;/h2&gt;

&lt;p&gt;Nothing special here, ESLint config extends &lt;code&gt;@typescript-eslint/recommended&lt;/code&gt; rules.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;lint&lt;/code&gt; command run linter on whole project&lt;/p&gt;
&lt;h2&gt;
  
  
  Environment
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;.env&lt;/code&gt; file to simplify setting environment variables for development, it will be&lt;br&gt;
picked up by &lt;a href="https://www.npmjs.com/package/dotenv"&gt;dotenv&lt;/a&gt;.&lt;br&gt;
Env files may contain values such as database passwords or API keys. It is bad practice committing &lt;code&gt;.env&lt;/code&gt; files to version control.&lt;/p&gt;
&lt;h2&gt;
  
  
  Logging
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;pino&lt;/code&gt; json logger, because it is standard in most enterprise applications.&lt;/p&gt;
&lt;h2&gt;
  
  
  Webserver
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Fastify&lt;/code&gt; web framework, becasue it is highly focused on providing the best developer experience with the least overhead.&lt;/p&gt;
&lt;h1&gt;
  
  
  Unit Test &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Testing is very important part of development process, that is why here we are going to bet on new player on unit test frameworks field &lt;a href="https://vitest.dev/guide/features.html"&gt;Vitest&lt;/a&gt;. In this case benefits are more important than potential risk choosing less established solution in enterprise (in any case it is worth a try because &lt;code&gt;Vitest&lt;/code&gt; and &lt;code&gt;Jest&lt;/code&gt; APIs and snapshots are compatible).&lt;/p&gt;
&lt;h1&gt;
  
  
  Benefits of using &lt;code&gt;Vitest&lt;/code&gt; over &lt;code&gt;Jest&lt;/code&gt;
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Main benefit is speed, in testing speed is important, especially if you tend to work in TDD/BDD style, every millisecond matters and &lt;code&gt;Vitest&lt;/code&gt; is way faster than Jest in watch mode.&lt;/li&gt;
&lt;li&gt;It understands TypeScript natively, no need to run transpiler&lt;/li&gt;
&lt;li&gt;Everything is in the box, assertions, mocking, coverage - no need to maintain bloated list of dependencies.&lt;/li&gt;
&lt;li&gt;Vitest UI, test dashboard interface. &lt;a href="https://stackblitz.com/edit/vitejs-vite-w46jsw?file=README.md"&gt;demo&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Warning though, &lt;code&gt;Vitest&lt;/code&gt; is in active development and still considered as not fully stable. Checkout &lt;a href="https://vuejs.org/guide/scaling-up/testing.html#recommendation"&gt;doc page&lt;/a&gt; for more info.&lt;/p&gt;
&lt;h1&gt;
  
  
  Project structure &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Two of the most commonly used approaches to structure projects are: &lt;code&gt;Folder-by-type&lt;/code&gt; and &lt;code&gt;Folder-by-feature&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Examples:
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Folder-by-type&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;src&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;controllers&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;UserController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;PetController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;repositories&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;PetRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;services&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;PetService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Folder-by-feature&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;src&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;pet&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;PetController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;PetRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;PetService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;UserController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Natively, when we are starting a new project, we tend to follow &lt;code&gt;Folder-by-type&lt;/code&gt; approach, because when there is small amount of functionality it looks cleaner and requires less thinking. But what actually happens is that when project grows it basically turns into one big feature without clean separation of concerns inside.&lt;/p&gt;

&lt;p&gt;It turns out that&lt;br&gt;
&lt;code&gt;Folder-by-type&lt;/code&gt; works well on small-scale projects and &lt;code&gt;Folder-by-feature&lt;/code&gt; better suits large applications, because it provides higher modularity and easier code navigation.&lt;/p&gt;

&lt;p&gt;We are aiming for scale with this starter, so it is based on &lt;code&gt;Folder-by-feature&lt;/code&gt; structure and when project will became really big and amount of files in feature will become too high, structure can be improved a bit by taking an advantage of &lt;code&gt;Folder-by-type&lt;/code&gt; structure inside features.&lt;/p&gt;

&lt;p&gt;It may look like this:&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Folder-by-feature-by-type&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;src&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;pet&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;controllers&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;PetGenericController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;PetSpecificController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;services&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;         &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;PetGenericService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;         &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;PetSpecificService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;controllers&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;UserGenericController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;UserPrivateController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;UserPublicController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;services&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;         &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;UserGenericService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;         &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;UserPrivateService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;         &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;UserPublicService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Dependency Injection &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;The idea behind dependency injection is really simple, it is basically providing list of dependencies as parameters instead of having hardcoded imports.&lt;/p&gt;

&lt;p&gt;The base of our dependency injection is a design pattern called composition root, it is located in the &lt;code&gt;src/container.ts&lt;/code&gt; file. Container is getting created with provided collection of dependencies, dependancy can be anything constant, function or class.&lt;br&gt;
Example:&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;getUserService&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;UserModel&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;{&lt;/span&gt;
    &lt;span class="na"&gt;getUserWithBooks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userId&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;...&lt;/span&gt;
      &lt;span class="nx"&gt;UserModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBooksByUserId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&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="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// the `userService` is resolved by invoking the function.&lt;/span&gt;
  &lt;span class="na"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;asFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getUserService&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;Take a look at &lt;a href="https://github.com/jeffijoe/awilix#asfunction"&gt;awilix docs&lt;/a&gt; for more information.&lt;/p&gt;

&lt;h1&gt;
  
  
  Automatic module loading &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Automatic module loading from filesystem (like pages in next.js) is used. The convention is that before container creation script will look into modules folder, traverse its content and auto load dependencies of defined types, like models, controllers, services etc. Check &lt;code&gt;src/index.ts&lt;/code&gt; for list of filenames that will be automatically loaded.&lt;/p&gt;

&lt;p&gt;For now &lt;code&gt;dependenciesLoader.ts&lt;/code&gt; script is very basic, for more advanced scenarios with nested folders or glob patterns you can use built-in &lt;code&gt;awilix&lt;/code&gt; &lt;a href="https://github.com/jeffijoe/awilix#auto-loading-modules"&gt;loadModules&lt;/a&gt; function.&lt;/p&gt;

&lt;h1&gt;
  
  
  Swagger documentation generator &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Automatically generated Swagger docs from your model schemas. Zod instance is automatically converted to JSON schema that is provided to Fastify route in order to generate docs, no code duplication.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final words &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Ultimate Starter was designed to be as much flexible as less opinionated as possible, that is why Database drivers, ORMs or authentication libraries were not included as part of the starter, despite there is strong temptation to add at least integration with &lt;a href="https://supabase.com/"&gt;supabase&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is not easy to find the Golden Mean, here is list of things that are currently missing, sorted by importance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Error handling&lt;/li&gt;
&lt;li&gt;GraphQL&lt;/li&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Commit hooks&lt;/li&gt;
&lt;li&gt;Deployment guidelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If there is something that is missing to achieve the best developer experience possible, please do not hesitate and leave a comment. Your comments may be extremely valuable, other people may encounter the same things you do. Sharing is caring :)&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Simple TypeScript tricks for scalable apps</title>
      <dc:creator>Pavel Litkin</dc:creator>
      <pubDate>Sun, 01 May 2022 17:27:05 +0000</pubDate>
      <link>https://dev.to/bfunc/simple-typescript-tricks-for-scalable-apps-3k75</link>
      <guid>https://dev.to/bfunc/simple-typescript-tricks-for-scalable-apps-3k75</guid>
      <description>&lt;p&gt;TypeScript gains popularity each day. We use TypeScript because it makes development safer and faster. Here is a set of tricks and guidelines for a more rigorous use of TypeScript. You need to get used to them once - and they will save a lot of time in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do not use &lt;code&gt;any&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The trick is, instead of ignoring the problem - "legalize" it:&lt;br&gt;
&lt;code&gt;type TODO_ANY = any&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Pros:
&lt;/h4&gt;

&lt;p&gt;• You do not have to be desperate and write props.&lt;br&gt;
• You are deliberately showing that the code should be improved in the future.&lt;br&gt;
• This type is easy to find by searching for the project.&lt;/p&gt;
&lt;h4&gt;
  
  
  Restrictions:
&lt;/h4&gt;

&lt;p&gt;• Using this technique too often is unlikely to be beneficial.&lt;br&gt;
• Conscientiousness and responsibility are needed to remove such gaps in the future.&lt;/p&gt;

&lt;p&gt;You may also find it useful:&lt;br&gt;
&lt;code&gt;export type TODO_UNKNOWN = unknown;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the case of any, the compiler will allow almost any action. In the case of unknown, on the contrary, almost any use will lead to an error.&lt;/p&gt;

&lt;p&gt;Last word, do not use &lt;code&gt;any&lt;/code&gt; even if type does not matter, for example, instead of this:&lt;br&gt;
   &lt;code&gt;const getLength = (arr: any []) =&amp;gt; arr.length&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;you can write this:&lt;br&gt;
   &lt;code&gt;const getLength = (arr: { length: number }) =&amp;gt; arr.length&lt;/code&gt;&lt;br&gt;
It is not ideal, but is much better than &lt;code&gt;any&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Of course best solution in this specific case is to use generics:&lt;br&gt;
&lt;code&gt;const getLength = &amp;lt;T&amp;gt;(arr: T[]) =&amp;gt; arr.length;&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Use &lt;code&gt;readonly&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;It is bad practice to mutate the structures you work with. For example, in the Angular world, this immediately leads to a number of consequences in the application: problems appear with checking changes in components, after which the display is not updated after mutating the data.&lt;br&gt;
But can we easily prevent all attempts to mutate data? For myself, I just formed a habit of writing readonly everywhere.&lt;/p&gt;
&lt;h4&gt;
  
  
  What is to be done?
&lt;/h4&gt;

&lt;p&gt;There are likely many places in your application where you can replace unsafe types with readonly alternatives.&lt;/p&gt;

&lt;p&gt;Use &lt;em&gt;readonly&lt;/em&gt; on interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Before
export interface Person {
  name: string;
}

// After
export interface Person {
  readonly name: string;
}

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

&lt;/div&gt;



&lt;p&gt;Give preference to &lt;em&gt;readonly&lt;/em&gt; in the types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Before
export type UnsafeType = { prop: number }

// After
export type SafeType = Readonly&amp;lt;{ prop: number }&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;em&gt;readonly&lt;/em&gt; fields class wherever it is possible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Before
class UnsafeComponent {
  loader$ = new Loader&amp;lt;boolean&amp;gt;(true);
}

// After
class SafeComponent {
  readonly loader$ = new Loader&amp;lt;boolean&amp;gt;(true);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use &lt;em&gt;readonly&lt;/em&gt; on all data structures, like:&lt;br&gt;
&lt;code&gt;const numsFromServer = readonly number[] = [1, 2, 42]&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  as const
&lt;/h4&gt;

&lt;p&gt;TypeScript v3.4 introduces const-assertions. It is a stricter tool than readonly types because it will pack your constant with the most precise type possible. Now you can be sure: no one and nothing can change this.&lt;/p&gt;

&lt;p&gt;Also, when using as const, your IDE will always show you the exact type of the entity being used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use &lt;em&gt;strict&lt;/em&gt; mode
&lt;/h2&gt;

&lt;p&gt;TypeScript has a cool strict mode that is unfortunately disabled by default. It includes a set of rules for safe and comfortable working with TypeScript.&lt;br&gt;
With &lt;em&gt;strict&lt;/em&gt; mode, you forget about errors like &lt;strong&gt;&lt;em&gt;undefined is not a function&lt;/em&gt;&lt;/strong&gt; and &lt;em&gt;&lt;strong&gt;cannot read property X of null&lt;/strong&gt;&lt;/em&gt;. Your types will be accurate and correct.&lt;/p&gt;

&lt;h4&gt;
  
  
  What is to be done?
&lt;/h4&gt;

&lt;p&gt;If you start a new project, just turn on &lt;em&gt;strict&lt;/em&gt; right away and be happy.&lt;/p&gt;

&lt;p&gt;If you already have a project without &lt;em&gt;strict&lt;/em&gt; mode and now you want to enable it, then you will face a number of difficulties. It is very difficult to write &lt;em&gt;strict&lt;/em&gt; code when the compiler does not signal problems in any way. So you will probably have a lot of buggy spots and the migration process makes you bored very quickly.&lt;/p&gt;

&lt;p&gt;Generally, the best approach is to break this huge task into chunks. The &lt;em&gt;strict&lt;/em&gt; mode itself is a set of six rules. You can enable one of them and fix any errors. Your project is now a little more rigorous. Next time, turn on another rule, correct any mistakes and keep working. In one day, you will collect the entire &lt;em&gt;strict&lt;/em&gt; mode!&lt;/p&gt;

&lt;p&gt;But in large projects everything is not so smooth, then you can act more iteratively. Enable the flag, and above all conflicts, add &lt;code&gt;@ts-ignore&lt;/code&gt; and a TODO comment. The next time you work with the file, correct the type as well.&lt;/p&gt;

&lt;p&gt;Setting --&lt;code&gt;strict&lt;/code&gt; to true, sets all of the following options to true:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;--&lt;em&gt;noImplicitAny&lt;/em&gt;: If TypeScript can’t infer a type, we must specify it. This mainly applies to parameters of functions and methods: With this settings, we must annotate them.&lt;/li&gt;
&lt;li&gt;--&lt;em&gt;noImplicitThis&lt;/em&gt;: Complain if the type of this isn’t clear.&lt;/li&gt;
&lt;li&gt;--&lt;em&gt;alwaysStrict&lt;/em&gt;: Use JavaScript’s strict mode whenever possible.&lt;/li&gt;
&lt;li&gt;--&lt;em&gt;strictNullChecks&lt;/em&gt;: null is not part of any type (other than its own type, null) and must be explicitly mentioned if it is a acceptable value.&lt;/li&gt;
&lt;li&gt;--&lt;em&gt;strictFunctionTypes&lt;/em&gt;: enables stronger checks for function types.&lt;/li&gt;
&lt;li&gt;--&lt;em&gt;strictPropertyInitialization&lt;/em&gt;: Properties in class definitions must be initialized, unless they can have the value undefined.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Use &lt;em&gt;Utility Types&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;TypeScript has a set of types that are shortcuts for conversions of other types.&lt;/p&gt;

&lt;p&gt;I advise you to study in detail all the official documentation on &lt;a href="https://www.typescriptlang.org/docs/handbook/utility-types.html"&gt;&lt;em&gt;Utility Types&lt;/em&gt;&lt;/a&gt; and start actively introducing them into your applications. They also save a lot of time.&lt;/p&gt;

&lt;h4&gt;
  
  
  From my point of view, most useful utility types are Pick and Omit, they allow you to avoid creating not essential intermediate types.
&lt;/h4&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;Pick&amp;lt;Type, Keys&amp;gt;&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type TodoPreview = Pick&amp;lt;Todo, "title" | "completed"&amp;gt;;

const todo: TodoPreview = {
  title: "Clean room",
  completed: false,
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;Omit&amp;lt;Type, Keys&amp;gt;&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Todo {
  title: string;
  description: string;
  completed: boolean;
  createdAt: number;
}

type TodoInfo = Omit&amp;lt;Todo, "completed" | "createdAt"&amp;gt;;

const todoInfo: TodoInfo = {
  title: "Pick up kids",
  description: "Kindergarten closes at 5pm",
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;These are just a few of the principles we use, but in our team, they are perhaps the most basic. Of course, this is not the only correct way to write code in TypeScript, but once we get used to it, we just write the code this way without thinking. From time to time, this saves us from unexpected tricky mistakes in large projects.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Best practices for file uploads in Nodejs and HTML</title>
      <dc:creator>Pavel Litkin</dc:creator>
      <pubDate>Wed, 21 Apr 2021 08:37:30 +0000</pubDate>
      <link>https://dev.to/bfunc/upload-files-easy-with-html5-and-nodejs-44fo</link>
      <guid>https://dev.to/bfunc/upload-files-easy-with-html5-and-nodejs-44fo</guid>
      <description>&lt;p&gt;Although it seems like uploading a file to the server is a simple task, there are many ways to do it and there are some pitfalls and edge cases, so the purpose of this article is to overview the whole process end to end and to take a closer look at each aspect.&lt;/p&gt;

&lt;p&gt;Let's begin from the&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating upload form
&lt;/h1&gt;

&lt;p&gt;To upload files to the server from the browser generally we need to create a html form. The most stupid simple example of the upload form that can be is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;form method="POST" enctype="multipart/form-data"&amp;gt;
  &amp;lt;input type="text" name="myText" /&amp;gt;
  &amp;lt;input type="file" name="myImage" /&amp;gt;
  &amp;lt;input type="submit" /&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works as is. &lt;strong&gt;No javascript needed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;However most likely we want something more sophisticated, for example if we are uploading images we may want to show preview thumbnails with a file size label or we may want to see a progress bar with pause/resume button or whatever else it may be.&lt;/p&gt;

&lt;p&gt;Possibly the most common requirement is to replace default html &lt;code&gt;&amp;lt;input type="file"&amp;gt;&lt;/code&gt; with nice dropzone area, there are javascript libs that can do that, but in reality you may not even need library, it can be done with simple input type="hidden" (to prevent that less-than-attractive user interface from being displayed). Because it is not affecting functionality we will skip form ui and styling here, there are plenty of good tutorials in the web (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications"&gt;MDN&lt;/a&gt;) on this topic.&lt;/p&gt;

&lt;p&gt;The html of basic upload form looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;form&amp;gt;
  &amp;lt;h4&amp;gt;Multipart from data upload example&amp;lt;/h4&amp;gt;
  &amp;lt;input id="text" type="text" name="myText" /&amp;gt;
  &amp;lt;input id="image" type="file" name="myImage" 
                                multiple accept="image/*" /&amp;gt;
  &amp;lt;input id="submit" type="submit" value="Upload" /&amp;gt;
  &amp;lt;hr /&amp;gt;
  &amp;lt;h4&amp;gt;Preview&amp;lt;/h4&amp;gt;
  &amp;lt;div id="preview"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Couple of interesting points here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; has &lt;em&gt;accept&lt;/em&gt; attribute that is handy to limit input from accepting undesired file types. Another &lt;em&gt;multiple&lt;/em&gt; attribute allows input to accept multiple files, omit it if you want to limit it to one (In this tutorial we will upload a single image).&lt;/li&gt;
&lt;li&gt;Example of text input here was added just for example, it may be handy to pass a caption with image in the same payload or some initial data that is needed to create an entry in db.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's add some javascript to bring form alive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;window.onload = function () {
  const submitButton = document.getElementById('submit')
  const imageInput = document.getElementById('image')
  const textInput = document.getElementById('text')
  const preview = document.getElementById('preview')

  submitButton.addEventListener('click', async e =&amp;gt; {
    e.preventDefault()

    const [file] = imageInput.files

    if (!file) {
      throw new Error('File was not selected')
    }

    // TODO - send file
  })
}

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

&lt;/div&gt;



&lt;p&gt;Nothing special, just some boring boilerplate to get values from inputs and register click handler for the submit button.&lt;/p&gt;

&lt;h2&gt;
  
  
  Select file
&lt;/h2&gt;

&lt;p&gt;To add some spice we can show preview for the image, when the user drops it into input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;imageInput.addEventListener('change', e =&amp;gt; {
  // we are taking only the first element
  // because we are doing single file upload
  const [file] = imageInput.files
  function updatePreviewImage(file){
    // TODO - update preview &amp;lt;img&amp;gt; src 
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when we have reference to the selected file we need to create a DOMString for &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag. There is browser interface method &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL"&gt;URL.createObjectURL()&lt;/a&gt; that can take underlying ArrayBuffer and create DOMString that represents the specified File object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function updatePreviewImage(file) {
  const url = URL.createObjectURL(file)
  preview.innerHTML = `&amp;lt;img src="${url}" /&amp;gt;`
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s take a look on &lt;code&gt;src&lt;/code&gt; attribute of appeared &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag:&lt;br&gt;
&lt;code&gt;&amp;lt;img src="blob:http://localhost:3000/1b2a4ac9-4bd4-4726-b302-d74e6ed2ba48"&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As you can see, url of page where our html is hosted is part of DOMString, if page will be opened with &lt;code&gt;file:///&lt;/code&gt; protocol and not being hosted, then DOMString will work but look like this:&lt;br&gt;
&lt;code&gt;&amp;lt;img src="blob:null/f8111cf8-d598-4305-9bdd-4ba5b7db22f7"&amp;gt;&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This illustrates that URL lifetime is tied to the document in the window on which it was created. That means that we have to release an object URL, by calling &lt;code&gt;revokeObjectURL()&lt;/code&gt; after the form submission.&lt;/p&gt;
&lt;h2&gt;
  
  
  Building FormData
&lt;/h2&gt;

&lt;p&gt;Building FormData is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const formData = new FormData()
formData.append('myImage', file)
formData.append('myText', textInput.value || 'default text')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;First parameter is the name of the property in the &lt;code&gt;request.body&lt;/code&gt; object when we will get a request later on server.&lt;/li&gt;
&lt;li&gt;Second is the value and there is an optional third parameter that may hold the original filename of the Blob object if we are sending Blob.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Adding file as a Blob
&lt;/h3&gt;

&lt;p&gt;Sometimes we need to upload files that are not images, like 3d models, audio records or any other binary file format. In some cases it may be useful to treat them as Blobs, example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [file] = imageInput.files
const arrayBuffer = await file.arrayBuffer()
const myBlob = new Blob([new Uint8Array(arrayBuffer)], {
  type: file.type,
})
formData.append('myBlob', myBlob, file.name)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sending FormData to server
&lt;/h3&gt;

&lt;p&gt;We can send data to server with simple &lt;code&gt;fetch&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await fetch(uploadUrl, {
  method: 'POST',
  body: formData,
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is small pitfall however:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Warning: When using FormData to submit POST requests using XMLHttpRequest or the Fetch_API with the multipart/form-data Content-Type (e.g. when uploading Files and Blobs to the server), &lt;em&gt;do not explicitly set the Content-Type header on the request&lt;/em&gt;. Doing so will prevent the browser from being able to set the Content-Type header with the boundary expression it will use to delimit form fields in the request body.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Open DevTools and take a look on request headers, you will see that browser automatically adds &lt;code&gt;Content-Type: multipart/form-data&lt;/code&gt; and then it appends random &lt;code&gt;boundary&lt;/code&gt; value that is used to separate parts of form-data&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Content-Type:
  multipart/form-data; boundary=---WebKitFormBoundaryrHPgSrtbIrJmn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Display progress bar
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Unfortunately currently it is not possible to get file upload progress for &lt;code&gt;fetch()&lt;/code&gt; method &lt;a href="https://www.chromestatus.com/features/5274139738767360"&gt;chromestatus.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Solution for now is to use good ol' fella &lt;code&gt;XMLHttpRequest&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let request = new XMLHttpRequest()
request.open('POST', '/upload')

// upload progress event
request.upload.addEventListener('progress', function (e) {
  // upload progress as percentage
  console.log((e.loaded / e.total) * 100) 
})

// request finished event
request.addEventListener('load', function (e) {
  // HTTP status message (200, 404 etc)
  console.log(request.status)
})

// send POST request to server
request.send(formData)

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Server side
&lt;/h1&gt;

&lt;p&gt;Before we dive into the code let's stop and think for a while.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Do we need to store files on the server? &lt;/li&gt;
&lt;li&gt;  What exactly has to be done with files on the server, is there any part of that responsibility that can be passed to third-party tools?&lt;/li&gt;
&lt;li&gt;  Can move files to external storage like AWS S3 or Azure Blob Storage without temporarily saving them on the server?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Libraries for processing file uploads
&lt;/h2&gt;

&lt;p&gt;To process uploaded files we need a library that knows how to do it in an efficient and secure way. There is good comparison article on this (link at the bottom of the page).&lt;/p&gt;

&lt;p&gt;We gonna stick with &lt;a href="https://github.com/mscdex/busboy"&gt;busboy&lt;/a&gt; becasue it is considered the most production stable solution (other libraries using it under the hood) and becasue it do not creates temporary files.&lt;/p&gt;

&lt;p&gt;If we do need to save files occasionally, we can stream file contents to disk like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const imageBuffer = req.raw.files['myImage'].data;
  const fileName = getRandomFileName();
  const stream = fs.createWriteStream(fileName);
  stream.once('open', function (fd) {
    stream.write(imageBuffer);
    stream.end();
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or we can can take &lt;a href="https://www.npmjs.com/package/multer"&gt;multer&lt;/a&gt; library that is based on &lt;code&gt;busboy&lt;/code&gt; too and it has option to automatically save files on disk upon receiving.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web Framework
&lt;/h2&gt;

&lt;p&gt;In this tutorial we will use a web framework, despite the fact that we do not need a web framework to receive uploaded files.&lt;/p&gt;

&lt;p&gt;Why? It’s because in real projects, almost always we do need a web framework, unless we are doing something very specific, so we want to know how to properly tie our library with the framework.&lt;/p&gt;

&lt;p&gt;Official Fastify plugin for uploading files is &lt;a href="https://github.com/huangang/fastify-file-upload"&gt;fastify-file-upload&lt;/a&gt;, if will take a closer look at it’s repo, we will see that is it nothing more than a wrapper around another library &lt;a href="https://www.npmjs.com/package/express-fileupload"&gt;express-fileupload&lt;/a&gt;, that is by itself a wrapper around &lt;a href="https://github.com/mscdex/busboy"&gt;busboy&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;So for Fastify we gonna use &lt;code&gt;fastify-file-upload&lt;/code&gt; and for Express &lt;code&gt;express-fileupload&lt;/code&gt;. Using wrapper is convinient for example, you may define validation schema for formdata, but we use &lt;code&gt;busboy&lt;/code&gt; directly without wrapper too. Let's write our own wrapper around &lt;code&gt;busboy&lt;/code&gt; library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing Fastify wrapper for busboy
&lt;/h3&gt;

&lt;p&gt;Writing a wrapper is really simple task, there is only one tiny thing that Fastify out of the box supports only the &lt;code&gt;application/json&lt;/code&gt; context-type, so we need to define our parser for &lt;code&gt;multipart/form-data&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fastify.addContentTypeParser('multipart/form-data', function (request, payload, done) {
  done(err, payload)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fasity exposes original nodejs request and response under &lt;code&gt;request.raw&lt;/code&gt; and &lt;code&gt;reply.raw&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fastify.post('/upload', function (request, reply) {
  const req = request.raw
  const res = reply.raw
  // TODO - copy paste code from busboy example as is, 
  // example: new Busboy({ headers: req.headers }) ...
  // full example in the demo repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;We just put some code in route handler, and it works, but this is not the right approach, Fastify gives us much cleaner was to do it, to register our hander as a &lt;a href="https://www.fastify.io/docs/master/Plugins/"&gt;plugin&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Blobs
&lt;/h3&gt;

&lt;p&gt;There is nothing special in receiving Blobs, the same server code works as is, the only difference is that it may be missing original filename if it was not provided as third parameter to &lt;code&gt;formData.append&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Security
&lt;/h1&gt;

&lt;p&gt;It is important to know that there are many types of vulnerabilities that may be exploited if there is a bug in the processing buffers, more information &lt;a href="https://snyk.io/blog/exploiting-buffer/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It is considered a good practice to take out upload endpoints to separate microservice that will have an additional layer of security.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Secure file uploads rules
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Always create a new unique filename, never use one provided by a client, because it may intentionally include paths to critical system files on the server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Never host uploaded files from the same document root, better to host them on totally different machines in different networks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any file may be malicious, extension doesn’t mean anything, it is better to perform some third-party malware scan if it is possible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep control of permissions, files should not be executable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Authenticate file uploads, limit number of uploaded files per session, limit file size range&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Link to example repository
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/bfunc/file-upload-example"&gt;https://github.com/bfunc/file-upload-example&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Further reading
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Guide on &lt;a href="[https://medium.com/@vecera.petr/how-to-handle-large-file-upload-with-nodejs-express-server-7de9ab3f7af1](http://vecera.petr/how-to-handle-large-file-upload-with-nodejs-express-server](https://medium.com/@vecera.petr/how-to-handle-large-file-upload-with-nodejs-express-server-7de9ab3f7af1))"&gt;how to manage upload of large files&lt;/a&gt; (more than 512mb)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Good post about &lt;a href="https://bytearcher.com/articles/formidable-vs-busboy-vs-multer-vs-multiparty/"&gt;differences in libraries for processing file uploads&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>html</category>
    </item>
  </channel>
</rss>
