<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>LoopBack Blog</title>
        <link>https://loopback.io/blog</link>
        <description>LoopBack Blog</description>
        <lastBuildDate>Tue, 10 Oct 2023 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Happy 5th Birthday LoopBack 4!]]></title>
            <link>https://loopback.io/blog/happy-5th-bday</link>
            <guid>https://loopback.io/blog/happy-5th-bday</guid>
            <pubDate>Tue, 10 Oct 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Can you believe it's been 5 years that LoopBack 4 GA was announced at Node+JS Interactive conference?]]></description>
            <content:encoded><![CDATA[<p>Can you believe it's been 5 years that LoopBack 4 GA was <a href="https://strongloop.com/strongblog/loopback-4-ga" target="_blank" rel="noopener noreferrer" class="">announced</a> at Node+JS Interactive conference?</p>
<p><img decoding="async" loading="lazy" alt="Happy birthday LoopBack" src="https://loopback.io/blog/assets/images/bday-0ff7a81f833c0ae2f86583db8b7d6a95.jpg" width="5184" height="3456" class="img_ev3q"><span style="font-size:0.4em;text-align:center"><i>Photo by <a href="https://unsplash.com/@socialcut?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">S O C I A L . C U T</a> on <a href="https://unsplash.com/photos/ww8hljWABIE?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></i></span></p>
<p>Since then, the framework has gained stability and has gained users substantially. We also see more contributions from the community not only to the core framework, but also building extensions. Thank you for all your contributions to LoopBack and the <a href="https://www.npmjs.com/search?q=loopback-extension" target="_blank" rel="noopener noreferrer" class="">160+ extensions published on npmjs.com</a>!</p>
<p>To continue moving towards an open governace model, it's exciting to see LoopBack <a href="https://openjsf.org/blog/2021/06/02/loopback-joins-openjs-foundation-as-new-incubating-project/" target="_blank" rel="noopener noreferrer" class="">joined the OpenJS foundation as the incubating project</a> in 2021 and <a href="https://openjsf.org/blog/2022/04/25/node-js-framework-loopback-graduates-to-at-large-project-at-openjs-foundation/" target="_blank" rel="noopener noreferrer" class="">graduated to at-large project</a> the following year.</p>
<p>Lastly, don't forget that <a href="https://hacktoberfest.com/" target="_blank" rel="noopener noreferrer" class="">HacktoberFest</a> is on this month. No matter you're a new developer to LoopBack or seasoned contributors, your contributions are always welcomed!</p>]]></content:encoded>
            <category>Meta</category>
        </item>
        <item>
            <title><![CDATA[New Home for the LoopBack Blog]]></title>
            <link>https://loopback.io/blog/new-home-for-the-loopback-blog</link>
            <guid>https://loopback.io/blog/new-home-for-the-loopback-blog</guid>
            <pubDate>Wed, 13 Apr 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[After a long hiatus, the LoopBack Blog has gotten a new home! Learn how it came]]></description>
            <content:encoded><![CDATA[<p>After a long hiatus, the LoopBack Blog has gotten a new home! Learn how it came
to be and how we managed to modernise blogging stack along the way.</p>
<p>As part of the planning for LoopBack moving to OpenJS Foundation, there have
been discussions around finding a new home for the blog, parting from the
strongloop.com web site. A few alternatives had brought up, such as having the
blog posts as part of the loopback.io repo, using a third party blog site and
creating a blog site in a separate repo.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="coming-up-with-a-plan">Coming Up With a Plan<a href="https://loopback.io/blog/new-home-for-the-loopback-blog#coming-up-with-a-plan" class="hash-link" aria-label="Direct link to Coming Up With a Plan" title="Direct link to Coming Up With a Plan" translate="no">​</a></h2>
<p>Putting the blog posts in the loopback.io repo is a natural progression, since
all the documentation and text-based content will be in the same repo. The
concern is that is Jekyll-based. Although it worked fine and integrated well
with GitHub Pages, many of the maintainers were not well-versed in the world of
Ruby. This was compounded by shell scripts that pulled data from other Git
Repositories and modified the site as part of the build process. Hence, a lot of
time was spent trying to understand how the website was put together and
figuring out the best way to tweak it to integrate the new blog.</p>
<p>The "Strong Blog" was also written with Jekyll and hosted on GitHub Pages. Hence
lifting and shifting was a real possibility that we contemplated. However,
the slow build times and the maintainers' unfamiliarity with Ruby and Jekyll
meant that we realised that the website's current stack wasn't worth keeping
around in the long run. At the same time, performing a full migration of the
website, documentation, and blog in one go was too daunting of a task for the
maintainers who were already working on the project on their own time.</p>
<p>The idea of using a third-party service such as <a href="https://www.medium.com/" target="_blank" rel="noopener noreferrer" class="">Medium</a>
was also considered. However utlimately, the lack of control over the interface,
the inability to place it in the same domain name as the main website and
documentation, and the frustration that stem from a reader being forced to use
a third-party service meant that it was quickly off the table.</p>
<p>As a result, we decided to come to a compromise.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="picking-a-blogging-stack">Picking A Blogging Stack<a href="https://loopback.io/blog/new-home-for-the-loopback-blog#picking-a-blogging-stack" class="hash-link" aria-label="Direct link to Picking A Blogging Stack" title="Direct link to Picking A Blogging Stack" translate="no">​</a></h2>
<p>After some deliberation we decided to create a hybrid stack which left the
website and documentation with Jekyll, and use
<a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docosaurus 2</a> as the new blogging platform. We found
Docusaurus to be a good fit as it is a Facebook-maintained open source project
which was written on top of React. Besides its benefit of speedy build times,
this JavaScript-based stack provides more opportunities for extensibility and a
reduced barrier for contributing and tweaking. The first-class support for MDX
was also a plus as it meant we were able to copy over most of our posts with
only a few tweaks, and the ability to generate the blog as build artifacts made
it compatible with the Jamstack-eque system of GitHub Pages.</p>
<p>Thanks to the amazing work done by <a href="https://github.com/dhmlau" target="_blank" rel="noopener noreferrer" class="">Diana</a>, all of
the LoopBack 4 blog posts from 2019 and 2020 were migrated to Docusaurus. With
her work, we were able to quickly build and see the new blog coming together
with all of the past blog posts populating the blog.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="merging-jekyll-and-docusaurus">Merging Jekyll and Docusaurus<a href="https://loopback.io/blog/new-home-for-the-loopback-blog#merging-jekyll-and-docusaurus" class="hash-link" aria-label="Direct link to Merging Jekyll and Docusaurus" title="Direct link to Merging Jekyll and Docusaurus" translate="no">​</a></h2>
<p>When we started building the blog, we hosted it on GitHub Pages in its own Git
Repository and served it in its own sub-domain. This allowed us to quickly build
and patch any bugs that may have cropped up. However the end-goal was to host it
under the same domain as the main website and documentation:
<a href="https://loopback.io/blog" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/blog</a>. Hence, we had to create a solution which merged the
new blog with the exsitng website codebase.</p>
<p>This solution? A shell script!</p>
<p>Since we already had a precedence for using shell scripts to pull in data from
other Git Repositories, I've decided to write one to do the same thing, but this
time, specifically for the blog. This script clones the
<a href="https://github.com/loopbackio/loopback-blog" target="_blank" rel="noopener noreferrer" class=""><code>loopbackio/loopback-blog</code> Git Repository</a>,
generates the blog's build artifacts, and copies it over to the <code>blog</code> directory
of the Jekyll website. There's additional logic in there to make it more
fool-proof and less verbose but in essence, that was what it did - Clone, build,
and copy. You can also view the
<a href="https://github.com/loopbackio/loopback.io/blob/8968cd6860c09a852ee4fd9ce07c7a1db3ce7771/update-blog.sh" target="_blank" rel="noopener noreferrer" class="">source code</a>
yourself if you'd like to see how it was done. Over time, we hope to refine this
further and make it more reliable, such as using Git Submodules instead of a
clean clone on every build.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="future-work">Future Work<a href="https://loopback.io/blog/new-home-for-the-loopback-blog#future-work" class="hash-link" aria-label="Direct link to Future Work" title="Direct link to Future Work" translate="no">​</a></h2>
<p>As it stands, we now have a blog that all of the maintainers can now contribute
to. With this change, we now have revived a new way for us, the maintianers, to
engage with our community and we hope that the blog posts can complement the
existing documentation and community channels such as Slack, GitHub
Discussions, and the mailing list.</p>
<p>This is just the first step in modernising our website stack. There's still
plenty of work to do, and it's our vision to fully migrate our stack to one
powered by the JavaScript ecosystem.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="upcoming-blog-series-maintainers-testimonial">Upcoming Blog Series: Maintainers' Testimonial<a href="https://loopback.io/blog/new-home-for-the-loopback-blog#upcoming-blog-series-maintainers-testimonial" class="hash-link" aria-label="Direct link to Upcoming Blog Series: Maintainers' Testimonial" title="Direct link to Upcoming Blog Series: Maintainers' Testimonial" translate="no">​</a></h2>
<p>With the launch of our new blog, we're excited to announce an upcoming blog
series where the maintainers can share their expriences and journey in adopting
LoopBack 4. Through this series, we hope to share with the community the unique
perspectives of those who work closely on LoopBack 4, not only as users but as
maintainers as well.</p>
<p>Don't miss out on future blog posts by subscribing to our
<a href="https://loopback.io/blog/rss.xml" target="_blank" rel="noopener noreferrer" class="">RSS</a> or
<a href="https://loopback.io/blog/atom.xml" target="_blank" rel="noopener noreferrer" class="">Atom</a> feeds which contain the full articles.</p>]]></content:encoded>
            <category>Meta</category>
        </item>
        <item>
            <title><![CDATA[LoopBack 4 November 2020 Milestone Update]]></title>
            <link>https://loopback.io/blog/november-2020-milestone</link>
            <guid>https://loopback.io/blog/november-2020-milestone</guid>
            <pubDate>Tue, 08 Dec 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>Hope you had a wonderful Thanksgiving for those who celebrate it! In November, LoopBack team focused on improving the context module and documentation, as well as bug fixes. The Toronto squad participated in the <a href="https://www-01.ibm.com/ibm/cas/cascon/" target="_blank" rel="noopener noreferrer" class="">CASCONxEVOKE</a> conference. Instead of a physical booth, we held a virtual one online. We welcomed <a href="https://github.com/nflaig" target="_blank" rel="noopener noreferrer" class="">@nflaig</a> as the new maintainer of <a href="https://github.com/strongloop/loopback-next" target="_blank" rel="noopener noreferrer" class=""><code>loopback-next</code></a>.</p>
<p>Read more to know about the highlighted improvements:</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="context">Context<a href="https://loopback.io/blog/november-2020-milestone#context" class="hash-link" aria-label="Direct link to Context" title="Direct link to Context" translate="no">​</a></h2>
<ul>
<li class="">
<p>A new phase <code>init()</code> was added to the application life cycle events. It is used when a component need to contribute bindings asynchronously. For example:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">MyComponent</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">Component</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> LifeCycleObserver </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Contribute bindings via `init`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// This cannot be done via constructor since it's synchronous.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> val </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">readFromConfig</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">bind</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'abc'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">to</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">val</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">status </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'initialized'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">initialized </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>You can check the <a href="https://loopback.io/doc/en/lb4/Component.html#component-life-cycle" target="_blank" rel="noopener noreferrer" class="">Component</a> page to learn about its usage.</p>
</li>
<li class="">
<p><code>toInjectable()</code> was introduced as a shortcut to decorate a common/provider/dynamic-value-factory class and automatically creating binding for them. For example:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">injectable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">scope</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> BindingScope</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">SINGLETON</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">MyController</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">inject</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'my-options'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> options</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> MyOptions</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">binding</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">toInjectable</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">MyController</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>The decorator's usage is well documented on page <a href="https://loopback.io/doc/en/lb4/Binding.html#an-injectable-class" target="_blank" rel="noopener noreferrer" class="">Binding</a>.</p>
</li>
<li class="">
<p>PR <a href="https://github.com/strongloop/loopback-next/pull/6701" target="_blank" rel="noopener noreferrer" class="">#6701</a> updated test cases to reflect how the design types of array/undefined/complex properties are retrieved.</p>
</li>
<li class="">
<p>Method injection is allowed for the lifecycle methods in PR <a href="https://github.com/strongloop/loopback-next/pull/6740" target="_blank" rel="noopener noreferrer" class="">#6740</a>. For example:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">MyObserverWithMethodInjection</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">implements</span><span class="token plain"> </span><span class="token class-name">LifeCycleObserver</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  status </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'not-initialized'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">init</span><span class="token punctuation" style="color:#393A34">(</span><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">inject</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'prefix'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> prefix</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">status </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">prefix</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string string" style="color:#e3116c">:initialized</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">inject</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'prefix'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> prefix</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">status </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">prefix</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string string" style="color:#e3116c">:started</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">stop</span><span class="token punctuation" style="color:#393A34">(</span><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">inject</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'prefix'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> prefix</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">status </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">prefix</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string string" style="color:#e3116c">:stopped</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
</li>
<li class="">
<p>In some cases, your Express middleware wants to access LoopBack's RequestContext to resolve certain bindings. This can be done via <code>MIDDLEWARE_CONTEXT</code> property of the Express request object, which is set up by LoopBack when the <code>RequestContext</code> is instantiated. For example:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token constant" style="color:#36acaa">MIDDLEWARE_CONTEXT</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> RequestContext</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@loopback/rest'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">expressHandler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">req</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> res</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> next</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> reqCtx </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">req </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token builtin">any</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token constant" style="color:#36acaa">MIDDLEWARE_CONTEXT</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// Now you have access to the LoopBack RequestContext</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="documentation">Documentation<a href="https://loopback.io/blog/november-2020-milestone#documentation" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h2>
<ul>
<li class="">
<p>The guide for calling REST APIs and SOAP services were separated to make the steps involved clearer. You can check the overview page <a href="https://loopback.io/doc/en/lb4/Accessing-services.html" target="_blank" rel="noopener noreferrer" class="">Accessing services</a> and its sub-topics <a href="https://loopback.io/doc/en/lb4/Calling-soap-web-services.html" target="_blank" rel="noopener noreferrer" class="">Calling SOAP web services</a> and <a href="https://loopback.io/doc/en/lb4/Calling-rest-apis.html" target="_blank" rel="noopener noreferrer" class="">Calling REST APIs</a> for details.</p>
</li>
<li class="">
<p>For troubleshooting, we added steps for creating breakpoints in vscode in the <a href="https://loopback.io/doc/en/lb4/Troubleshooting.html#creating-breakpoints" target="_blank" rel="noopener noreferrer" class="">documentation</a>. You can find more details in PR <a href="https://github.com/strongloop/loopback-next/pull/6743" target="_blank" rel="noopener noreferrer" class="">#6743</a>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rest">REST<a href="https://loopback.io/blog/november-2020-milestone#rest" class="hash-link" aria-label="Direct link to REST" title="Direct link to REST" translate="no">​</a></h2>
<ul>
<li class="">Matching a URL or hostname against a regular expression that contains an unescaped dot as part of the hostname might match more hostnames than expected. PR <a href="https://github.com/strongloop/loopback-next/pull/6813" target="_blank" rel="noopener noreferrer" class="">#6813</a> updated the regular expression of hostnames accordingly.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="repository">Repository<a href="https://loopback.io/blog/november-2020-milestone#repository" class="hash-link" aria-label="Direct link to Repository" title="Direct link to Repository" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://github.com/strongloop/loopback-next/pull/6755" target="_blank" rel="noopener noreferrer" class="">#6755</a> threw 400 <code>BadRequestError</code> for invalid inclusion relation name by rejecting the request with statusCode as 400.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="examples">Examples<a href="https://loopback.io/blog/november-2020-milestone#examples" class="hash-link" aria-label="Direct link to Examples" title="Direct link to Examples" translate="no">​</a></h2>
<ul>
<li class="">PR <a href="https://github.com/strongloop/loopback-next/pull/6598" target="_blank" rel="noopener noreferrer" class="">#6598</a> updated artifacts of the <a href="https://github.com/strongloop/loopback-next/tree/master/examples/todo-list" target="_blank" rel="noopener noreferrer" class="">todo-list</a> example to the latest style generated by the LoopBack CLI.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="enriching-loopback-and-its-community---you-are-invited">Enriching LoopBack and its Community - You are Invited!<a href="https://loopback.io/blog/november-2020-milestone#enriching-loopback-and-its-community---you-are-invited" class="hash-link" aria-label="Direct link to Enriching LoopBack and its Community - You are Invited!" title="Direct link to Enriching LoopBack and its Community - You are Invited!" translate="no">​</a></h2>
<p>As mentioned in our <a href="https://strongloop.com/strongblog/2020-community-contribution/" target="_blank" rel="noopener noreferrer" class="">recent blog post</a>, your contribution is important to make LoopBack a sustainable open source project.</p>
<p>Here is what you can do:</p>
<ul>
<li class=""><a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Join LoopBack Slack community</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22" target="_blank" rel="noopener noreferrer" class="">Look for first-contribution-friendly issues</a></li>
<li class="">Give us feedback and join our discussion in <a href="https://github.com/strongloop/loopback-next" target="_blank" rel="noopener noreferrer" class="">our GitHub repo</a></li>
</ul>
<p>Let's make LoopBack a better framework together!</p>]]></content:encoded>
            <category>Milestone update</category>
        </item>
        <item>
            <title><![CDATA[LoopBack 4 October 2020 Milestone Update]]></title>
            <link>https://loopback.io/blog/october-2020-milestone</link>
            <guid>https://loopback.io/blog/october-2020-milestone</guid>
            <pubDate>Thu, 05 Nov 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>In October, we were excited to see an increasing number of community contributions as people joined the <a href="https://strongloop.com/strongblog/2020-hacktoberfest/" target="_blank" rel="noopener noreferrer" class="">Hacktoberfest</a> event. This month we had pretty balanced improvements in each area of the framework, including context, health check, OpenAPI specification and documentations. Keep reading to learn about the recently added features!</p>
<p>We welcomed <a href="https://github.com/mrmodise" target="_blank" rel="noopener noreferrer" class="">@mrmodise</a> as the maintainer of <a href="https://github.com/strongloop/loopback4-example-shopping" target="_blank" rel="noopener noreferrer" class=""><code>loopback4-shopping-example</code></a>. And we'd like to thank everyone <a href="https://github.com/nflaig" target="_blank" rel="noopener noreferrer" class="">@nflaig</a>, <a href="https://github.com/MattiaPrimavera" target="_blank" rel="noopener noreferrer" class="">@MattiaPrimavera</a>, <a href="https://github.com/mdbetancourt" target="_blank" rel="noopener noreferrer" class="">@mdbetancourt</a>, <a href="https://github.com/mrmodise" target="_blank" rel="noopener noreferrer" class="">@mrmodise</a>, <a href="https://github.com/frbuceta" target="_blank" rel="noopener noreferrer" class="">@frbuceta</a>, <a href="https://github.com/HrithikMittal" target="_blank" rel="noopener noreferrer" class="">@HrithikMittal</a>, <a href="https://github.com/simlt" target="_blank" rel="noopener noreferrer" class="">@simlt</a>, <a href="https://github.com/hectorleiva" target="_blank" rel="noopener noreferrer" class="">@hectorleiva</a>, <a href="https://github.com/pktippa" target="_blank" rel="noopener noreferrer" class="">@pktippa</a>, <a href="https://github.com/VergilSkye" target="_blank" rel="noopener noreferrer" class="">@VergilSkye</a>, <a href="https://github.com/kerolloz" target="_blank" rel="noopener noreferrer" class="">@kerolloz</a>, <a href="https://github.com/arondn2" target="_blank" rel="noopener noreferrer" class="">@arondn2</a>, <a href="https://github.com/mayank-SFIN571" target="_blank" rel="noopener noreferrer" class="">@mayank-SFIN571</a> for your contributions in October!</p>
<p>Here are the highlighted improvements:</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="context">Context<a href="https://loopback.io/blog/october-2020-milestone#context" class="hash-link" aria-label="Direct link to Context" title="Direct link to Context" translate="no">​</a></h2>
<ul>
<li class="">A set of fine-grained scopes <code>APPLICATION</code>, <code>SERVER</code> and <code>REQUEST</code> has been introduced to allow better
scoping of binding resolutions. The limitation of the previous scopes is explained in section <a href="https://loopback.io/doc/en/lb4/Binding.html#choose-the-right-scope" target="_blank" rel="noopener noreferrer" class="">choose the right scope</a>, and section <a href="https://loopback.io/doc/en/lb4/Binding.html#resolve-a-binding-value-by-key-and-scope-within-a-context-hierarchy" target="_blank" rel="noopener noreferrer" class="">resolve a binding value by key and scope within a context hierarchy</a> explains how different scopes determine the binding resolutions.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rest">REST<a href="https://loopback.io/blog/october-2020-milestone#rest" class="hash-link" aria-label="Direct link to REST" title="Direct link to REST" translate="no">​</a></h2>
<ul>
<li class="">
<p>Allowed array query parameter for a single value, like <code>{tags: 'hello'}</code> where parameter <code>tags</code> is a string array. See PR <a href="https://github.com/strongloop/loopback-next/pull/6542" target="_blank" rel="noopener noreferrer" class="">#6542</a>.</p>
</li>
<li class="">
<p>Supported property level configuration for hidden fields, like <code>@property({type: 'string', hidden: true}) password: string</code>. This is the shortcut for specifying the hidden properties in model settings. See PR <a href="https://github.com/strongloop/loopback-next/pull/6484" target="_blank" rel="noopener noreferrer" class="">#6484</a>.</p>
</li>
<li class="">
<p><code>save()</code> method throwing error due to missing <code>idName</code> is fixed in PR <a href="https://github.com/strongloop/loopback-next/pull/6640" target="_blank" rel="noopener noreferrer" class="">#6640</a>.</p>
</li>
<li class="">
<p><code>modifySpec()</code> turns to an async function to allow async spec updates. See PR <a href="https://github.com/strongloop/loopback-next/pull/6655" target="_blank" rel="noopener noreferrer" class="">#6655</a>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="build">Build<a href="https://loopback.io/blog/october-2020-milestone#build" class="hash-link" aria-label="Direct link to Build" title="Direct link to Build" translate="no">​</a></h2>
<ul>
<li class="">
<p>A force clean rebuild was added to the pre-start script for the LoopBack 4 examples. You can run <code>npm start</code> after removing artifacts without manually cleaning the <code>/dist</code> files. See PR <a href="https://github.com/strongloop/loopback-next/pull/6588" target="_blank" rel="noopener noreferrer" class="">#6588</a>.</p>
</li>
<li class="">
<p>Turned on <code>exit</code> for mocha tests for the created LoopBack applications. See PR <a href="https://github.com/strongloop/loopback-next/pull/6475" target="_blank" rel="noopener noreferrer" class="">#6475</a>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="extensions">Extensions<a href="https://loopback.io/blog/october-2020-milestone#extensions" class="hash-link" aria-label="Direct link to Extensions" title="Direct link to Extensions" translate="no">​</a></h2>
<ul>
<li class="">
<p>Module <a href="https://github.com/strongloop/loopback-next/tree/master/extensions/socketio" target="_blank" rel="noopener noreferrer" class="">@loopback/socketio</a> was added to use socket.io to expose controllers as WebSocket friendly endpoints.</p>
</li>
<li class="">
<p>Enable/disable the metrics endpoints in explorer when mounting the metric and health extensions. See PR <a href="https://github.com/strongloop/loopback-next/pull/6646" target="_blank" rel="noopener noreferrer" class="">#6646</a> and PR <a href="https://github.com/strongloop/loopback-next/pull/6645" target="_blank" rel="noopener noreferrer" class="">#6645</a>.</p>
</li>
<li class="">
<p>Only add <code>MetricsObserver</code>, <code>MetricsPushObserver</code> and expose <code>/metrics</code> endpoints when they are enabled. See PR <a href="https://github.com/strongloop/loopback-next/pull/6644" target="_blank" rel="noopener noreferrer" class="">#6644</a>.</p>
</li>
<li class="">
<p>The health check for applications running in container now returns a more accurate HTTP status code based on the state. For example, checking <code>/health</code> for application in states 'STARTING', 'STOPPING' or 'STOPPED' returns 503. You can find more details in PR <a href="https://github.com/strongloop/loopback-next/pull/6648" target="_blank" rel="noopener noreferrer" class="">#6648</a>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="documentation-restructure">Documentation Restructure<a href="https://loopback.io/blog/october-2020-milestone#documentation-restructure" class="hash-link" aria-label="Direct link to Documentation Restructure" title="Direct link to Documentation Restructure" translate="no">​</a></h2>
<ul>
<li class="">
<p>LoopBack 4 targets both API developers and extension developers, while the current website doesn't distinguish them clearly. This month we restructured the sidebar to classify the documentation into two parts: "Building LoopBack Applications" and "Extending LoopBack Framework". You can check <a href="https://loopback.io/doc/en/lb4/Customizing-server-configuration.html" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/lb4/Customizing-server-configuration.html</a> to view the new layout.</p>
</li>
<li class="">
<p>The instructions for implementing HTTP redirects and mounting an Express router are extracted into a standalone page under "How-to guides". You can check <a href="https://loopback.io/doc/en/lb4/Customizing-routes.html" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/lb4/Customizing-routes.html</a> to view the content.</p>
</li>
<li class="">
<p>Moved server recipes to how-to guides <a href="https://loopback.io/doc/en/lb4/Customizing-server-configuration.html" target="_blank" rel="noopener noreferrer" class="">Customizing-server-configuration</a>. See PR <a href="https://github.com/strongloop/loopback-next/pull/6663" target="_blank" rel="noopener noreferrer" class="">#6663</a>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="examples">Examples<a href="https://loopback.io/blog/october-2020-milestone#examples" class="hash-link" aria-label="Direct link to Examples" title="Direct link to Examples" translate="no">​</a></h2>
<p>Two examples were added last month:</p>
<ul>
<li class="">
<p>Example <a href="https://github.com/strongloop/loopback-next/tree/master/examples/webpack" target="_blank" rel="noopener noreferrer" class="">webpack</a> was added to demo LoopBack running inside the browser as client-side JavaScript application.</p>
</li>
<li class="">
<p>Example <a href="https://github.com/strongloop/loopback-next/tree/master/examples/socketio" target="_blank" rel="noopener noreferrer" class="">socketio</a> gives a basic implementation of socketio with LoopBack 4.</p>
</li>
</ul>
<p>You can also download the examples by using the <code>lb4 example</code> command.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="enriching-loopback-and-its-community---you-are-invited">Enriching LoopBack and its Community - You are Invited!<a href="https://loopback.io/blog/october-2020-milestone#enriching-loopback-and-its-community---you-are-invited" class="hash-link" aria-label="Direct link to Enriching LoopBack and its Community - You are Invited!" title="Direct link to Enriching LoopBack and its Community - You are Invited!" translate="no">​</a></h2>
<p>As mentioned in our <a href="https://strongloop.com/strongblog/2020-community-contribution/" target="_blank" rel="noopener noreferrer" class="">recent blog post</a>, your contribution is important to make LoopBack a sustainable open source project.</p>
<p>Here is what you can do:</p>
<ul>
<li class=""><a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Join LoopBack Slack community</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22" target="_blank" rel="noopener noreferrer" class="">Look for first-contribution-friendly issues</a></li>
<li class="">Give us feedback and join our discussion in <a href="https://github.com/strongloop/loopback-next" target="_blank" rel="noopener noreferrer" class="">our GitHub repo</a></li>
</ul>
<p>Let's make LoopBack a better framework together!</p>]]></content:encoded>
            <category>Milestone update</category>
        </item>
        <item>
            <title><![CDATA[Community Q&A Monthly Digest - Oct 2020]]></title>
            <link>https://loopback.io/blog/2020-oct-slack-qa</link>
            <guid>https://loopback.io/blog/2020-oct-slack-qa</guid>
            <pubDate>Wed, 28 Oct 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>It's been 6 months since we created the <a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Slack channel</a> for LoopBack community. Thanks to your support, over 500 members had joined and new members are joining almost everyday! Let's take a look at the October edition of the “Community Q&amp;A Monthly Digest”, capturing some of the Q&amp;A in this forum.</p>
<hr>
<p><strong>Question:</strong> How to get the raw request in LoopBack 4 in a function without changing the parsing for the entire app?</p>
<p><strong>Answer:</strong>
It's possible to get the raw request body with <code>x-parser</code>: <a href="https://loopback.io/doc/en/lb4/Parsing-requests.html#extend-request-body-parsing" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/lb4/Parsing-requests.html#extend-request-body-parsing</a>.
-- <em>Answered by @Rifa Achrinza</em></p>
<hr>
<p><strong>Question:</strong> Is there any solution for tracking database migration, for example, migrations has been already run and possible rollback of migration?</p>
<p><strong>Answer:</strong>
I created a module which tracks migrations and executes scripts based on the db version compared to the app version, see <a href="https://www.npmjs.com/package/loopback4-migration" target="_blank" rel="noopener noreferrer" class="">https://www.npmjs.com/package/loopback4-migration</a>.
--<em>Answered by @nflaig</em></p>
<p>Ideally, LoopBack generates the DDL for users to review, and then it’s up to the users to run it or not. It's a feature to be implemented, see <a href="https://github.com/strongloop/loopback-next/issues/4757" target="_blank" rel="noopener noreferrer" class="">https://github.com/strongloop/loopback-next/issues/4757</a>.
--<em>Answered by @Diana Lau</em></p>
<hr>
<p><strong>Question:</strong> I want to check whether a specified <code>categoryId</code> exists in a Mongo datasource, how can I do that? For example,</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token property" style="color:#36acaa">"categories"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token property" style="color:#36acaa">"categoryId"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"e759c15e-3552-4557-aa6b-c1396674c7e6"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token property" style="color:#36acaa">"name"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"test"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token property" style="color:#36acaa">"categoryId"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"e759c15e-3552-4557-aa6b-c1396674c7e5"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token property" style="color:#36acaa">"name"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"test1"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>I tried <code>await this.usersRepository.find({'categories.categoryId': 'e759c15e-3552-4557-aa6b-c1396674c7e5'});</code> but getting an error message below:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">&gt; { 'categories.categoryId': string; }' is not assignable to parameter of type 'Filter&lt;Users&gt;'. Object literal may only specify known properties, and ''categories.categoryId'' does not exist in type 'Filter&lt;Users&gt;'</span><br></span></code></pre></div></div>
<p><strong>Answer:</strong>
The object you pass into <code>.find()</code> needs to be a <code>Filter</code> object. Make sure you <code>import { Filter } from '@loopback/repository';</code>, then you can:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> existingCategoryFilter</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Filter </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">//...filter properties in here...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> existingCategories </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">categoryRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">existingCategoryFilter</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>-- Answered by @Jackson Hyde</p>
<p>To add on what @Jackson Hyde has mentioned, due to limitations on TypeScript types, nested objects are not included in the typings. Hence, you'll also need to override TypeScript's check by adding <code>// @ts-ignore</code> just before the repository function.
-- Answered by @Rifa Achrinza</p>
<hr>
<p><strong>Question:</strong> I want to implement JWT refresh token in LoopBack 4. Can you suggest any good tutorial?</p>
<p><strong>Answer:</strong> You can follow this <a href="https://loopback.io/doc/en/lb4/JWT-authentication-extension.html" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/lb4/JWT-authentication-extension.html</a>.
--<em>Answered by @Pratik Jaiswal</em></p>
<hr>
<p><strong>Question:</strong> I used LoopBack CLI to create a "SHIPPING" model but it tries to do lowercase "Shipping" in the SQL with the quotes. An error occurred in the SQL statement because it is case sensitive with the quotes around it. How can I fix this? I'm on LoopBack 4 and using the <code>loopback-connector-ibmi</code>.</p>
<p><strong>Answer:</strong>
Did u try to give the name in your model?</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">model</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'member_membership'</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">MemberMembership</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">Entity</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">//...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>So <code>member_membership</code> is the table in the database.
-- Answered by @Mohammed</p>
<p>The <code>name</code> property customizes the model name, which is default to the class name if not provided. The model name is then used as the default for table name unless you further customize it for specific databases.
-- Answered by @Raymond Feng</p>
<hr>
<p><strong>Question:</strong> I have a CORS issue with <code>passport-login</code> example when trying to establish connection with Google using Angular Frontend. I keep getting CORS error:</p>
<blockquote>
<p>Access to XMLHttpRequest at '<a href="https://accounts.google.com/o/oauth2/v2/auth" target="_blank" rel="noopener noreferrer" class="">https://accounts.google.com/o/oauth2/v2/auth</a>?...' (redirected from '<a href="http://localhost:3000/api/auth/thirdparty/google" target="_blank" rel="noopener noreferrer" class="">http://localhost:3000/api/auth/thirdparty/google</a>') from origin '<a href="http://localhost:4200/" target="_blank" rel="noopener noreferrer" class="">http://localhost:4200</a>' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."</p>
</blockquote>
<p>But the application is working fine with jade.</p>
<p><strong>Answer:</strong>
In your login component you could do something like:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token constant" style="color:#36acaa">OAUTH2_LINK_GOOGLE</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">api_url</span><span class="token operator" style="color:#393A34">+</span><span class="token string" style="color:#e3116c">'/api/auth/thirdparty/google?redirect_uri='</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">redir_url</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token function" style="color:#d73a49">onGoogleSignIn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">href </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token constant" style="color:#36acaa">OAUTH2_LINK_GOOGLE</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>Bind the Google link to the above in the HTML code.</p>
<p>-- Answered by @marg330</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="enriching-loopback-and-its-community---you-are-invited">Enriching LoopBack and its Community - You are Invited!<a href="https://loopback.io/blog/2020-oct-slack-qa#enriching-loopback-and-its-community---you-are-invited" class="hash-link" aria-label="Direct link to Enriching LoopBack and its Community - You are Invited!" title="Direct link to Enriching LoopBack and its Community - You are Invited!" translate="no">​</a></h2>
<p>As mentioned in our <a href="https://strongloop.com/strongblog/2020-community-contribution/" target="_blank" rel="noopener noreferrer" class="">recent blog post</a>, your contribution is important to make LoopBack a sustainable open source project.</p>
<p>Here is what you can do:</p>
<ul>
<li class=""><a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Join LoopBack Slack community</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22" target="_blank" rel="noopener noreferrer" class="">Look for first-contribution-friendly issues</a></li>
<li class="">Give us feedback and join our discussion in <a href="https://github.com/strongloop/loopback-next" target="_blank" rel="noopener noreferrer" class="">our GitHub repo</a></li>
</ul>
<p>Let's make LoopBack a better framework together!</p>]]></content:encoded>
            <category>Community</category>
            <category>Slack</category>
            <category>Q&amp;A</category>
        </item>
        <item>
            <title><![CDATA[LoopBack 4 2020 Q3 Overview]]></title>
            <link>https://loopback.io/blog/loopback-4-2020-q3-overview</link>
            <guid>https://loopback.io/blog/loopback-4-2020-q3-overview</guid>
            <pubDate>Wed, 21 Oct 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>Fall is the season of the harvest. We're glad to see the good progress that we've made in the past 3 months, together with the contributions from the community. In September, there is record high percentage (25.6%) of the merged PRs which are coming from the community. Thank you all!</p>
<p>If you haven't heard of <a href="https://hacktoberfest.digitalocean.com/" target="_blank" rel="noopener noreferrer" class="">Hacktoberfest</a> happening this month, check out the details in our <a href="https://strongloop.com/strongblog/2020-hacktoberfest/" target="_blank" rel="noopener noreferrer" class="">previous blog on Hacktoberfest</a>. There's still time to join. For those who participated, we appreciated your contributions.</p>
<p>Let's take a look some of the highlights in the last quarter by you and the LoopBack team.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="integrate-with-typeorm-typegraphql-and-messagepack">Integrate with TypeORM, TypeGraphQL and MessagePack<a href="https://loopback.io/blog/loopback-4-2020-q3-overview#integrate-with-typeorm-typegraphql-and-messagepack" class="hash-link" aria-label="Direct link to Integrate with TypeORM, TypeGraphQL and MessagePack" title="Direct link to Integrate with TypeORM, TypeGraphQL and MessagePack" translate="no">​</a></h2>
<p>One of our strategies to add value to LoopBack is to leverage third-party libraries and integrate with them. We created the following extensions:</p>
<ul>
<li class=""><a href="https://www.npmjs.com/package/@loopback/typeorm" target="_blank" rel="noopener noreferrer" class=""><code>@loopback/typeorm</code></a>: enables <a href="https://typeorm.io/" target="_blank" rel="noopener noreferrer" class="">TypeORM</a> support in LoopBack</li>
<li class=""><a href="https://www.npmjs.com/package/@loopback/graphql" target="_blank" rel="noopener noreferrer" class=""><code>@loopback/graphql</code></a>: integrates with <a href="https://typegraphql.com/" target="_blank" rel="noopener noreferrer" class="">TypeGraphQL</a> for creating GraphQL API <a href="https://loopback.io/doc/en/lb4/GraphQL.html" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/lb4/GraphQL.html</a></li>
<li class=""><a href="https://www.npmjs.com/package/@loopback/rest-msgpack" target="_blank" rel="noopener noreferrer" class=""><code>@loopback/rest-msgpack</code></a>: adds support to allow receive <a href="https://msgpack.org/index.html" target="_blank" rel="noopener noreferrer" class="">MessagePack</a> requests and transparently convert it to a regular JavaScript object. It provides a BodyParser implementation and a component to register it.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="reorganize-and-enhance-documentation">Reorganize and Enhance Documentation<a href="https://loopback.io/blog/loopback-4-2020-q3-overview#reorganize-and-enhance-documentation" class="hash-link" aria-label="Direct link to Reorganize and Enhance Documentation" title="Direct link to Reorganize and Enhance Documentation" translate="no">​</a></h2>
<p>To better organize our content and easier for navigation/discovery, we reorganized our content based on <a href="https://documentation.divio.com/" target="_blank" rel="noopener noreferrer" class="">four quadrants</a>: tutorials, how-to guides, concepts and reference guides. To find out more how our documentation is organized, see <a href="https://loopback.io/doc/en/lb4/#how-is-our-documentation-organized" target="_blank" rel="noopener noreferrer" class="">this documentation page</a>.</p>
<p>Besides the ongoing <a href="https://github.com/strongloop/loopback-next/issues/5783" target="_blank" rel="noopener noreferrer" class="">refactoring work</a>, we enriched the content and clarified on some of the topics that are frequently asked by you. For example, we:</p>
<ul>
<li class=""><a href="https://loopback.io/doc/en/lb4/Extending-LoopBack-4.html" target="_blank" rel="noopener noreferrer" class="">cleaned up the documentation about LoopBack extension</a> so that your extension creation experience would be easier and smoother. We'll continue to make some more improvement in this area as well.</li>
<li class="">enhanced the content for <a href="https://loopback.io/doc/en/lb4/Authentication-overview.html" target="_blank" rel="noopener noreferrer" class="">authentication</a> and <a href="https://loopback.io/doc/en/lb4/Authorization-overview.html" target="_blank" rel="noopener noreferrer" class="">authorization</a> to include basic concepts, usage and examples.</li>
<li class="">added a section on <a href="https://loopback.io/doc/en/lb4/Using-database-transactions.html#accessing-multiple-models-inside-one-transaction" target="_blank" rel="noopener noreferrer" class="">accessing multiple models inside a transaction</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="other-key-feature-highlights">Other Key Feature Highlights<a href="https://loopback.io/blog/loopback-4-2020-q3-overview#other-key-feature-highlights" class="hash-link" aria-label="Direct link to Other Key Feature Highlights" title="Direct link to Other Key Feature Highlights" translate="no">​</a></h2>
<p>There were many features, fixes and enhancements in the past few months, and here are some highlights:</p>
<ul>
<li class="">completed the <a href="https://loopback.io/doc/en/lb4/HasManyThrough-relation.html" target="_blank" rel="noopener noreferrer" class="">HasManyThrough relation</a></li>
<li class=""><a href="https://strongloop.com/strongblog/august-2020-milestone/#improving-rest-experience" target="_blank" rel="noopener noreferrer" class="">improved REST experience</a> by adding a <a href="https://loopback.io/doc/en/lb4/REST-middleware-sequence.html" target="_blank" rel="noopener noreferrer" class="">middleware based sequence</a></li>
<li class="">added <a href="https://loopback.io/doc/en/lb4/Authentication-component-decorator.html" target="_blank" rel="noopener noreferrer" class="">support for applying multiple authentication strategies to one endpoint</a></li>
<li class="">implemented the <a href="https://github.com/strongloop/loopback-next/tree/master/extensions/authentication-jwt#endpoints-with-refresh-token" target="_blank" rel="noopener noreferrer" class="">refresh token service</a> in the <code>@loopback/authentication-jwt</code> extension</li>
<li class="">added the <a href="https://github.com/strongloop/loopback-next/pull/6285" target="_blank" rel="noopener noreferrer" class="">support of OpenAPI parameter AJV validation</a> on simple types and <a href="https://github.com/strongloop/loopback-next/pull/6262" target="_blank" rel="noopener noreferrer" class="">AJV formats for OpenAPI spec data type formats</a>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="encourage-community-contributions">Encourage Community Contributions<a href="https://loopback.io/blog/loopback-4-2020-q3-overview#encourage-community-contributions" class="hash-link" aria-label="Direct link to Encourage Community Contributions" title="Direct link to Encourage Community Contributions" translate="no">​</a></h2>
<p>In a <a href="https://strongloop.com/strongblog/2020-community-contribution/" target="_blank" rel="noopener noreferrer" class="">recent blog post</a>, we shared our views on encouraging more community contributions to match with our growing user community. The <a href="https://loopback.io/doc/en/contrib/code-contrib.html#developer-certificate-of-origin-dco" target="_blank" rel="noopener noreferrer" class="">switch to Developer Certificate of Origin (DCO)</a> as the contribution method is a change we made to make your contribution process easier. We also created a <a href="https://loopback.io/doc/en/lb4/Community-extensions.html" target="_blank" rel="noopener noreferrer" class="">community extension documentation page</a> to showcase LoopBack extensions built by the community.</p>
<p>In addition, we are pleased to have <a href="https://github.com/nabdelgadir" target="_blank" rel="noopener noreferrer" class="">@nabdelgadir</a> and <a href="https://github.com/madaky" target="_blank" rel="noopener noreferrer" class="">@madaky</a> to be one of our community maintainers. We appreciate the great work you’ve done and welcome to the team.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="previous-milestone-blogs">Previous Milestone Blogs<a href="https://loopback.io/blog/loopback-4-2020-q3-overview#previous-milestone-blogs" class="hash-link" aria-label="Direct link to Previous Milestone Blogs" title="Direct link to Previous Milestone Blogs" translate="no">​</a></h2>
<p>There are many more accomplishments that cannot be captured in this blog, make sure you check out our previously published monthly milestone blog posts in Q3 for more details:</p>
<ul>
<li class=""><a href="https://strongloop.com/strongblog/july-2020-milestone" target="_blank" rel="noopener noreferrer" class="">July summary</a></li>
<li class=""><a href="https://strongloop.com/strongblog/august-2020-milestone" target="_blank" rel="noopener noreferrer" class="">August summary</a></li>
<li class=""><a href="https://strongloop.com/strongblog/september-2020-milestone/" target="_blank" rel="noopener noreferrer" class="">Sept summary</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="enriching-loopback-and-its-community---you-are-invited">Enriching LoopBack and its Community - You are Invited!<a href="https://loopback.io/blog/loopback-4-2020-q3-overview#enriching-loopback-and-its-community---you-are-invited" class="hash-link" aria-label="Direct link to Enriching LoopBack and its Community - You are Invited!" title="Direct link to Enriching LoopBack and its Community - You are Invited!" translate="no">​</a></h2>
<p>Your contribution is important to make LoopBack a sustainable open source project.</p>
<p>Here is what you can do:</p>
<ul>
<li class=""><a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Join LoopBack Slack community</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22" target="_blank" rel="noopener noreferrer" class="">Look for first-contribution-friendly issues</a></li>
<li class="">Give us feedback and join our discussion in <a href="https://github.com/strongloop/loopback-next" target="_blank" rel="noopener noreferrer" class="">our GitHub repo</a></li>
<li class="">Limited time only: <a href="https://strongloop.com/strongblog/2020-hacktoberfest/" target="_blank" rel="noopener noreferrer" class="">Join the Hacktoberfest</a> in the month of October</li>
</ul>
<p>Let's make LoopBack a better framework together!</p>]]></content:encoded>
            <category>Quarterly update</category>
        </item>
        <item>
            <title><![CDATA[LoopBack 3 End-of-Life]]></title>
            <link>https://loopback.io/blog/2020-lb3-eol</link>
            <guid>https://loopback.io/blog/2020-lb3-eol</guid>
            <pubDate>Wed, 14 Oct 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>LoopBack 3 is <a href="https://loopback.io/doc/en/contrib/Long-term-support.html" target="_blank" rel="noopener noreferrer" class="">approaching its end-of-life</a> at the end of the year for community support. For LoopBack 3 users, we hope the <a href="https://loopback.io/doc/en/lb4/migration-overview.html" target="_blank" rel="noopener noreferrer" class="">migration guide</a> helps you migrate your applications to version 4.</p>
<p>At the same time, we understand you might still be using LoopBack 3 and/or in the process of migrating to LoopBack 4. For the next few months after the EOL date, we'll try to support the community in the following ways:</p>
<ul>
<li class=""><strong>Helping the community to migrate</strong>: we will continue to help with questions on <a href="https://github.com/strongloop/loopback" target="_blank" rel="noopener noreferrer" class="">GitHub</a> and <a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Slack</a>, but it will be on a best-effort basis.</li>
<li class=""><strong>Security vulnerabilities</strong>: Critical security fixes will be applied as needed by <a href="https://www.ibm.com/cloud/api-connect" target="_blank" rel="noopener noreferrer" class="">IBM API Connect</a>.</li>
<li class=""><strong>New features</strong>: No features will be accepted.</li>
<li class=""><strong>Bugs</strong>: We are not going to actively fix any bugs reported by the community users. For critical bugs, maintainers will review and assess the risks of community-submitted PRs. If you’re planning to submit a fix, it’s the best to open a GitHub issue to discuss with the maintainers before proceeding.</li>
</ul>
<p>Please note that the December 2020 end-of-life date is applicable to community support. If you are using LoopBack as part of the <a href="https://www.ibm.com/cloud/api-connect" target="_blank" rel="noopener noreferrer" class="">IBM API Connect</a> v5 or v2018 product, check with the product announcement for its end-of-support schedule.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-should-i-do-if-im-still-using-loopback-3">What Should I Do If I'm Still Using LoopBack 3?<a href="https://loopback.io/blog/2020-lb3-eol#what-should-i-do-if-im-still-using-loopback-3" class="hash-link" aria-label="Direct link to What Should I Do If I'm Still Using LoopBack 3?" title="Direct link to What Should I Do If I'm Still Using LoopBack 3?" translate="no">​</a></h2>
<p>If you already have LoopBack 3 applications running in production, it is highly recommended for you to review the <a href="https://loopback.io/doc/en/lb4/Understanding-the-differences.html" target="_blank" rel="noopener noreferrer" class="">Understanding the differences between LoopBack 3 and LoopBack 4 page</a> as mentioned in <a href="https://strongloop.com/strongblog/lb3-extended-lts/" target="_blank" rel="noopener noreferrer" class="">one of our older blog posts</a>. There is also the <a href="https://loopback.io/doc/en/lb4/migration-overview.html" target="_blank" rel="noopener noreferrer" class="">migration guide</a> helping you to migrate your LoopBack 3 applications incrementally.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-if-i-cannot-migrate-to-loopback-4-any-time-soon">What If I Cannot Migrate to LoopBack 4 Any Time Soon?<a href="https://loopback.io/blog/2020-lb3-eol#what-if-i-cannot-migrate-to-loopback-4-any-time-soon" class="hash-link" aria-label="Direct link to What If I Cannot Migrate to LoopBack 4 Any Time Soon?" title="Direct link to What If I Cannot Migrate to LoopBack 4 Any Time Soon?" translate="no">​</a></h2>
<p>Your LoopBack 3 applications will continue to work even after LoopBack 3 reaches end of life. There will be <em>very</em> minimal, if any, changes going into the codebase. In the case of addressing security vulnerabilities, you might need to fork the corresponding GitHub repos and apply security fixes. See <a href="https://strongloop.com/strongblog/lb3-entered-maintenance-mode/" target="_blank" rel="noopener noreferrer" class="">this blog</a> for the list of Node.js packages reaching end-of-life along with <code>loopback</code> repo.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="enriching-loopback-and-its-community---you-are-invited">Enriching LoopBack and its Community - You are Invited!<a href="https://loopback.io/blog/2020-lb3-eol#enriching-loopback-and-its-community---you-are-invited" class="hash-link" aria-label="Direct link to Enriching LoopBack and its Community - You are Invited!" title="Direct link to Enriching LoopBack and its Community - You are Invited!" translate="no">​</a></h2>
<p>Your contribution is important to make LoopBack a sustainable open source project. Here is what you can do:</p>
<ul>
<li class=""><a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Join LoopBack Slack community</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22" target="_blank" rel="noopener noreferrer" class="">Look for first-contribution-friendly issues</a></li>
<li class="">Give us feedback and join our discussion in <a href="https://github.com/strongloop/loopback-next" target="_blank" rel="noopener noreferrer" class="">our GitHub repo</a></li>
</ul>
<p>Let's make LoopBack a better framework together!</p>]]></content:encoded>
            <category>LoopBack 3</category>
        </item>
        <item>
            <title><![CDATA[LoopBack 4 September 2020 Milestone Update]]></title>
            <link>https://loopback.io/blog/september-2020-milestone</link>
            <guid>https://loopback.io/blog/september-2020-milestone</guid>
            <pubDate>Wed, 07 Oct 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>We bring another month of new features, fixes, and improvements in documentation and developer experience in LoopBack. Make sure to update your compatible projects with <code>lb4 update</code> if you want to update the underlying libraries to their latest versions.</p>
<p>Also, as part of our long-term effort to encourage more community contributions, we are participating in this year’s <a href="https://hacktoberfest.digitalocean.com/" target="_blank" rel="noopener noreferrer" class="">Hacktoberfest</a>. You can read more about the event and participation details at our <a href="https://strongloop.com/strongblog/2020-hacktoberfest/" target="_blank" rel="noopener noreferrer" class="">Hacktoberfest blogpost</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="documentation-enhancements">Documentation Enhancements<a href="https://loopback.io/blog/september-2020-milestone#documentation-enhancements" class="hash-link" aria-label="Direct link to Documentation Enhancements" title="Direct link to Documentation Enhancements" translate="no">​</a></h2>
<p>There has been a continuous effort to improve our documentation. Below are some highlights for this month:</p>
<ul>
<li class="">A new documentation page, <a href="https://loopback.io/doc/en/lb4/Accessing-http-request-response.html" target="_blank" rel="noopener noreferrer" class="">Accessing HTTP request and response objects</a>, was added explaining the various ways and places to access the request and response objects.</li>
<li class="">We are working on a series of troubleshooting guides for LoopBack. This month we completed the <a href="https://loopback.io/doc/en/lb4/Troubleshooting.html" target="_blank" rel="noopener noreferrer" class="">basic guide</a> and <a href="https://loopback.io/doc/en/lb4/Debugging-tests-with-mocha.html" target="_blank" rel="noopener noreferrer" class="">Debugging tests with Mocha</a>. <a href="https://github.com/strongloop/loopback-next/issues/5701#issuecomment-700955686" target="_blank" rel="noopener noreferrer" class="">A few more areas</a> that can be added to the guide.</li>
<li class="">We added an <a href="https://github.com/strongloop/loopback-next/tree/master/examples/binding-resolution" target="_blank" rel="noopener noreferrer" class="">example app</a> demonstrating LoopBack 4's context binding resolution and dependency injection within a context hierarchy.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-experimental-features">New Experimental Features<a href="https://loopback.io/blog/september-2020-milestone#new-experimental-features" class="hash-link" aria-label="Direct link to New Experimental Features" title="Direct link to New Experimental Features" translate="no">​</a></h2>
<ul>
<li class="">We have created a <a href="https://github.com/strongloop/loopback-next/tree/master/extensions/graphql" target="_blank" rel="noopener noreferrer" class="">GraphQL extension</a> that provides integration with GraphQL using <a href="https://typegraphql.com/" target="_blank" rel="noopener noreferrer" class="">type-graphql</a>. Check out the <a href="https://github.com/strongloop/loopback-next/tree/master/examples/graphql" target="_blank" rel="noopener noreferrer" class="">GraphQL example app</a> for a sample app.</li>
<li class="">We added support for parsing <a href="https://msgpack.org/index.html" target="_blank" rel="noopener noreferrer" class="">MessagePack</a> bodies. For usage, refer to the <a href="https://github.com/strongloop/loopback-next/tree/master/bodyparsers/rest-msgpack" target="_blank" rel="noopener noreferrer" class="">documentation</a>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="investigation-on-better-handling-of-objectid-in-mongodb">Investigation on Better Handling of ObjectID in MongoDB<a href="https://loopback.io/blog/september-2020-milestone#investigation-on-better-handling-of-objectid-in-mongodb" class="hash-link" aria-label="Direct link to Investigation on Better Handling of ObjectID in MongoDB" title="Direct link to Investigation on Better Handling of ObjectID in MongoDB" translate="no">​</a></h2>
<p>We spent a good amount of time to improve the experience of using <code>ObjectID</code> with LoopBack. We have identified the direction we want to take and the tasks to work on. You can learn more about the spike in issue <a href="https://github.com/strongloop/loopback-next/issues/3456" target="_blank" rel="noopener noreferrer" class="">3456</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="fixes-and-improvements">Fixes and Improvements<a href="https://loopback.io/blog/september-2020-milestone#fixes-and-improvements" class="hash-link" aria-label="Direct link to Fixes and Improvements" title="Direct link to Fixes and Improvements" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://github.com/strongloop/loopback-next/pull/6230" target="_blank" rel="noopener noreferrer" class="">added <code>.onStart()</code> and <code>.onStop()</code> methods of the <code>Application</code></a>, so that they can be used to register observers as plain functions for the start and stop life-cycle events.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/pull/6398" target="_blank" rel="noopener noreferrer" class="">enhanced the <code>lb4 update</code> command</a> to be runnable against any projects that use <code>@loopback/*</code> dependencies in <code>dependencies</code> or <code>devDependencies</code>, or <code>peerDependencies</code>; not just LoopBack 4 projects.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/pull/6390" target="_blank" rel="noopener noreferrer" class="">included the application build when running <code>migrate</code> and <code>openapi-spec</code> scripts</a>.</li>
<li class="">added <code>@injectable</code>, so that <code>@injectable</code> can be used instead of <code>@bind</code>, which is in tune with other frameworks using Dependency Injection. <code>@bind</code> is not removed from the framework, so apps using <code>@bind</code> will not be affected.</li>
<li class="">made the <code>keepAliveTimeout</code>, <code>headersTimeout</code>, <code>maxConnections</code>, <code>maxHeadersCount</code>, and <code>timeout</code> properties of the underlying <a href="https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_class_http_server" target="_blank" rel="noopener noreferrer" class="">HTTP server</a> instance <a href="https://github.com/strongloop/loopback-next/pull/6267" target="_blank" rel="noopener noreferrer" class="">configurable by specifying them in the application config object</a>.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/pull/6429" target="_blank" rel="noopener noreferrer" class="">updated the generated application directory name during application scaffolding</a> when application names involve numbers</li>
<li class="">added <a href="https://github.com/strongloop/loopback-next/pull/6315" target="_blank" rel="noopener noreferrer" class="">the ability to boot dynamic value provider classes and classes with <code>@inject</code></a>.</li>
<li class="">removed the <code>extension-</code> prefix from the affected extensions for their names to be consistent with other extension modules.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/pull/6313" target="_blank" rel="noopener noreferrer" class="">improved the overall experience of graphql configuration and subscriptions</a> in LoopBack.</li>
<li class="">added the <a href="https://github.com/strongloop/loopback-next/pull/6285" target="_blank" rel="noopener noreferrer" class="">support of OpenAPI parameter AJV validation</a> on simple types and <a href="https://github.com/strongloop/loopback-next/pull/6262" target="_blank" rel="noopener noreferrer" class="">AJV formats for OpenAPI spec data type formats</a>.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/pull/6284" target="_blank" rel="noopener noreferrer" class="">updated the REST middleware</a> so that it can now cached by the use of singleton binding scope.</li>
<li class="">added Twitter example in the <a href="https://github.com/strongloop/loopback-next/tree/master/examples/passport-login" target="_blank" rel="noopener noreferrer" class="">Passport login example app</a>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="community-contributions">Community Contributions<a href="https://loopback.io/blog/september-2020-milestone#community-contributions" class="hash-link" aria-label="Direct link to Community Contributions" title="Direct link to Community Contributions" translate="no">​</a></h2>
<p>Shout out to <a href="https://github.com/achrinza" target="_blank" rel="noopener noreferrer" class="">Rifa Achrinza</a> for explaining the differences between weak and strong relations in PR <a href="https://github.com/strongloop/loopback-next/pull/6404" target="_blank" rel="noopener noreferrer" class="">6404</a>, <a href="https://github.com/strongloop/loopback-next/pull/6155" target="_blank" rel="noopener noreferrer" class="">MessagePack PR</a>, and his numerous other PRs.</p>
<p>Opening issues are community contributions too, so thanks to all those who help LoopBack become better by reporting bugs and usability issue. We try to address popular issues with higher priority, so continue to let us know the problems you face on <a href="https://github.com/strongloop/loopback-next/issues" target="_blank" rel="noopener noreferrer" class="">GitHub</a> or <a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Slack</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="enriching-loopback-and-its-community---you-are-invited">Enriching LoopBack and its Community - You are Invited!<a href="https://loopback.io/blog/september-2020-milestone#enriching-loopback-and-its-community---you-are-invited" class="hash-link" aria-label="Direct link to Enriching LoopBack and its Community - You are Invited!" title="Direct link to Enriching LoopBack and its Community - You are Invited!" translate="no">​</a></h2>
<p>As mentioned in our <a href="https://strongloop.com/strongblog/2020-community-contribution/" target="_blank" rel="noopener noreferrer" class="">recent blog post</a>, your contribution is important to make LoopBack a sustainable open source project.</p>
<p>Here is what you can do:</p>
<ul>
<li class=""><a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Join LoopBack Slack community</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22" target="_blank" rel="noopener noreferrer" class="">Look for first-contribution-friendly issues</a></li>
<li class="">Give us feedback and join our discussion in <a href="https://github.com/strongloop/loopback-next" target="_blank" rel="noopener noreferrer" class="">our GitHub repo</a></li>
</ul>
<p>Let's make LoopBack a better framework together!</p>]]></content:encoded>
            <category>Milestone update</category>
        </item>
        <item>
            <title><![CDATA[LoopBack is participating in Hacktoberfest 2020]]></title>
            <link>https://loopback.io/blog/2020-hacktoberfest</link>
            <guid>https://loopback.io/blog/2020-hacktoberfest</guid>
            <pubDate>Tue, 29 Sep 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>As part of our long-term effort to <a class="" href="https://loopback.io/2020-community-contribution">encourange more community
contributions</a>,
LoopBack is going to participate in this year's
<a href="https://hacktoberfest.digitalocean.com/" target="_blank" rel="noopener noreferrer" class="">Hacktoberfest</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-hacktoberfest">What is Hacktoberfest?<a href="https://loopback.io/blog/2020-hacktoberfest#what-is-hacktoberfest" class="hash-link" aria-label="Direct link to What is Hacktoberfest?" title="Direct link to What is Hacktoberfest?" translate="no">​</a></h2>
<p>Hacktoberfest is an annual event encouraging participation in the open source community, open to everyone. Whether you’re new to development, a student, or a long-time contributor, you can help drive the growth of open source and make positive impact on an ever-growing community. All backgrounds and skills levels are encouraged to complete the challenge.</p>
<p>You can learn more about Hacktoberfest values at <a href="https://hacktoberfest.digitalocean.com/details#values" target="_blank" rel="noopener noreferrer" class="">https://hacktoberfest.digitalocean.com/details#values</a>.</p>
<p>Participants completing the challenge (contributing at least 4 valid pull requests) will earn a limited edition T-shirt.</p>
<p><em>Please note that any prizes are subject to conditions set by Hacktoberfest. IBM and the LoopBack team are not involved and not responsible in any way.</em></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-to-participate">How to participate<a href="https://loopback.io/blog/2020-hacktoberfest#how-to-participate" class="hash-link" aria-label="Direct link to How to participate" title="Direct link to How to participate" translate="no">​</a></h2>
<p>Joining the effort is simple. Just pick any problem that is itching you and send a pull request to fix it. You can also choose one of LoopBack's issues labelled as <a href="https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Astrongloop+label%3AHacktoberfest" target="_blank" rel="noopener noreferrer" class="">Hacktoberfest</a> or <a href="https://github.com/issues?q=is%3Aopen+is%3Aissue+user%3Astrongloop+label%3A%22good+first+issue%22" target="_blank" rel="noopener noreferrer" class="">good first issue</a> if you need inspiration.</p>
<p>Make sure to familiarize yourself with Hacktoberfest's <a href="https://hacktoberfest.digitalocean.com/details#rules" target="_blank" rel="noopener noreferrer" class="">Participation rules</a> and <a href="https://hacktoberfest.digitalocean.com/details#quality" target="_blank" rel="noopener noreferrer" class="">Quality standards</a>; and also LoopBack's <a href="https://github.com/strongloop/loopback-next/blob/master/docs/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer" class="">Contributing guide</a>.</p>
<p>Are you new to open source? No problem, we have you covered! Check out Hacktoberfest's <a href="https://hacktoberfest.digitalocean.com/details#beginners" target="_blank" rel="noopener noreferrer" class="">Beginners</a> guides and LoopBack's guide on <a href="https://loopback.io/doc/en/lb4/submitting_a_pr.html" target="_blank" rel="noopener noreferrer" class="">submitting a pull request to LoopBack 4</a>.</p>
<p>For the entire month of October, LoopBack's maintainers team will be giving extra priority to pull request reviews and helping new contributors along their journey to the first accepted contribution.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="focus-areas">Focus areas<a href="https://loopback.io/blog/2020-hacktoberfest#focus-areas" class="hash-link" aria-label="Direct link to Focus areas" title="Direct link to Focus areas" translate="no">​</a></h2>
<p>We are primarily looking for quick wins with long term impact: small enhancements improving your day-to-day experience while using LoopBack.</p>
<p>As you may know, we have introduced a new documentation system in June to better organize the content and make it easier to find the information you need (see <a class="" href="https://loopback.io/june-2020-milestone#new-documentation-structure">New Documentation Structure</a> and <a class="" href="https://loopback.io/june-2020-milestone#alignment-along-abstraction-levels">Alignment Along Abstraction Levels</a>). The reorganization is still in progress and we would love to get some help. In particular, extracting recipes from "Concepts" explanations into proper "How-to guides" is an easy way how to quickly score valuable pull requests. See the GitHub issue <a href="https://github.com/strongloop/loopback-next/issues/5783" target="_blank" rel="noopener noreferrer" class="">loopback-next#5783</a> for the list of docs pages to rework.</p>
<p>Having said that, all improvements are welcome!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="closing-thoughts">Closing thoughts<a href="https://loopback.io/blog/2020-hacktoberfest#closing-thoughts" class="hash-link" aria-label="Direct link to Closing thoughts" title="Direct link to Closing thoughts" translate="no">​</a></h2>
<p>We are looking forward to receive and eventually land your pull requests. Let's make LoopBack a better framework together!</p>]]></content:encoded>
            <category>hacktoberfest</category>
        </item>
        <item>
            <title><![CDATA[Community Q&A Monthly Digest - Sept 2020]]></title>
            <link>https://loopback.io/blog/2020-sept-slack-qa</link>
            <guid>https://loopback.io/blog/2020-sept-slack-qa</guid>
            <pubDate>Wed, 16 Sep 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>Welcome back to the September edition of the "Community Q&amp;A Monthly Digest", in which we are curating some of the Q&amp;A that we think it might be helpful to you. Thank you for posting your questions and helping your fellow LoopBack users.</p>
<p>The <a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">LoopBack Slack community</a> is a platform where LoopBack users are helping each other out. If you haven't joined already, sign up today!</p>
<p>Let's take a look at some of the questions and answers from the community.</p>
<p><strong>Question:</strong> Is it possible to use auto-generate timestamp property in a model?</p>
<p><strong>Answer:</strong> To set the property to the current datetime upon Model Create, you can:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">property</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">type</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'date'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">defaultFn</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'now'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">timestamp</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<hr>
<p><strong>Question:</strong> Does LoopBack has any built-in cache? Or should we implement that to make response even faster?</p>
<p><strong>Answer:</strong>
We currently don’t but there are some example implementations for your reference:</p>
<ul>
<li class=""><a href="https://github.com/strongloop/loopback-next/tree/master/packages/rest/src/__tests__/acceptance/caching-interceptor" target="_blank" rel="noopener noreferrer" class="">caching interceptor</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/blob/master/examples/greeting-app/src/caching-service.ts" target="_blank" rel="noopener noreferrer" class="">caching service</a></li>
</ul>
<hr>
<p><strong>Question:</strong> I want to perform schema migration but the order of tables is important beacause there are some relation and foreign key between them. How can I set the order of tables to be migrated?</p>
<p><strong>Answer:</strong> Within <code>migrate.ts</code>, <code>app.migrateSchema</code> accepts a <code>model</code> array. So it can be updated as such:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">migrateSchema</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">Object</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">assign</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">SchemaMigrationOptions</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">models</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token comment" style="color:#999988;font-style:italic">/* Add model names here */</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> existingSchema</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>Like with any auto-migration, please do take a backup of the database before running the migration.</p>
<hr>
<p><strong>Question:</strong> I wanted to implement an API like the <code>file-transfer</code> example on the docs but with more endpoints with different storage directories. How is that possible?</p>
<p><strong>Answer:</strong> You can have different endpoints backed by different methods using <code>post /&lt;url&gt;</code> decoration as you see at <a href="https://github.com/strongloop/loopback-next/blob/master/examples/file-transfer/src/controllers/file-upload.controller.ts#L28" target="_blank" rel="noopener noreferrer" class="">https://github.com/strongloop/loopback-next/blob/master/examples/file-transfer/src/controllers/file-upload.controller.ts#L28</a>. If you want to calculate the file path per request, you can instantiate a new upload service instance instead of using the injected one.</p>
<hr>
<p><strong>Questions:</strong> I work with LoopBack in a k8 cluster, when i try to implement JWT authentication, all users get the same token, and the data in that token is not equal to that user. Is there any way to fix it besides saving the token in a database?</p>
<p><strong>Answer:</strong> Typically JWT tokens are generated using a combination of a secret and some sort of UUID of the user. When they successfully authenticate, a token is generated and returned. When you need to verify the token, you decode it using the secret, giving you the UUID of the user. This means that you don’t actually have to save a token at all. Here’s how we are generating tokens for our users.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> userInfoForToken </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> userProfile</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">name</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> userProfile</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">name</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">roles</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> userProfile</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">roles</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Generate a JSON Web Token</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> token</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">string</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">token </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">signAsync</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">userInfoForToken</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">jwtSecret</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">expiresIn</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Number</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">jwtExpiresIn</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">error</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">throw</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">HttpErrors</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Unauthorized</span><span class="token punctuation" style="color:#393A34">(</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token template-string string" style="color:#e3116c">Error encoding token : </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token template-string interpolation">error</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token template-string template-punctuation string" style="color:#e3116c">`</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>In this context, <code>signAsync</code> is a <code>promisify</code>’d version of <code>jsonwebtoken.sign()</code>.</p>
<hr>
<p><strong>Question:</strong> I want to use the LoopBack app cli-command programmatically. Is this possible?</p>
<p><strong>Answer:</strong>
You can try to <code>require('@loopback/cli/lib/cli')</code>. See <a href="https://github.com/strongloop/loopback-next/blob/master/packages/cli/lib/cli.js" target="_blank" rel="noopener noreferrer" class="">https://github.com/strongloop/loopback-next/blob/master/packages/cli/lib/cli.js</a>. <code>cli.js</code> has logic to create yeoman env and register generators.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="enriching-loopback-and-its-community---you-are-invited">Enriching LoopBack and its Community - You are Invited!<a href="https://loopback.io/blog/2020-sept-slack-qa#enriching-loopback-and-its-community---you-are-invited" class="hash-link" aria-label="Direct link to Enriching LoopBack and its Community - You are Invited!" title="Direct link to Enriching LoopBack and its Community - You are Invited!" translate="no">​</a></h2>
<p>As mentioned in our <a href="https://strongloop.com/strongblog/2020-community-contribution/" target="_blank" rel="noopener noreferrer" class="">recent blog post</a>, your contribution is important to make LoopBack a sustainable open source project.</p>
<p>Here is what you can do:</p>
<ul>
<li class=""><a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Join LoopBack Slack community</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22" target="_blank" rel="noopener noreferrer" class="">Look for first-contribution-friendly issues</a></li>
<li class="">Give us feedback and join our discussion in <a href="https://github.com/strongloop/loopback-next" target="_blank" rel="noopener noreferrer" class="">our GitHub repo</a></li>
</ul>
<p>Let's make LoopBack a better framework together!</p>]]></content:encoded>
            <category>Community</category>
            <category>Slack</category>
            <category>Q&amp;A</category>
        </item>
        <item>
            <title><![CDATA[LoopBack 4 August 2020 Milestone Update]]></title>
            <link>https://loopback.io/blog/august-2020-milestone</link>
            <guid>https://loopback.io/blog/august-2020-milestone</guid>
            <pubDate>Wed, 02 Sep 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>Our focus in August is the documentation restructure. The layout of several main sections are reorganized for easier navigation. Another significant improvement is about the request handling. More flexible approaches of adding LoopBack style middleware and express middleware are introduced in <code>@loopback/rest</code>.</p>
<p>We would like to appreciate <a href="https://github.com/agnes512" target="_blank" rel="noopener noreferrer" class="">Agnes Lin</a>'s great contributions during her internship. There has been so much fun and pleasure working with her! She will be continue helping us part time. Good luck with your school.</p>
<p>Keep reading to learn about the improved documentation and recently added features!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="documentation-enhancements">Documentation Enhancements<a href="https://loopback.io/blog/august-2020-milestone#documentation-enhancements" class="hash-link" aria-label="Direct link to Documentation Enhancements" title="Direct link to Documentation Enhancements" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="reorganizing-the-concepts-list">Reorganizing the Concepts List<a href="https://loopback.io/blog/august-2020-milestone#reorganizing-the-concepts-list" class="hash-link" aria-label="Direct link to Reorganizing the Concepts List" title="Direct link to Reorganizing the Concepts List" translate="no">​</a></h3>
<p>The fundamental concepts were listed in section "Behind the Scene" sorted by the publish date. To have a concise name and a more organized layout for users to search, we renamed the section to be "Concepts" and restructured the documentations into the following sub-sections:</p>
<ul>
<li class="">Crafting LoopBack 4</li>
<li class="">Core</li>
<li class="">REST APIs</li>
<li class="">Data Access</li>
</ul>
<p>You can visit the more organized contents in <a href="https://loopback.io/doc/en/lb4/Concepts.html" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/lb4/Concepts.html</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="reorganizing-how-to-guide-list">Reorganizing How-to Guide List<a href="https://loopback.io/blog/august-2020-milestone#reorganizing-how-to-guide-list" class="hash-link" aria-label="Direct link to Reorganizing How-to Guide List" title="Direct link to Reorganizing How-to Guide List" translate="no">​</a></h3>
<p>The "How-to Guide" is also reorganized by topics. The existing tutorials are classified into the following sections for users to search quickly:</p>
<ul>
<li class="">Building REST APIs</li>
<li class="">Creating Other Forms of APIS</li>
<li class="">Accessing Databases</li>
<li class="">Accessing Services</li>
<li class="">Validating Data</li>
<li class="">Securing Applications</li>
<li class="">Deploying Applications</li>
<li class="">Troubleshooting</li>
</ul>
<p>You can visit the more organized contents in <a href="https://loopback.io/doc/en/lb4/" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/lb4/</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="adding-property-types">Adding Property Types<a href="https://loopback.io/blog/august-2020-milestone#adding-property-types" class="hash-link" aria-label="Direct link to Adding Property Types" title="Direct link to Adding Property Types" translate="no">​</a></h3>
<p>We added documentation for LoopBack 4 types including the syntax of model property definition in page <a href="https://loopback.io/doc/en/lb4/LoopBack-types.html" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/lb4/LoopBack-types.html</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="adding-application-layout">Adding Application Layout<a href="https://loopback.io/blog/august-2020-milestone#adding-application-layout" class="hash-link" aria-label="Direct link to Adding Application Layout" title="Direct link to Adding Application Layout" translate="no">​</a></h3>
<p>We added project layout for LoopBack 4 applications in page <a href="https://loopback.io/doc/en/lb4/Loopback-application-layout.html" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/lb4/Loopback-application-layout.html</a>, users can find each file's meaning and responsibility in the application scaffolded by <code>lb4 app</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cleaning-up-extensions">Cleaning up Extensions<a href="https://loopback.io/blog/august-2020-milestone#cleaning-up-extensions" class="hash-link" aria-label="Direct link to Cleaning up Extensions" title="Direct link to Cleaning up Extensions" translate="no">​</a></h3>
<p>We are seeing more users creating extensions and it's a good time to make the extension creation experience easier and smoother. Therefore the extension generator and related documentations are updated to align with the latest code base. You can check the latest material in:</p>
<ul>
<li class=""><a href="https://loopback.io/doc/en/lb4/Component.html" target="_blank" rel="noopener noreferrer" class="">Concept Component</a></li>
<li class=""><a href="https://loopback.io/doc/en/lb4/Creating-components.html" target="_blank" rel="noopener noreferrer" class="">Creating Components</a></li>
</ul>
<p>And run <code>lb4 extension</code> to create extensions with the new component template.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="renaming-legacy-juggler">Renaming Legacy Juggler<a href="https://loopback.io/blog/august-2020-milestone#renaming-legacy-juggler" class="hash-link" aria-label="Direct link to Renaming Legacy Juggler" title="Direct link to Renaming Legacy Juggler" translate="no">​</a></h3>
<p>The term "legacy juggler bridge" might give the wrong impression to users that the <code>loopback-datasource-juggler</code> won't be supported or not working well because of the "legacy" word. So we removed the misleading word "legacy" across the documentations and CLI prompts.</p>
<p><code>loopback-datasource-juggler</code> is still well maintained and we have a plan to modernize it. Feel free to join the discussion in <a href="https://github.com/strongloop/loopback-next/issues/5956" target="_blank" rel="noopener noreferrer" class="">issue #5956</a> if you are interested.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="investigation">Investigation<a href="https://loopback.io/blog/august-2020-milestone#investigation" class="hash-link" aria-label="Direct link to Investigation" title="Direct link to Investigation" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="restructuring-connector-reference">Restructuring Connector Reference<a href="https://loopback.io/blog/august-2020-milestone#restructuring-connector-reference" class="hash-link" aria-label="Direct link to Restructuring Connector Reference" title="Direct link to Restructuring Connector Reference" translate="no">​</a></h3>
<p>The current connector contents are mixed with how-to guides, references and tutorials. The spike story <a href="https://github.com/strongloop/loopback-next/issues/5961" target="_blank" rel="noopener noreferrer" class="">5961</a> came up with a better plan to reorganize them into the four quadrants layout:</p>
<ul>
<li class="">Connector concepts, its role in the framework and its relations to other artifacts will go to section "Concepts/Datasources".</li>
<li class="">Datasource level configurations and features like migration/discovery will go to section "How-to Guides/Configuring DataSource".</li>
<li class="">All the other connector specific tutorials will go to section "Tutorials/Connect to back-end tutorial".</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="improving-rest-experience">Improving REST Experience<a href="https://loopback.io/blog/august-2020-milestone#improving-rest-experience" class="hash-link" aria-label="Direct link to Improving REST Experience" title="Direct link to Improving REST Experience" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="rest-middleware">REST Middleware<a href="https://loopback.io/blog/august-2020-milestone#rest-middleware" class="hash-link" aria-label="Direct link to REST Middleware" title="Direct link to REST Middleware" translate="no">​</a></h3>
<p>A big feature took place in <code>@loopback/rest</code> to support more flexible ways to add express middleware for handling requests. PR <a href="https://github.com/strongloop/loopback-next/pull/5366" target="_blank" rel="noopener noreferrer" class="">#5366</a> added a middleware based sequence and wrapped existing actions as middleware. The new usage is documented in the following pages:</p>
<ul>
<li class="">Concept <a href="https://loopback.io/doc/en/lb4/Middleware.html" target="_blank" rel="noopener noreferrer" class="">Middleware</a> in LoopBack 4.</li>
<li class=""><a href="https://loopback.io/doc/en/lb4/REST-middleware-sequence.html" target="_blank" rel="noopener noreferrer" class="">Middleware-based Sequence for REST Server</a></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="optimizing-middleware-based-sequence">Optimizing Middleware Based Sequence<a href="https://loopback.io/blog/august-2020-milestone#optimizing-middleware-based-sequence" class="hash-link" aria-label="Direct link to Optimizing Middleware Based Sequence" title="Direct link to Optimizing Middleware Based Sequence" translate="no">​</a></h3>
<p>PR <a href="https://github.com/strongloop/loopback-next/pull/6062" target="_blank" rel="noopener noreferrer" class="">#6062</a> optimized middleware based sequence and its middleware providers to be singletons:</p>
<ul>
<li class="">MiddlewareSequence is now a singleton and it caches a list of middleware.</li>
<li class="">Built-in middleware providers are now singletons.</li>
<li class="">Validating sorted middleware groups is supported. Error will be reported if a middleware is unreachable.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="improving-serviceability-of-loopbackrest">Improving Serviceability of @loopback/rest<a href="https://loopback.io/blog/august-2020-milestone#improving-serviceability-of-loopbackrest" class="hash-link" aria-label="Direct link to Improving Serviceability of @loopback/rest" title="Direct link to Improving Serviceability of @loopback/rest" translate="no">​</a></h3>
<p>There are several improvements made for easier debugging and error tracing in <code>@loopback/rest</code> module:</p>
<ul>
<li class="">
<p>PR <a href="https://github.com/strongloop/loopback-next/pull/6159" target="_blank" rel="noopener noreferrer" class="">#6159</a> added more debug information for request parsing, routing, and method invocation. The debugging keywords are <code>loopback:rest:find-route</code>, <code>loopback:rest:invoke-method</code>, and <code>loopback:rest:parse-param</code>.</p>
</li>
<li class="">
<p>The route description is improved in PR <a href="https://github.com/strongloop/loopback-next/pull/6168" target="_blank" rel="noopener noreferrer" class="">#6188</a> to include the verb and the path.</p>
</li>
<li class="">
<p>PR <a href="https://github.com/strongloop/loopback-next/pull/6171" target="_blank" rel="noopener noreferrer" class="">#6171</a> added HTTP server options and status information in the debug string. The debugging keyword is <code>loopback:http-server</code>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="switching-to-dco">Switching to DCO<a href="https://loopback.io/blog/august-2020-milestone#switching-to-dco" class="hash-link" aria-label="Direct link to Switching to DCO" title="Direct link to Switching to DCO" translate="no">​</a></h2>
<p>To <a href="https://strongloop.com/strongblog/switching-to-dco/" target="_blank" rel="noopener noreferrer" class="">make your contribution process simpler</a>, we have changed the contribution method from CLA to DCO for <code>loopback-next</code> and most of the connector repositories. Be sure to sign off your commits using the <code>-s</code> flag or adding <code>Signed-off-By: Name&lt;Email&gt;</code> in the commit message. For more details, see <a href="https://loopback.io/doc/en/contrib/code-contrib.html#developer-certificate-of-origin-dco" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/contrib/code-contrib.html</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="miscellaneous">Miscellaneous<a href="https://loopback.io/blog/august-2020-milestone#miscellaneous" class="hash-link" aria-label="Direct link to Miscellaneous" title="Direct link to Miscellaneous" translate="no">​</a></h2>
<ul>
<li class="">
<p>PR <a href="https://github.com/strongloop/loopback-next/pull/6172" target="_blank" rel="noopener noreferrer" class="">#6172</a> makes sure the REST options are passed to http-server.</p>
</li>
<li class="">
<p>PR <a href="https://github.com/strongloop/loopback-next/pull/6105" target="_blank" rel="noopener noreferrer" class="">#6105</a> Reworked the validation code to use exiting <code>RestHttpErrors.invalidData</code> error. This way the error object includes the parameter name in the error message &amp; properties and has a machine-readable code property.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="community-contributions">Community Contributions<a href="https://loopback.io/blog/august-2020-milestone#community-contributions" class="hash-link" aria-label="Direct link to Community Contributions" title="Direct link to Community Contributions" translate="no">​</a></h2>
<p>Thank you for the contribution coming from the community. Here are some of the contributions that we'd like highlight:</p>
<ul>
<li class="">
<p>Thanks to <a href="https://github.com/nflaig" target="_blank" rel="noopener noreferrer" class="">Nico Flaig</a>'s <a href="https://github.com/strongloop/loopback-next/pull/5735" target="_blank" rel="noopener noreferrer" class="">contribution</a>! Now <code>@loopback/authenticate</code> supports applying multiple authentication strategies to one endpoint. The new syntax of decorator is:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">authenticate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  strategyOne </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> strategyOneWithOptions</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  strategyTwo </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> strategyTwoWithOptions</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">myFunction</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>The new syntax is well documented in page <a href="https://loopback.io/doc/en/lb4/Authentication-component-decorator.html" target="_blank" rel="noopener noreferrer" class="">Authentication Decorator</a>.</p>
</li>
<li class="">
<p>We appreciate <a href="https://github.com/madaky" target="_blank" rel="noopener noreferrer" class="">Madaky</a>'s feature PR <a href="https://github.com/strongloop/loopback-next/pull/5589" target="_blank" rel="noopener noreferrer" class="">#5589</a> which adds the token refresh service in extension <code>@loopback/authentication-jwt</code>. You can check the <a href="https://github.com/strongloop/loopback-next/tree/master/extensions/authentication-jwt#endpoints-with-refresh-token" target="_blank" rel="noopener noreferrer" class="">new guide</a> to try it.</p>
</li>
<li class="">
<p>Many thanks to <a href="https://github.com/achrinza" target="_blank" rel="noopener noreferrer" class="">Rifa Achrinza</a>'s contribution in PR <a href="https://github.com/strongloop/loopback-next/pull/6153" target="_blank" rel="noopener noreferrer" class="">6153</a>. The order filter now supports string value as the shortcut in addition to the existing array value. You can specify an order filter as <code>{order: 'name DESC'}</code>.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="enriching-loopback-and-its-community---you-are-invited">Enriching LoopBack and its Community - You are Invited!<a href="https://loopback.io/blog/august-2020-milestone#enriching-loopback-and-its-community---you-are-invited" class="hash-link" aria-label="Direct link to Enriching LoopBack and its Community - You are Invited!" title="Direct link to Enriching LoopBack and its Community - You are Invited!" translate="no">​</a></h2>
<p>As mentioned in our <a href="https://strongloop.com/strongblog/2020-community-contribution/" target="_blank" rel="noopener noreferrer" class="">recent blog post</a>, your contribution is important to make LoopBack a sustainable open source project.</p>
<p>Here is what you can do:</p>
<ul>
<li class=""><a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Join LoopBack Slack community</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22" target="_blank" rel="noopener noreferrer" class="">Look for first-contribution-friendly issues</a></li>
<li class="">Give us feedback and join our discussion in <a href="https://github.com/strongloop/loopback-next" target="_blank" rel="noopener noreferrer" class="">our GitHub repo</a></li>
</ul>
<p>Let's make LoopBack a better framework together!</p>]]></content:encoded>
            <category>Milestone update</category>
        </item>
        <item>
            <title><![CDATA[Enriching LoopBack and its Community - You are Invited!]]></title>
            <link>https://loopback.io/blog/2020-community-contribution</link>
            <guid>https://loopback.io/blog/2020-community-contribution</guid>
            <pubDate>Thu, 27 Aug 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>Almost two years ago, <a href="https://strongloop.com/strongblog/loopback-4-ga" target="_blank" rel="noopener noreferrer" class="">LoopBack 4 was released and announced</a> at Node+JS Interactive event. Thanks to your support, we now have over 110k downloads per month on npmjs.com and over 3000 GitHub stars on the <a href="https://github.com/strongloop/loopback-next" target="_blank" rel="noopener noreferrer" class="">loopback-next repo</a>. Recently, we created the <a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">LoopBack Slack community</a> to provide a platform for the community and us helping each other. We are glad to see an increasing engagement in that front as well!</p>
<p>With the core of the framework maturing and contributions shifting to the LoopBack extensions, we think LoopBack has entered a new stage and it's time to revisit our approach to planning work, delivering features, fixing bugs, and improving documentation.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-short-history-of-loopback-4">A Short History of LoopBack 4<a href="https://loopback.io/blog/2020-community-contribution#a-short-history-of-loopback-4" class="hash-link" aria-label="Direct link to A Short History of LoopBack 4" title="Direct link to A Short History of LoopBack 4" translate="no">​</a></h2>
<p>As we started the rewrite of LoopBack from ground up back in early 2017 (see the <a href="https://strongloop.com/strongblog/announcing-loopback-next/" target="_blank" rel="noopener noreferrer" class="">kick-off post</a>), it quickly became clear the scope is huge and we must be very disciplined in planning and scoping features if we want to reach a meaningful release in a reasonable time. We were working in short iterations, burning through a backlog of tasks we identified as required for the initial release. Eventually we published the first <a href="https://strongloop.com/strongblog/loopback-4-developer-preview-release" target="_blank" rel="noopener noreferrer" class="">Developer Preview</a> in November 2017, followed by more preview releases, until we finally released <a href="https://strongloop.com/strongblog/loopback-4-ga" target="_blank" rel="noopener noreferrer" class="">LoopBack 4 GA</a> in October 2018. Keeping a tight control over backlog prioritization and milestone planning allowed us to achieve this great milestone.</p>
<p>Such a tight planning worked great while it was mostly the IBM core team working on the project. On the flip side, this process made it sometimes difficult to juggle our time between working on our roadmap vs helping community contributors; and often created the impression that the core team will eventually implement all missing features, given enough time, and community contributions are not really necessary. This was acceptable while the framework offered only a limited subset of features needed to build real applications, because there were only few early adopters to support and it was indeed the core team that was contributing most of the improvements.</p>
<p>As more and more users discover and try LoopBack, they may find feature gaps, identify bugs, or even come up great ideas. If the perception is that somebody else (the core team) will eventually implement those features, then there are little incentives for users to step up and join the project as contributors. As a result, the number of maintainers is not keeping up with the growing number of users, leading to ever-increasing load on existing maintainers and eventually maintainers burning out or leaving the project. (You can read more on this topic in <a href="https://medium.com/the-node-js-collection/healthy-open-source-967fa8be7951" target="_blank" rel="noopener noreferrer" class="">Healthy Open Source</a> and <a href="https://medium.com/loopback/sustaining-loopback-project-b67fd59673e4" target="_blank" rel="noopener noreferrer" class="">Sustaining and growing LoopBack as a successful open source project</a>).</p>
<p>Many of us has experienced this ourselves in the past, when LoopBack 3 got to the stage where the maintainers were overwhelmed with the amount of incoming issues and pull requests. We feel it's time to turn the ship around and make sure we don't repeat the same mistakes in LoopBack 4. As LoopBack 4 user base grows, it is essential to grow our contributor community joining forces to enhance the framework together.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="encourage-more-community-contributions">Encourage More Community Contributions<a href="https://loopback.io/blog/2020-community-contribution#encourage-more-community-contributions" class="hash-link" aria-label="Direct link to Encourage More Community Contributions" title="Direct link to Encourage More Community Contributions" translate="no">​</a></h2>
<p>We have been always actively looking for new ways to attract more contributions from our community and grow contributors into maintainers.</p>
<p>To make it easy for our users to find easy-to-implement improvements to contribute, we are adding <code>good first issue</code> and <code>help wanted</code> labels on GitHub issues, and listing items we'd like to see progress in our roadmaps and milestones.</p>
<p>In addition, we recently made <a href="https://strongloop.com/strongblog/switching-to-dco/" target="_blank" rel="noopener noreferrer" class="">an announcement</a> about switching the contribution method to Developer Certificate of Origin (DCO) from Contributor License Agreement (CLA). We hope this will make the contribution process easier for you.</p>
<p>Going forward, we would like to focus more on enabling more of you to contribute by mentoring and coaching them to complete their PRs and providing technical guidance on their work if needed. We would also like to create more examples and starter code for experimental features, and invite the community to enhance those features collectively.</p>
<p>To further encourage community contributions, we are going to open our planning process too and start building the roadmap together with our community, based on what tasks individual contributors would like to work on.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="inspire-more-community-extensions">Inspire More Community Extensions<a href="https://loopback.io/blog/2020-community-contribution#inspire-more-community-extensions" class="hash-link" aria-label="Direct link to Inspire More Community Extensions" title="Direct link to Inspire More Community Extensions" translate="no">​</a></h2>
<p>One of the strengths of LoopBack 4 is its extensibility. You can create extensions to extend the programming model and integration capability of the LoopBack 4 framework.</p>
<p>We created a number of extensions, for example, the recently published <a href="https://github.com/strongloop/loopback-next/tree/master/extensions/typeorm" target="_blank" rel="noopener noreferrer" class="">TypeORM</a> and <a href="https://github.com/strongloop/loopback-next/tree/master/extensions/pooling" target="_blank" rel="noopener noreferrer" class="">pooling service</a> extensions. These can be served as references to inspire you to build extensions to fit your needs.</p>
<p>Moreover, we'll be working on <a href="https://github.com/strongloop/loopback-next/issues/5336" target="_blank" rel="noopener noreferrer" class="">cleaning up the extension template and documentation</a>, so that the developer experience of building an extension is smoother.</p>
<p>At the same time, we're happy to see more extensions built by the community, see the <a href="https://loopback.io/doc/en/lb4/Community-extensions.html" target="_blank" rel="noopener noreferrer" class="">community extensions page</a>. Let's build this list together by submitting a PR to include your extensions!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="potential-work-under-our-radar">Potential Work under Our Radar<a href="https://loopback.io/blog/2020-community-contribution#potential-work-under-our-radar" class="hash-link" aria-label="Direct link to Potential Work under Our Radar" title="Direct link to Potential Work under Our Radar" translate="no">​</a></h2>
<p>We have been investigating a few areas that can further improve LoopBack 4 based on our visions, even more importantly community feedbacks. There are some ideas for inspiration.</p>
<p>Modernizing the juggler has been under our radar. We would like to position LoopBack as the composition layer that brings API/microservice stories together. It will include built-in capabilities such as REST API and Data/Service access as well as integration with other frameworks. We're planning to publish a blog to cover that. Stay tuned.</p>
<p>Below are areas that we've done some initial investigation/implementation and would like to invite you to join us to build a more complete story. It includes continuing to improve our documentation and building more education materials. Likewise, we'll be publishing blog posts to share our plans and visions in the following areas:</p>
<ul>
<li class=""><a href="https://github.com/strongloop/loopback-next/tree/master/examples/multi-tenancy" target="_blank" rel="noopener noreferrer" class="">Multi-tenancy</a></li>
<li class=""><a href="https://github.com/raymondfeng/loopback4-example-websocket" target="_blank" rel="noopener noreferrer" class="">Web socket</a></li>
<li class=""><a href="https://github.com/strongloop/loopback4-example-kafka" target="_blank" rel="noopener noreferrer" class="">Kafka integration</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/pull/5545" target="_blank" rel="noopener noreferrer" class="">GraphQL</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/pull/6134" target="_blank" rel="noopener noreferrer" class="">gRPC</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="conclusion">Conclusion<a href="https://loopback.io/blog/2020-community-contribution#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion" translate="no">​</a></h2>
<p>Your contribution is important to make LoopBack a sustainable open source project. We hope our plans to adopt DCO, improve the extension development experience and focus on enabling contributors would make your contribution experience smoother and better. We are also planning on sharing our views on a few technologies.</p>
<p>Here is what you can do:</p>
<ul>
<li class=""><a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Join LoopBack Slack community</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22" target="_blank" rel="noopener noreferrer" class="">Look for first-contribution-friendly issues</a></li>
<li class="">Give us feedback and join our discussion in <a href="https://github.com/strongloop/loopback-next" target="_blank" rel="noopener noreferrer" class="">our GitHub repo</a></li>
</ul>
<p>Let's make LoopBack a better framework together!</p>]]></content:encoded>
            <category>Community</category>
        </item>
        <item>
            <title><![CDATA[Community Q&A Monthly Digest - July 2020]]></title>
            <link>https://loopback.io/blog/2020-jul-slack-qa</link>
            <guid>https://loopback.io/blog/2020-jul-slack-qa</guid>
            <pubDate>Wed, 19 Aug 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>Welcome to the July edition of the "Community Q&amp;A Monthly Digest", curating some of the Q&amp;A that we think it might be helpful to you. Let's take a look.</p>
<hr>
<p><strong>Question</strong>: Is there a built-in support in LB4 for database retries if the db responds with 429 for example? Or is it possible to overwrite a single method to implement this for all db operations similiar to how entityToData can be overwriten if data should be added to all create/update operations.</p>
<p><strong>Answer</strong>: It's better to intercept execution errors inside the datasource, not at repository level. I created a small example to demonstrate the approach. In a real app, I would extract the code into a mixin that can be applied on any DataSource class.
<a href="https://gist.github.com/bajtos/2379d7c6df31e477aaa3a3f6ea87886c" target="_blank" rel="noopener noreferrer" class="">https://gist.github.com/bajtos/2379d7c6df31e477aaa3a3f6ea87886c</a></p>
<hr>
<p><strong>Question</strong>: Is it possible to connect my API to a webhook, so that when an event is triggered, it notifies my API? What documentation could I read about doing this?</p>
<p><strong>Answer</strong>: A webhook is just another HTTP request. Depending on the architecture of the lb4 app, this request can be done in a Service, an Interceptor, or a Controller, using either the built-in Node.js API or third-party HTTP request modules such as Axios.
Besides that, no special configuration is needed for web hooks.&nbsp;</p>
<hr>
<p><strong>Question</strong>: How to implement&nbsp;<code>findOrCreate</code>&nbsp;instead&nbsp;<code>await exists</code>&nbsp;+&nbsp;<code>await create</code>?</p>
<p><strong>Answer</strong>: You can extend&nbsp;<code>DefaultCrudRepository</code>&nbsp;with&nbsp;<code>findOrCreate</code>&nbsp;’s implementation.
Then your repositories extend the custom one. Similar to&nbsp;how <code>AccountRepository</code> extends <code>MyDefaultCrudRepository</code> in the tutorial <a href="https://loopback.io/doc/en/lb4/Repositories.html#define-repositories" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/lb4/Repositories.html#define-repositories</a>.</p>
<hr>
<p><strong>Question</strong>: I started using Loopback 4. How to redirect home screen of LB4 to angular 8 running on some other port?</p>
<p><strong>Answer</strong>: It should be possible to replace the <code>.static</code> function in the app class with <code>.redirect</code>: <a href="https://loopback.io/doc/en/lb4/apidocs.rest.restapplication.redirect.html" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/lb4/apidocs.rest.restapplication.redirect.html</a>.</p>
<hr>
<p><strong>Question</strong>: The compiler throws the error <code>error TS2322: Type 'string' is not assignable to type PredicateComparison&lt;..&gt;</code> when I tried some repository CRUD methods. Is it a bug or anything wrong with my setup?</p>
<p><strong>Answer</strong>: It is a type issue. For <a href="https://loopback.io/doc/en/lb4/apidocs.repository.defaultcrudrepository.html#methods" target="_blank" rel="noopener noreferrer" class="">repository CRUD methods</a>, they may take in <code>Filter</code> or <code>Where</code> type parameters. For those cases, you will need to specify the type of it, for example:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> userCount </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">userRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">count</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">tags</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'admin'</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> Where</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">User</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> vipUser </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">userRepository</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">find</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">where</span><span class="token operator" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">tags</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'vip'</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> Filter</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">User</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<hr>
<p><strong>Question</strong>: We have a project which includes multi-tenancy based multi-database pattern (We have Common DB which stores Client Informations (Users, DB configs etc), and each clients has own database). How can I perform switching datasource dynamically with the multi-tenancy based project?</p>
<p><strong>Answer</strong>: You can check out <a href="https://github.com/strongloop/loopback-next/tree/master/examples/multi-tenancy" target="_blank" rel="noopener noreferrer" class="">the multi-tenancy example</a> and <a href="https://github.com/strongloop/loopback-next/issues/5056" target="_blank" rel="noopener noreferrer" class="">the GH issue</a> that discusses about multi-tenancy and dynamic schema selection. You can create datasources at runtime. Meanwhile, if the number of dbs is limited, you can define them upfront and reuse them, see <a href="https://loopback.io/doc/en/lb4/DataSources.html#creating-a-datasource-at-runtime" target="_blank" rel="noopener noreferrer" class="">Creating a datasource at runtime</a>. Then the tenant strategy can inject a repository talking to your common DB to load configs per logged in user.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="interested-to-join-our-slack-workspace">Interested to Join our Slack Workspace?<a href="https://loopback.io/blog/2020-jul-slack-qa#interested-to-join-our-slack-workspace" class="hash-link" aria-label="Direct link to Interested to Join our Slack Workspace?" title="Direct link to Interested to Join our Slack Workspace?" translate="no">​</a></h2>
<p>Simply click <a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">this invitation link</a> to join. You can also find more channel details here: <a href="https://github.com/strongloop/loopback-next/issues/5048" target="_blank" rel="noopener noreferrer" class="">https://github.com/strongloop/loopback-next/issues/5048</a>.</p>]]></content:encoded>
            <category>Community</category>
            <category>Slack</category>
            <category>Q&amp;A</category>
        </item>
        <item>
            <title><![CDATA[LoopBack 4 July 2020 Milestone Update]]></title>
            <link>https://loopback.io/blog/july-2020-milestone</link>
            <guid>https://loopback.io/blog/july-2020-milestone</guid>
            <pubDate>Wed, 05 Aug 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>We can't believe that it is already August! Let's check out the work we did in July:</p>
<ul>
<li class=""><a href="https://loopback.io/blog/july-2020-milestone#hasmanythrough-relation" class="">HasManyThrough Relation</a></li>
<li class=""><a href="https://loopback.io/blog/july-2020-milestone#documentation-enhancements" class="">Documentation Enhancements</a></li>
<li class=""><a href="https://loopback.io/blog/july-2020-milestone#reorganize-code-and-docs-along-abstraction-levels" class="">Reorganize Code and Docs Along Abstraction Levels</a></li>
<li class=""><a href="https://loopback.io/blog/july-2020-milestone#bug-fixes" class="">Bug Fixes</a></li>
<li class=""><a href="https://loopback.io/blog/july-2020-milestone#community-contribution" class="">Community Contribution</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="hasmanythrough-relation">HasManyThrough Relation<a href="https://loopback.io/blog/july-2020-milestone#hasmanythrough-relation" class="hash-link" aria-label="Direct link to HasManyThrough Relation" title="Direct link to HasManyThrough Relation" translate="no">​</a></h2>
<p>A <code>HasManyThrough</code> relation sets up a many-to-many connection through another model. A real-world example is a doctor has many patients through appointments. The relation can be defined with <code>@hasMany</code> decorator as:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">//...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">hasMany</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> Patient</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">through</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token function-variable function" style="color:#d73a49">model</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> Appointment</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  patients</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Patient</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>We finished most of implementation in June, and we added <code>HasManyThrough</code> to the relation CLI and also related documentation so that users could learn it better. Please make sure you have <code>@loopback/repository</code> with version 2.10.0 or higher installed.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="documentation">Documentation<a href="https://loopback.io/blog/july-2020-milestone#documentation" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h3>
<p>The <a href="https://loopback.io/doc/en/lb4/HasManyThrough-relation.html" target="_blank" rel="noopener noreferrer" class=""><code>hasManyThrough</code> Relation</a> page is being added under <a href="https://loopback.io/doc/en/lb4/Relations.html" target="_blank" rel="noopener noreferrer" class="">Relations</a> page. We introduced the use cases, definitions, and examples of how you can customize the relation to meet your requirements. Nevertheless, as mentioned in the docs, because it is an experimental feature, there are some missing functionalities such as <a href="https://github.com/strongloop/loopback-next/issues/5946" target="_blank" rel="noopener noreferrer" class=""><code>inclusionResolver</code></a>. Feel free to join discussions on GitHub or even contribute <!-- -->:D</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cli-command">CLI Command<a href="https://loopback.io/blog/july-2020-milestone#cli-command" class="hash-link" aria-label="Direct link to CLI Command" title="Direct link to CLI Command" translate="no">​</a></h3>
<p>Command line interfaces (CLI) is a convenient tool to help you create artifacts quickly. We added <code>hasManyThrough</code> relation to <code>lb4 relation</code> command. With a few prompts, you can define a <code>hasManyThrough</code> relation easily:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$ lb4 relation</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">? Please select the relation type hasManyThrough</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">? Please select source model Doctor</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">? Please select target model Patient</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">? Please select through model Appointment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">? Foreign key name that references the source model to define on the through model</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> doctorId</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">? Foreign key name that references the target model to define on the through model</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> patientId</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">? Source property name for the relation getter (will be the relation name)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> patients</span><br></span></code></pre></div></div>
<p>Don't forget to install the latest <code>@loopback/cli</code> to try it out!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="documentation-enhancements">Documentation Enhancements<a href="https://loopback.io/blog/july-2020-milestone#documentation-enhancements" class="hash-link" aria-label="Direct link to Documentation Enhancements" title="Direct link to Documentation Enhancements" translate="no">​</a></h2>
<p>One of our recent targets is to upgrade the documentation system. As you can see on the site, we reorganized most of the items in sidebar. In the overview page, the section <a href="https://loopback.io/doc/en/lb4/index.html#how-is-our-documentation-organized" target="_blank" rel="noopener noreferrer" class="">How is our documentation organized</a> introduces how you can find documentation in the four quadrants.</p>
<p>Besides improving the structure, here are some documentation enhancements we'd like to share:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="apply-jwt-authentication-component-to-shopping-example">Apply JWT Authentication Component to Shopping Example<a href="https://loopback.io/blog/july-2020-milestone#apply-jwt-authentication-component-to-shopping-example" class="hash-link" aria-label="Direct link to Apply JWT Authentication Component to Shopping Example" title="Direct link to Apply JWT Authentication Component to Shopping Example" translate="no">​</a></h3>
<p>The <a href="https://github.com/strongloop/loopback-next/tree/master/extensions/authentication-jwt" target="_blank" rel="noopener noreferrer" class=""><code>@loopback/authentication-jwt</code></a> component was created to make adding JWT authentication to your application earlier. We've applied it to the <a href="https://github.com/strongloop/loopback4-example-shopping" target="_blank" rel="noopener noreferrer" class="">shopping example</a>. To find out more, see the <a href="https://loopback.io/doc/en/lb4/JWT-authentication-extension.html" target="_blank" rel="noopener noreferrer" class="">JWT authentication extension documentation page</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-to-access-multiple-models-in-a-single-transaction">How to Access Multiple Models in a Single Transaction<a href="https://loopback.io/blog/july-2020-milestone#how-to-access-multiple-models-in-a-single-transaction" class="hash-link" aria-label="Direct link to How to Access Multiple Models in a Single Transaction" title="Direct link to How to Access Multiple Models in a Single Transaction" translate="no">​</a></h3>
<p>A <em>transaction</em> is a sequence of data operations performed as a single logical
unit of work. LoopBack 4 has many relational database connectors support such logic requirements. We added a section <a href="https://loopback.io/doc/en/lb4/Using-database-transactions.html#accessing-multiple-models-inside-one-transaction" target="_blank" rel="noopener noreferrer" class="">Accessing multiple models inside one transaction</a> to show how it can be achieved.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="custom-ajv-validation">Custom AJV Validation<a href="https://loopback.io/blog/july-2020-milestone#custom-ajv-validation" class="hash-link" aria-label="Direct link to Custom AJV Validation" title="Direct link to Custom AJV Validation" translate="no">​</a></h3>
<p>We realized that the current AJV Validation documentation is missing a crucial information piece on how to enable custom validation and error messages. Please check out the section <a href="https://loopback.io/doc/en/lb4/Model.html#custom-validation-rules-and-error-messages" target="_blank" rel="noopener noreferrer" class="">Custom validation rules and error messages</a> and <a href="https://github.com/strongloop/loopback-next/tree/master/examples/validation-app" target="_blank" rel="noopener noreferrer" class="">Validation example</a> for details.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="reorganize-code-and-docs-along-abstraction-levels">Reorganize Code and Docs Along Abstraction Levels<a href="https://loopback.io/blog/july-2020-milestone#reorganize-code-and-docs-along-abstraction-levels" class="hash-link" aria-label="Direct link to Reorganize Code and Docs Along Abstraction Levels" title="Direct link to Reorganize Code and Docs Along Abstraction Levels" translate="no">​</a></h2>
<p>As LoopBack 4 is growing larger, we decide to hide some low-level tools from users so that the framework looks neat and friendly. In July, we hid module <a href="https://github.com/strongloop/loopback-next/tree/master/packages/openapi-v3" target="_blank" rel="noopener noreferrer" class=""><code>@loopback/openapi-v3</code></a> as it can be loaded from <a href="https://github.com/strongloop/loopback-next/tree/master/packages/rest" target="_blank" rel="noopener noreferrer" class=""><code>@loopback/rest</code></a>.</p>
<p>We removed <code>@loopback/openapi-v3</code> from dependencies and also our CLI template dependencies. If you check the page <a href="https://loopback.io/doc/en/lb4/Extending-OpenAPI-specification.html" target="_blank" rel="noopener noreferrer" class="">Extending OpenAPI Specification</a> or other related pages, you will notice it is now hidden and replaced by <code>@loopback/rest</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="execute-raw-nosql-queries">Execute Raw NoSQL Queries<a href="https://loopback.io/blog/july-2020-milestone#execute-raw-nosql-queries" class="hash-link" aria-label="Direct link to Execute Raw NoSQL Queries" title="Direct link to Execute Raw NoSQL Queries" translate="no">​</a></h2>
<p>If you have a SQL database as back-end service, you can execute raw queries using the <code>execute</code> method that we have in <code>Repository</code>, and it works great. Unfortunately, <code>execute</code> does not work for NoSQL connectors such as MongoDB as they require more than just a <code>command</code> string and <code>args</code> array.</p>
<p>In July, we started working on how we can improve LB4 API and MongoDB connector API to make it easy to execute raw MongoDB commands. We added a <code>DataSource.execute</code> method to the Juggler, and leveraged it to support different <code>execute</code> styles. We also added support for non-SQL variants of <code>Repository.execute()</code> in the <code>loopback/repository</code> module. More works will be done in August. You can check the progress in story <a href="https://github.com/strongloop/loopback-next/issues/3342" target="_blank" rel="noopener noreferrer" class="">Execute raw NoSQL queries</a> on GitHub if you're interested.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="bug-fixes">Bug Fixes<a href="https://loopback.io/blog/july-2020-milestone#bug-fixes" class="hash-link" aria-label="Direct link to Bug Fixes" title="Direct link to Bug Fixes" translate="no">​</a></h2>
<p>There was a story that a boy woke up in one morning and found himself transformed into a gigantic bug. We don't want that to happen, so we fixed a few bugs in July:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="unable-to-perform-nested-filters">Unable to Perform Nested Filters<a href="https://loopback.io/blog/july-2020-milestone#unable-to-perform-nested-filters" class="hash-link" aria-label="Direct link to Unable to Perform Nested Filters" title="Direct link to Unable to Perform Nested Filters" translate="no">​</a></h3>
<p>As we added the support for coercing query object with schema last month, it exposed a bug that the nested scope filters don't have the correct constraints. It is being fixed and released in <code>@loopback/rest@5.2.1</code>. Now you can include nested navigational properties using filter like:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  include</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      relation</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"orders"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      scope</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// nested relation</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        include</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            relation</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"someOtherRelation"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token operator" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="query-with-dollar-signs-in-mongodb-connector">Query with Dollar Signs in MongoDB Connector<a href="https://loopback.io/blog/july-2020-milestone#query-with-dollar-signs-in-mongodb-connector" class="hash-link" aria-label="Direct link to Query with Dollar Signs in MongoDB Connector" title="Direct link to Query with Dollar Signs in MongoDB Connector" translate="no">​</a></h3>
<p>If you're using MongoDB, you would be used to have dollar signs ($) in your queries. However, the dollar signs are not needed in LB4 general queries, and that's why <a href="https://github.com/strongloop/loopback-connector-mongodb" target="_blank" rel="noopener noreferrer" class="">loopback-mongodb-connector</a> users get confused usually. To improve the user experience, we made some changes in the connector <a href="https://github.com/strongloop/loopback-connector-mongodb" target="_blank" rel="noopener noreferrer" class="">loopback-mongodb-connector</a>, so that the connector users won't get errors even if the queries contain extra dollar signs. The change is released in <code>@loopback-connector-mongodb@5.3.0</code></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="community-contribution">Community Contribution<a href="https://loopback.io/blog/july-2020-milestone#community-contribution" class="hash-link" aria-label="Direct link to Community Contribution" title="Direct link to Community Contribution" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-community-maintainers">New Community Maintainers<a href="https://loopback.io/blog/july-2020-milestone#new-community-maintainers" class="hash-link" aria-label="Direct link to New Community Maintainers" title="Direct link to New Community Maintainers" translate="no">​</a></h3>
<p>We are glad to have <a href="https://github.com/nabdelgadir" target="_blank" rel="noopener noreferrer" class="">@nabdelgadir</a> and <a href="https://github.com/madaky" target="_blank" rel="noopener noreferrer" class="">@madaky</a> to be one of our community maintainers. We appreciate your great work you've done and welcome to the team.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="highlights">Highlights<a href="https://loopback.io/blog/july-2020-milestone#highlights" class="hash-link" aria-label="Direct link to Highlights" title="Direct link to Highlights" translate="no">​</a></h3>
<ul>
<li class="">As LoopBack 4 is designed to be more scalable and extensible, there are numbers of extensions created by the open source community. You may find some interesting and helpful extensions under the <a href="https://loopback.io/doc/en/lb4/Community-extensions.html" target="_blank" rel="noopener noreferrer" class="">Community extensions</a> page. We are also considering adding example usages of LB4 from the community. Please let us know if you got any great extensions or examples you would like to share with us!</li>
<li class="">The community user <a href="https://github.com/zyqVizzzzz" target="_blank" rel="noopener noreferrer" class="">@zyqVizzzzz</a> translated several tutorials for LB4 in Chinese. They can be found in the page <a href="https://loopback.io/doc/zh/lb4/Tutorials" target="_blank" rel="noopener noreferrer" class="">教程（Tutorials）</a>. We really appreciate it! If you're interested in translating LB4 documentation, the instructions can be found in the page <a href="https://loopback.io/doc/en/contrib/translation.html" target="_blank" rel="noopener noreferrer" class="">Translation</a>.</li>
</ul>
<p>In order to make your contribution process simpler, we will be gradually changing the contribution method from Contribution License Agreement (CLA) to Developer Certificate of Origin (DCO). Take a look at <a href="https://strongloop.com/strongblog/switching-to-dco/" target="_blank" rel="noopener noreferrer" class="">this blog</a> to find out what the changes are and what it means to you.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="whats-next">What's Next?<a href="https://loopback.io/blog/july-2020-milestone#whats-next" class="hash-link" aria-label="Direct link to What's Next?" title="Direct link to What's Next?" translate="no">​</a></h2>
<p>If you're interested in what we're working on next, you can check out the <a href="https://github.com/strongloop/loopback-next/pull/6028" target="_blank" rel="noopener noreferrer" class="">August Milestone</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="call-to-action">Call to Action<a href="https://loopback.io/blog/july-2020-milestone#call-to-action" class="hash-link" aria-label="Direct link to Call to Action" title="Direct link to Call to Action" translate="no">​</a></h2>
<p>In 2020, we look forward to helping you and seeing you around! LoopBack's success depends on you. We appreciate your continuous support and engagement to make LoopBack even better and meaningful for your API creation experience. Here's how you can join us and help the project:</p>
<ul>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues" target="_blank" rel="noopener noreferrer" class="">Report issues</a>.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/blob/master/docs/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer" class="">Contribute</a> code and documentation.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/labels/good%20first%20issue" target="_blank" rel="noopener noreferrer" class="">Open a pull request on one of our "good first issues"</a>.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues/110" target="_blank" rel="noopener noreferrer" class="">Join</a> our user group.</li>
</ul>]]></content:encoded>
            <category>Milestone update</category>
        </item>
        <item>
            <title><![CDATA[Making Your Contribution Process Simpler - Switching from CLA to DCO]]></title>
            <link>https://loopback.io/blog/switching-to-dco</link>
            <guid>https://loopback.io/blog/switching-to-dco</guid>
            <pubDate>Wed, 29 Jul 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>Since the beginning of the LoopBack project, we have been using the Contributor License Agreement (CLA) as the contribution method. Contributors need to sign each CLA for each LoopBack repository they're contributing. To simplify the contribution process and encourage community contributions, we are planning to gradually switch to use <a href="https://developercertificate.org/" target="_blank" rel="noopener noreferrer" class="">Developer Certificate of Origin (DCO)</a> as the contribution method.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-developer-certificate-of-origin-dco">What Is Developer Certificate of Origin (DCO)?<a href="https://loopback.io/blog/switching-to-dco#what-is-developer-certificate-of-origin-dco" class="hash-link" aria-label="Direct link to What Is Developer Certificate of Origin (DCO)?" title="Direct link to What Is Developer Certificate of Origin (DCO)?" translate="no">​</a></h2>
<p>As an alternative to CLA, a Developer Ceritifcate of Origin (DCO) is a more lightweight contribution method. According to <a href="https://en.wikipedia.org/wiki/Developer_Certificate_of_Origin" target="_blank" rel="noopener noreferrer" class="">Wikipedia</a>:</p>
<blockquote>
<p>Instead a signed legal contract, a DCO is an affirmation that the source code being submitted originated from the developer, or that the developer has permission to submit the code.</p>
</blockquote>
<p>The full text of DCO can be found: <a href="https://developercertificate.org/" target="_blank" rel="noopener noreferrer" class="">https://developercertificate.org/</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-are-we-switching">Why Are We Switching?<a href="https://loopback.io/blog/switching-to-dco#why-are-we-switching" class="hash-link" aria-label="Direct link to Why Are We Switching?" title="Direct link to Why Are We Switching?" translate="no">​</a></h2>
<p>Community contributions are vital to the success of LoopBack. Since DCO simply needs your affirmation that you are the one who is submitting the code, we hope this switch would make the contribution process simpler and thus encourages more contributions from you!</p>
<p>In addition, this change can help us to reduce the infrastructure cost, including the team's time and effort, to maintain the CLA server.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-does-it-mean-to-you">What Does It Mean To You?<a href="https://loopback.io/blog/switching-to-dco#what-does-it-mean-to-you" class="hash-link" aria-label="Direct link to What Does It Mean To You?" title="Direct link to What Does It Mean To You?" translate="no">​</a></h2>
<p>Currently, the <a href="https://github.com/strongloop/loopback4-example-shopping" target="_blank" rel="noopener noreferrer" class="">loopback4-example-shopping</a> is already using DCO.</p>
<p>To sign off the commit, you can:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">git commit -s -m "feat: my commit message"</span><br></span></code></pre></div></div>
<p>Over the next little while, we'll start the switch for the repositories with the most community contributions, namely <a href="https://github.com/strongloop/loopback-next" target="_blank" rel="noopener noreferrer" class="">loopback-next</a>, <a href="https://github.com/strongloop/loopback.io" target="_blank" rel="noopener noreferrer" class="">loopback.io</a> and <a href="https://github.com/strongloop/loopback-datasource-juggler" target="_blank" rel="noopener noreferrer" class="">loopback-datasource-juggler</a>, then we'll roll it out for the connector repos.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="start-contributing">Start Contributing!<a href="https://loopback.io/blog/switching-to-dco#start-contributing" class="hash-link" aria-label="Direct link to Start Contributing!" title="Direct link to Start Contributing!" translate="no">​</a></h2>
<p>You are more than welcome to contribute on something that you find it relevant and interesting to you. If you're simply looking for items that we want help, you can look for GitHub issues with <a href="https://github.com/issues?q=is%3Aopen+is%3Aissue+archived%3Afalse+user%3Astrongloop+label%3A%22help+wanted%22" target="_blank" rel="noopener noreferrer" class=""><code>help wanted</code></a> or <a href="https://github.com/issues?q=is%3Aopen+is%3Aissue+archived%3Afalse+user%3Astrongloop+label%3A%22good+first+issue%22" target="_blank" rel="noopener noreferrer" class=""><code>good first issue</code></a> labels.</p>
<p>More questions? Feel free to ask in the #loopback-contributors channel of the <a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">LoopBack Slack community</a>.</p>]]></content:encoded>
            <category>Community</category>
            <category>Contribution</category>
        </item>
        <item>
            <title><![CDATA[Community Q&A Monthly Digest - Jun 2020]]></title>
            <link>https://loopback.io/blog/2020-Jun-slack-qa</link>
            <guid>https://loopback.io/blog/2020-Jun-slack-qa</guid>
            <pubDate>Thu, 16 Jul 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>Welcome back to the "Community Q&amp;A Monthly Digest", in which we highlight some of the questions and answers in <a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">our LoopBack Slack community</a> here.</p>
<p><strong>Question:</strong> Has anyone implemented Casbin on a brand new project? or is there a good tutorial for lb4? I need to have some rbac / roles system in an app.. or what would you suggest to achieve that?</p>
<p><strong>Answer:</strong> We have an access control example uses casbin, see the <a href="https://github.com/strongloop/loopback-next/tree/master/examples/access-control-migration" target="_blank" rel="noopener noreferrer" class="">access-control-migration example</a> and <a href="https://loopback.io/doc/en/lb4/migration-auth-access-control-example.html" target="_blank" rel="noopener noreferrer" class="">its tutorial</a>. The logic on casbin side is only a prototype, the example mainly shows the integration between casbin and LoopBack authorization system.</p>
<hr>
<p><strong>Question:</strong> I am new to LoopBack and so far I really like what it has to offer. I was wondering if anyone knows of a good online course to learn LoopBack. I have worked through the basic tutorials found in the documentation, but I find it easier to listen and follow along to videos.</p>
<p><strong>Answer:</strong> Recently one of our community member posts a <a href="https://www.youtube.com/watch?v=cgBCRY169qg" target="_blank" rel="noopener noreferrer" class="">YouTube tutorial for LoopBack 4 beginners</a>. There is another series of educational videos on <a href="https://www.youtube.com/watch?v=pDGWb-q65qM" target="_blank" rel="noopener noreferrer" class="">a LoopBack introduction</a> and <a href="https://www.youtube.com/watch?v=1U9ZCDlBtjc" target="_blank" rel="noopener noreferrer" class="">installation</a>.</p>
<p>From our side, there are a few recent videos on our <a href="https://www.youtube.com/channel/UCR8LLOxVNwSEWLMqoZzQNXw/videos" target="_blank" rel="noopener noreferrer" class="">StrongLoop YouTube channel</a> and we're trying to add more. Hope it helps.</p>
<hr>
<p><strong>Question:</strong> I am trying to disable the openapi.json from showing in my loopback 4 application and its not working. I was able to disable the explorer. Any ideas?</p>
<p><strong>Answer:</strong> You can use <code>openApiSpec: {disabled: true}</code> in <code>index.ts</code>. i.e.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> config </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    rest</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic">//..</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      openApiSpec</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        disabled</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">//..</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<hr>
<p><strong>Question:</strong> Does Loopback 4 support extracting cookies from the header? Currently I had to integrate Express server to achieve this.</p>
<p><strong>Answer:</strong> You can use express middleware like <a href="http://expressjs.com/en/resources/middleware/cookie-parser.html" target="_blank" rel="noopener noreferrer" class="">http://expressjs.com/en/resources/middleware/cookie-parser.html</a> see how to use middleware in <a href="https://loopback.io/doc/en/lb4/Express-middleware.html" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/lb4/Express-middleware.html</a>.</p>
<hr>
<p><strong>Question:</strong> Is there a quick way to generate timestamp? Like at the model level <code>generated:true</code>?</p>
<p><strong>Answer:</strong> I recommend to use defaultFn set to one of the following string values:</p>
<ul>
<li class="">"guid": generate a new globally unique identifier (GUID) using the computer MAC address and current time (UUID version 1).</li>
<li class="">"uuid": generate a new universally unique identifier (UUID) using the computer MAC address and current time (UUID version 1).</li>
<li class="">"uuidv4": generate a new universally unique identifier using the UUID version 4 algorithm.</li>
<li class="">"now": use the current date and time as returned by new Date()</li>
</ul>
<p>See also <a href="https://github.com/strongloop/loopback/issues/292" target="_blank" rel="noopener noreferrer" class="">https://github.com/strongloop/loopback/issues/292</a> and <a href="https://loopback.io/doc/en/lb4/Model.html#property-decorator" target="_blank" rel="noopener noreferrer" class="">https://loopback.io/doc/en/lb4/Model.html#property-decorator</a>.</p>
<p>It would be great to capture these options in our TypeScript definitions, see <a href="https://github.com/strongloop/loopback-next/blob/ae6427322451c914ae54f44dbb656981e7fbbb81/packages/repository/src/model.ts#L34-L42" target="_blank" rel="noopener noreferrer" class="">https://github.com/strongloop/loopback-next/blob/ae6427322451c914ae54f44dbb656981e7fbbb81/packages/repository/src/model.ts#L34-L42</a>.</p>
<hr>
<p><strong>Question:</strong> Can I use MongoDB update operators in LoopBack apps? How can I enable it?</p>
<p><strong>Answer:</strong> Yes, except comparison and logical operators, the mongo connector also supports MongoDB update operators such as <code>max</code>, <code>rename</code>, etc. You will need to set the flag <code>allowExtendedOperators</code> to <code>true</code> in the datasource configuration. You can find details and examples at <a href="https://loopback.io/doc/en/lb4/MongoDB-connector.html#update-operators" target="_blank" rel="noopener noreferrer" class="">MongoDB connector - update operators</a>.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="interested-to-join-our-slack-workspace">Interested to Join our Slack Workspace?<a href="https://loopback.io/blog/2020-Jun-slack-qa#interested-to-join-our-slack-workspace" class="hash-link" aria-label="Direct link to Interested to Join our Slack Workspace?" title="Direct link to Interested to Join our Slack Workspace?" translate="no">​</a></h2>
<p>Simply click <a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">this invitation link</a> to join. You can also find more channel details here: <a href="https://github.com/strongloop/loopback-next/issues/5048" target="_blank" rel="noopener noreferrer" class="">https://github.com/strongloop/loopback-next/issues/5048</a>.</p>]]></content:encoded>
            <category>Community</category>
            <category>Slack</category>
            <category>Q&amp;A</category>
        </item>
        <item>
            <title><![CDATA[LoopBack 4 2020 Q2 Overview]]></title>
            <link>https://loopback.io/blog/loopback-4-2020-q2-overview</link>
            <guid>https://loopback.io/blog/loopback-4-2020-q2-overview</guid>
            <pubDate>Tue, 14 Jul 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>Over the recent months, this global pandemic has affected our lives in different ways; we hope you all stay safe during these difficult times. The LoopBack team has adapted to new ways of working, including virtually and in new settings. Even though it could be challenging sometimes, we are glad that we were able to complete most of our Q2 plan. Thanks to all the support from the team and the community!</p>
<p>Here's a brief look at the Q2 summary:</p>
<ul>
<li class=""><a href="https://loopback.io/blog/loopback-4-2020-q2-overview#migration-guide" class="">Migration Guide</a></li>
<li class=""><a href="https://loopback.io/blog/loopback-4-2020-q2-overview#enhancing-documentation" class="">Enhancing Documentation</a></li>
<li class=""><a href="https://loopback.io/blog/loopback-4-2020-q2-overview#leveraging-authentication-system" class="">Leveraging Authentication System</a></li>
<li class=""><a href="https://loopback.io/blog/loopback-4-2020-q2-overview#apic/lb4-integration" class="">APIC/LB4 Integration</a></li>
<li class=""><a href="https://loopback.io/blog/loopback-4-2020-q2-overview#other-highlights" class="">Other Highlights</a></li>
<li class=""><a href="https://loopback.io/blog/loopback-4-2020-q2-overview#building-loopBack-community" class="">Building LoopBack Community</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="migration-guide">Migration Guide<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#migration-guide" class="hash-link" aria-label="Direct link to Migration Guide" title="Direct link to Migration Guide" translate="no">​</a></h2>
<p>One of our main targets in Q2 was to finish the migration guide, and we did it! We accomplished all the items on the <a href="https://github.com/strongloop/loopback-next/issues/453" target="_blank" rel="noopener noreferrer" class="">migration plan</a>. The <a href="https://loopback.io/doc/en/lb4/migration-overview.html" target="_blank" rel="noopener noreferrer" class="">Migration guide</a> can be found easily on the LB4 home page. We have instructions that helps you migrate various artifacts and also have docs to explain similarities and differences between LB3 and LB4. From request/response infrastructure to datasource setup, from model definitions to the authentication and authorization, we hope the guide is useful for you when migrating your LoopBack 3 applications to LoopBack 4.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="enhancing-documentation">Enhancing Documentation<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#enhancing-documentation" class="hash-link" aria-label="Direct link to Enhancing Documentation" title="Direct link to Enhancing Documentation" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-documentation-structure">New Documentation Structure<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#new-documentation-structure" class="hash-link" aria-label="Direct link to New Documentation Structure" title="Direct link to New Documentation Structure" translate="no">​</a></h3>
<p>This quarter, one of our targets was to upgrade the documentation system. As we are adding more features and documentation to LoopBack 4, the abundant amount of sidebar entries was overwhelming and difficult to navigate with the old documentation system. We reorganized most of them into the following four parts:</p>
<ul>
<li class="">"Tutorials"</li>
<li class="">"How-to guides"</li>
<li class="">"Behind the scenes"</li>
<li class="">"References guides"</li>
</ul>
<p>For example, if you'd like to learn how you can secure your LoopBack 4 application, now you can find it easily under the "Tutorials" sections instead of searching through the whole path "Concept -&gt; Authentication -&gt; Authentication tutorial".</p>
<p>Moreover, we also started working on reorganizing most of our documentation to focus on framework-level APIs and de-emphasizing the lower-level building blocks to reduce the complexity. For example, we removed <code>@loopback/express</code> from framework-level documentation and replaced references to use <code>@loopback/rest instead</code>.</p>
<p>This is just the first step of our long journey of improving the documentation system. Please let us know if you have any feedback.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="rewriting-your-favorite-lb3-content-to-loopback-4">Rewriting your favorite LB3 content to LoopBack 4<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#rewriting-your-favorite-lb3-content-to-loopback-4" class="hash-link" aria-label="Direct link to Rewriting your favorite LB3 content to LoopBack 4" title="Direct link to Rewriting your favorite LB3 content to LoopBack 4" translate="no">​</a></h3>
<p>We've been using shared content for some topics in both LB3 and LB4, but this might be confusing if the user is not familiar with LB3. To reduce the gap between these two versions, we also rewrote some documentation from LB3 in LB4 style. For example, now you can check usage examples written in LB4 style for the Filters under the page <a href="https://loopback.io/doc/en/lb4/Working-with-data.html" target="_blank" rel="noopener noreferrer" class="">Working with data</a>. What's more is that we also created tutorials for connecting to <a href="https://loopback.io/doc/en/lb4/Connecting-to-MySQL.html" target="_blank" rel="noopener noreferrer" class="">MySQL</a>, <a href="https://loopback.io/doc/en/lb4/Connecting-to-Oracle.html" target="_blank" rel="noopener noreferrer" class="">Oracle</a>, <a href="https://loopback.io/doc/en/lb4/Connecting-to-PostgreSQL.html" target="_blank" rel="noopener noreferrer" class="">PostgreSQL</a>, and <a href="https://loopback.io/doc/en/lb4/Connecting-to-MongoDB.html" target="_blank" rel="noopener noreferrer" class="">MongoDB</a> databases. By following the steps in these tutorials, you'll find it easy to connect to databases with LB4 applications.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="leveraging-authentication-system">Leveraging Authentication System<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#leveraging-authentication-system" class="hash-link" aria-label="Direct link to Leveraging Authentication System" title="Direct link to Leveraging Authentication System" translate="no">​</a></h2>
<p>The authentication system has changed a lot since it was being used as an experimental feature. It is now more reliable and flexible. We improved it in the following aspects:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="examples">Examples<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#examples" class="hash-link" aria-label="Direct link to Examples" title="Direct link to Examples" translate="no">​</a></h3>
<p>We added two examples for different authentication strategies:</p>
<ul>
<li class="">
<p><a href="https://github.com/strongloop/loopback-next/tree/master/examples/todo-jwt" target="_blank" rel="noopener noreferrer" class="">TODO example with JWT</a> demos enabling JWT authentication in the Todo application. This is a good example for beginners to follow the authentication system.</p>
</li>
<li class="">
<p><a href="https://github.com/strongloop/loopback-next/tree/master/examples/passport-login" target="_blank" rel="noopener noreferrer" class="">Passport Login example</a> shows how to use <a href="http://www.passportjs.org/docs/" target="_blank" rel="noopener noreferrer" class="">Passport Strategies</a> in LoopBack 4. If you are using the loopback-component-passport in LoopBack 3, this example can help you migrate your application to LoopBack 4.</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="documentation">Documentation<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#documentation" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h3>
<p>We reorganized the authentication documentation to make it more easy to adopt. Instead of throwing all the details to users, now the <a href="https://loopback.io/doc/en/lb4/Authentication-overview.html" target="_blank" rel="noopener noreferrer" class="">authentication docs</a> starts with a simple high-level explanation, then it walks through users with several examples with different difficulties to show what the system is capable of and how they can be achieved.</p>
<p>Besides, as we mentioned above, we also added page <a href="https://loopback.io/doc/en/lb4/migration-auth-overview.html" target="_blank" rel="noopener noreferrer" class="">Migrating authentication and authorization</a> as part of the migration plan as well.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="apiclb4-integration">APIC/LB4 Integration<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#apiclb4-integration" class="hash-link" aria-label="Direct link to APIC/LB4 Integration" title="Direct link to APIC/LB4 Integration" translate="no">​</a></h2>
<p><a href="https://developer.ibm.com/apiconnect/" target="_blank" rel="noopener noreferrer" class="">API Connect</a> is a complete, intuitive and scalable API platform provided by IBM.</p>
<p>In Q2, we completed the integration of LoopBack 4 with API Connect v10 which was released in June. When a LoopBack application is scaffolded through the APIC toolkit, the LoopBack-generated OpenAPIv3 spec comes with API Connect specific metadata added, thanks to the <a href="https://github.com/strongloop/loopback-next/tree/master/extensions/apiconnect" target="_blank" rel="noopener noreferrer" class="">LoopBack APIConnect extension</a>. If you're interested, we've been preparing an article on how you can take the APIs created from LoopBack and import them into API Connect for API management. Stay tuned!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="other-highlights">Other Highlights<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#other-highlights" class="hash-link" aria-label="Direct link to Other Highlights" title="Direct link to Other Highlights" translate="no">​</a></h2>
<p>Here are some highlights of our work we would like to share!</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="supporting-typeorm">Supporting TypeORM<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#supporting-typeorm" class="hash-link" aria-label="Direct link to Supporting TypeORM" title="Direct link to Supporting TypeORM" translate="no">​</a></h3>
<p>You might decide to use an alternative ORM/ODM in your LoopBack 4 application, and LoopBack 4 also has such flexibility as it no longer expects you to provide your data in its own custom Model format for routing purposes, which means you are free to alter your classes to suit these ORMs/ODMs.</p>
<p><a href="https://typeorm.io/#/" target="_blank" rel="noopener noreferrer" class="">TypeORM</a> is an ORM that can run in NodeJS and others platforms and can be used with TypeScript and JavaScript, which fits LoopBack 4 well. We implemented initial support for TypeORM in LoopBack 4 in the <code>@loopback/typeorm</code> package. Please check the <a href="https://github.com/strongloop/loopback-next/blob/master/packages/typeorm/README.md" target="_blank" rel="noopener noreferrer" class="">README</a> file for the usage and limitations.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="express-middleware">Express Middleware<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#express-middleware" class="hash-link" aria-label="Direct link to Express Middleware" title="Direct link to Express Middleware" translate="no">​</a></h3>
<p>LoopBack 4 leverages Express behind the scenes for its REST server implementation. The new <a href="https://github.com/strongloop/loopback-next/tree/master/packages/express" target="_blank" rel="noopener noreferrer" class="">Express Package</a>, has enabled injecting single and multiple express middleware functions as <code>Interceptor</code>s into <code>Controller</code> invocations and also as a middleware step in the application <code>Sequence</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="component-application-booter">Component Application Booter<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#component-application-booter" class="hash-link" aria-label="Direct link to Component Application Booter" title="Direct link to Component Application Booter" translate="no">​</a></h3>
<p>Sometimes it might be the case that we want to break our complex application into multiple smaller LoopBack applications. The component application booter composes these sub applications into the main application. This is helpful for building a scalable micro-services application. See the page <a href="https://loopback.io/doc/en/lb4/Booting-an-Application.html" target="_blank" rel="noopener noreferrer" class="">Booting an Application</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="hasmanythrough-relation">HasManyThrough Relation<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#hasmanythrough-relation" class="hash-link" aria-label="Direct link to HasManyThrough Relation" title="Direct link to HasManyThrough Relation" translate="no">​</a></h3>
<p>With help from the community users, the experimental feature <a href="https://github.com/strongloop/loopback-next/blob/master/packages/repository/src/relations/has-many/has-many-through.repository.ts" target="_blank" rel="noopener noreferrer" class=""><code>HasManyThrough</code> relation</a> is added to LB4. Currently it only has some basic functionalities. The documentation and related CLI will be updated in the near future.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="run-tests-in-parallel">Run Tests in Parallel<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#run-tests-in-parallel" class="hash-link" aria-label="Direct link to Run Tests in Parallel" title="Direct link to Run Tests in Parallel" translate="no">​</a></h3>
<p>We upgraded <code>mocha</code> to the new version 8, and it enable parallel execution of Mocha tests. With the option, we can control the number of worker processes and make the testing process more efficient. Details can be found in <a href="https://loopback.io/doc/en/lb4/code-contrib-lb4.html#running-tests" target="_blank" rel="noopener noreferrer" class="">Running tests</a> section.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="extensions">Extensions<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#extensions" class="hash-link" aria-label="Direct link to Extensions" title="Direct link to Extensions" translate="no">​</a></h3>
<p>Extensions/Extension points is one of the main features of LB4 to make the application extensible. We added the following two extensions in Q2:</p>
<ul>
<li class="">
<p>JWT authentication: as the authentication system gets popular and more solid, we extracted the JWT authentication system into a separate extension package as an experimental feature, so that users can quickly mount a component to try out the feature. Check <a href="https://github.com/strongloop/loopback-next/tree/master/extensions/authentication-jwt" target="_blank" rel="noopener noreferrer" class=""><code>authentication-jwt</code></a> for details.</p>
</li>
<li class="">
<p>LoopBack APIConnect extension: the <a href="https://github.com/strongloop/loopback-next/tree/master/extensions/apiconnect" target="_blank" rel="noopener noreferrer" class="">LoopBack APIConnect extension</a> is ready for use. It provides <code>ApiConnectComponent</code> that adds an <code>OASEnhencer</code> extension to contribute <code>x-ibm-configuration</code> to the OpenAPI spec generated by LoopBack applications.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="building-loopback-community">Building LoopBack Community<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#building-loopback-community" class="hash-link" aria-label="Direct link to Building LoopBack Community" title="Direct link to Building LoopBack Community" translate="no">​</a></h2>
<p>We're happy to see more users/developers join our community. We appreciate all the help! We've opened a public <a href="https://slack.com/" target="_blank" rel="noopener noreferrer" class="">Slack</a> channel so that developers can ask questions, discuss issues, and share their knowledge to help each other easily.</p>
<p>We also had a several video-calls with LoopBack maintainers. It's nice to get to know each other, share the plans &amp; visions and discuss topics by talking together. Let's continue building LoopBack a better framework together.</p>
<p>Wanna join us? Yes! You're invited <!-- -->👉<!-- --> <a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Join LoopBack Channel on Slack</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="previous-milestone-blogs">Previous Milestone Blogs<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#previous-milestone-blogs" class="hash-link" aria-label="Direct link to Previous Milestone Blogs" title="Direct link to Previous Milestone Blogs" translate="no">​</a></h2>
<p>There are many more accomplishments that cannot be captured in this blog, make sure you check out our previously published monthly milestone blog posts in Q2 for more details:</p>
<ul>
<li class=""><a href="https://strongloop.com/strongblog/april-2020-milestone/" target="_blank" rel="noopener noreferrer" class="">April 2020</a></li>
<li class=""><a href="https://strongloop.com/strongblog/may-2020-milestone/" target="_blank" rel="noopener noreferrer" class="">May 2020</a></li>
<li class=""><a href="https://strongloop.com/strongblog/june-2020-milestone/" target="_blank" rel="noopener noreferrer" class="">June 2020</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="whats-next">What's Next?<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#whats-next" class="hash-link" aria-label="Direct link to What's Next?" title="Direct link to What's Next?" translate="no">​</a></h2>
<p>We have published a blog <a href="https://strongloop.com/strongblog/2020-goals/" target="_blank" rel="noopener noreferrer" class="">LoopBack - 2020 Goals and Focus</a> about our plans this year. Here is a summary of the <a href="https://github.com/strongloop/loopback-next/blob/master/docs/ROADMAP.md#q3-2020-roadmap" target="_blank" rel="noopener noreferrer" class="">Q3 2020 roadmap</a>:</p>
<ul>
<li class="">finish migration guide for both general runtime and authentication &amp; authorization</li>
<li class="">continue with API Connect and LoopBack integration</li>
<li class="">look into feature parity gaps that are highly requested by users</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="call-to-action">Call to Action<a href="https://loopback.io/blog/loopback-4-2020-q2-overview#call-to-action" class="hash-link" aria-label="Direct link to Call to Action" title="Direct link to Call to Action" translate="no">​</a></h2>
<p>In 2020, we look forward to helping you and seeing you around! LoopBack's success depends on you. We appreciate your continuous support and engagement to make LoopBack even better and meaningful for your API creation experience. Here's how you can join us and help the project:</p>
<ul>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues" target="_blank" rel="noopener noreferrer" class="">Report issues</a>.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/blob/master/docs/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer" class="">Contribute</a> code and documentation.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/labels/good%20first%20issue" target="_blank" rel="noopener noreferrer" class="">Open a pull request on one of our "good first issues"</a>.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues/110" target="_blank" rel="noopener noreferrer" class="">Join</a> our user group.</li>
</ul>]]></content:encoded>
            <category>Quarterly update</category>
        </item>
        <item>
            <title><![CDATA[LoopBack 4 June 2020 Milestone Update]]></title>
            <link>https://loopback.io/blog/june-2020-milestone</link>
            <guid>https://loopback.io/blog/june-2020-milestone</guid>
            <pubDate>Wed, 08 Jul 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>Documentation restructuring, TypeORM support, and HasManyThrough were the three main accomplishments in the month of June. Based on the community feedback, documentation improvement remains our number one priority in the coming month. Besides, while welcoming Nathan Chen join as a maintainer of the <code>strong-globalize</code> repo, we said farewell to Deepak.</p>
<p>Here is what we did in the month June:</p>
<ul>
<li class=""><a href="https://loopback.io/blog/june-2020-milestone#documentation-improvements" class="">Documentation Improvements</a></li>
<li class=""><a href="https://loopback.io/blog/june-2020-milestone#hasmanythrough" class="">HasManyThrough</a></li>
<li class=""><a href="https://loopback.io/blog/june-2020-milestone#typeormsupport" class="">TypeORM Support</a></li>
<li class=""><a href="https://loopback.io/blog/june-2020-milestone#miscellaneous" class="">Miscellaneous</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="documentation-improvements">Documentation Improvements<a href="https://loopback.io/blog/june-2020-milestone#documentation-improvements" class="hash-link" aria-label="Direct link to Documentation Improvements" title="Direct link to Documentation Improvements" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-documentation-structure">New Documentation Structure<a href="https://loopback.io/blog/june-2020-milestone#new-documentation-structure" class="hash-link" aria-label="Direct link to New Documentation Structure" title="Direct link to New Documentation Structure" translate="no">​</a></h3>
<p>When writing documentation for new features, we were often struggling to find the right place to put the content and the right form to frame the information. Recently, we discovered a documentation system based on four different functions. It explains why we were struggling and provides a structure to guide us when writing new content.</p>
<blockquote>
<p>Documentation needs to include and be structured around its four different functions: tutorials, how-to guides, technical reference and explanation. Each of them requires a distinct mode of writing. People working with software need these four different kinds of documentation at different times, in different circumstances - so software usually needs them all, and they should all be integrated into your documentation.</p>
</blockquote>
<p>In June, we explored how to apply this documentation system to our content and implemented first high-level changes in the way how our content is organized. Check out <a href="https://github.com/strongloop/loopback-next/issues/5549" target="_blank" rel="noopener noreferrer" class="">loopback-next#5549</a> to find more resources about our new documentation system.</p>
<p>In a series of incremental pull requests, we reworked our documentation structure as follows:</p>
<ul>
<li class="">Renamed "Usage scenarios" to "How-to guides" to make it clear what kind of content is there.</li>
<li class="">Placed all explanation-related pages in "Behind the scenes" section and removed the section "Key concepts".</li>
<li class="">Relocated all reference guides to be nested under "Reference guides". We moved pages like "Error handling" and "Reserved binding keys" to references guides to make them easier to find.</li>
<li class="">Moved pages from "Using components" to "How-to guides".</li>
<li class="">Added support for sidebar sections that are just grouping related pages together but don't have a page of their own. This allowed us to remove few section pages that were rather anemic: "Access databases", "Reference guides", "How-to guides".</li>
<li class="">Reworked the "Server" page in "Behind the scenes" because there was a mix of different kinds of content in the page. We extracted some of the guides into new pages nested under "How-to guides".</li>
</ul>
<p>The re-organized documentation is already live at <a href="https://loopback.io/doc/en/lb4" target="_blank" rel="noopener noreferrer" class="">loopback.io</a>, take a look and let us know what do you think!</p>
<p>Now that the new structure is in place, we are going to gradually review and update existing documentation content to align it with the new system. You can find the list of relevant tasks in <a href="https://github.com/strongloop/loopback-next/issues/5113" target="_blank" rel="noopener noreferrer" class="">loopback-next#5113</a>. As always, your help is welcome!</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="alignment-along-abstraction-levels">Alignment Along Abstraction Levels<a href="https://loopback.io/blog/june-2020-milestone#alignment-along-abstraction-levels" class="hash-link" aria-label="Direct link to Alignment Along Abstraction Levels" title="Direct link to Alignment Along Abstraction Levels" translate="no">​</a></h3>
<p>As we were incrementally adding new features to the framework and extracting building blocks into standalone packages, our documentation ended up describing concepts from different abstraction layers in the same place, mixing information for framework users with references to low-level building blocks. This resulted in a steep learning curve for new users, because there were so many concept and packages to learn about!</p>
<p>In June, we reorganized most of our documentation to focus on framework-level APIs and deemphasize lower-level building blocks. As a result, we updated our developer documentation to describe which packages are considered as building blocks, see <a href="https://loopback.io/doc/en/lb4/code-contrib-lb4.html#organization-of-content" target="_blank" rel="noopener noreferrer" class="">Organization of content</a>. We also:</p>
<ul>
<li class=""><a href="https://github.com/strongloop/loopback-next/pull/5625" target="_blank" rel="noopener noreferrer" class="">updated our packages and documentation pages to use <code>@loopback/core</code> instead of <code>@loopback/context</code></a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/pull/5696" target="_blank" rel="noopener noreferrer" class="">removed <code>@loopback/metadata</code> from framework-level documentation and replaced references to use <code>@loopback/core</code> instead</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/pull/5693" target="_blank" rel="noopener noreferrer" class="">removed <code>@loopback/express</code> from framework-level documentation and replaced references to use <code>@loopback/rest</code> instead</a></li>
</ul>
<p>Now we need to update places referring to <code>@loopback/openapi-v3</code>, as discussed in <a href="https://github.com/strongloop/loopback-next/issues/5692" target="_blank" rel="noopener noreferrer" class="">loopback-next5692</a>. Want to contribute those changes yourself? Submit a PR today!</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="refactoring-of-authentication-related-documentation">Refactoring of Authentication-related Documentation<a href="https://loopback.io/blog/june-2020-milestone#refactoring-of-authentication-related-documentation" class="hash-link" aria-label="Direct link to Refactoring of Authentication-related Documentation" title="Direct link to Refactoring of Authentication-related Documentation" translate="no">​</a></h3>
<p>We refactored the authentication documentation so that it is easier for beginners to follow. As the new entry page, the <a href="https://loopback.io/doc/en/lb4/Authentication-overview.html" target="_blank" rel="noopener noreferrer" class="">authentication overview page</a> describes a typical scenario for securing APIs and it also helps you understand what "authentication" means in LoopBack 4. Next you can follow a simple hands-on tutorial <a href="https://loopback.io/doc/en/lb4/Authentication-tutorial.html" target="_blank" rel="noopener noreferrer" class="">secure your LoopBack 4 application with JWT authentication</a> to start exploring this feature. Then you can gradually learn the authentication system's mechanism and how to implement your own authentication strategies.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="adding-loopback-4-content-to-connector-pages">Adding LoopBack 4 Content to Connector Pages<a href="https://loopback.io/blog/june-2020-milestone#adding-loopback-4-content-to-connector-pages" class="hash-link" aria-label="Direct link to Adding LoopBack 4 Content to Connector Pages" title="Direct link to Adding LoopBack 4 Content to Connector Pages" translate="no">​</a></h3>
<p>As the continuation of improving connector documentation, after updating the PostgreSQL connector, we updated the connector page and added three more tutorials for <a href="https://loopback.io/doc/en/lb4/Connecting-to-MySQL.html" target="_blank" rel="noopener noreferrer" class="">MySQL</a>, <a href="https://loopback.io/doc/en/lb4/Connecting-to-Oracle.html" target="_blank" rel="noopener noreferrer" class="">Oracle</a>, and <a href="https://loopback.io/doc/en/lb4/Connecting-to-MongoDB.html" target="_blank" rel="noopener noreferrer" class="">MongoDB</a> connectors in June. By walking you through the steps of creating a LB4 application and connecting to a certain database, we hope new users find the tutorial helpful to adopt LoopBack 4 better. Besides the basic setup steps, we also added some sections to explain those questions that are being asked a lot from the community. Check out these documentations under <a href="https://loopback.io/doc/en/lb4/Database-connectors.html" target="_blank" rel="noopener noreferrer" class="">Database connectors</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="hasmanythrough">HasManyThrough<a href="https://loopback.io/blog/june-2020-milestone#hasmanythrough" class="hash-link" aria-label="Direct link to HasManyThrough" title="Direct link to HasManyThrough" translate="no">​</a></h2>
<p>A <code>HasManyThrough</code> relation sets up a many-to-many connection through another model. At the moment, LB4 only supports three basic relations: <code>HasMany</code>, <code>BelongsTo</code>, and <code>HasOne</code>.</p>
<p>Thanks to the initial work by <a href="https://github.com/codejamninja" target="_blank" rel="noopener noreferrer" class=""><code>codejamninja</code></a> and <a href="https://github.com/derdeka" target="_blank" rel="noopener noreferrer" class=""><code>derdeka</code></a>, we have a working prototype of the feature.</p>
<p>While functional, the <a href="https://github.com/strongloop/loopback-next/pull/2359" target="_blank" rel="noopener noreferrer" class="">PR</a> is pretty huge and some of the parts are up for discussion. As a result, we started to extract the core parts of the implementation into smaller PRs so that it's easier for review. In June, we had the basic operations working and tests are added. As the next step, we'll be adding documentation.</p>
<p>Stay tuned with the progress by going to <a href="https://github.com/strongloop/loopback-next/issues/5835" target="_blank" rel="noopener noreferrer" class="">loopback-next #5835</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="typeorm-support">TypeORM Support<a href="https://loopback.io/blog/june-2020-milestone#typeorm-support" class="hash-link" aria-label="Direct link to TypeORM Support" title="Direct link to TypeORM Support" translate="no">​</a></h2>
<p>We have implemented initial support for TypeORM in LoopBack. All it takes to enable TypeORM is to compose your app with the <code>TypeOrmMixin</code> mixin.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">BootMixin</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@loopback/boot'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">RestApplication</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@loopback/rest'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">TypeOrmMixin</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@loopback/typeorm'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">MyApplication</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">BootMixin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token function" style="color:#d73a49">TypeOrmMixin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">RestApplication</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token operator" style="color:#393A34">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>For details about using TypeORM with LoopBack, refer to the <code>@loopback/typeorm</code> <a href="https://github.com/strongloop/loopback-next/blob/master/packages/typeorm/README.md" target="_blank" rel="noopener noreferrer" class="">doc</a>.</p>
<p>Complete support for TypeORM is a significant amount of work. While the initial work is done, we're looking for ways to improve the implementation in the following areas.</p>
<ol>
<li class="">Complete TypeORM to OpenAPI data type conversion (currently only <code>number</code>,
<code>string</code>, and <code>boolean</code> are supported)</li>
<li class="">Full JSON/OpenAPI schema for models, including variants like with/without id,
with/without relations, partial, etc.</li>
<li class="">Json/OpenAPI schema to describe the supported filter format</li>
<li class="">Support for LoopBack-style filters</li>
<li class="">Custom repository classes (e.g. to implement bookRepo.findByTitle(title)).</li>
<li class="">Database migration</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="miscellaneous">Miscellaneous<a href="https://loopback.io/blog/june-2020-milestone#miscellaneous" class="hash-link" aria-label="Direct link to Miscellaneous" title="Direct link to Miscellaneous" translate="no">​</a></h2>
<p>We upgraded <code>mocha</code> to the new version 8. This version brings support for running tests in parallel (yay!), but also drops support for <code>--opts</code> argument and <code>test/mocha.opts</code> file. See <a href="https://github.com/mochajs/mocha/releases/tag/v8.0.0" target="_blank" rel="noopener noreferrer" class="">Mocha 8.0.0 release notes</a> for the full list of breaking changes and instructions on migrating existing projects. Our changes were introduced by <a href="https://github.com/strongloop/loopback-next/pull/5750" target="_blank" rel="noopener noreferrer" class="">loopback-next#5750</a> and <a href="https://github.com/strongloop/loopback-next/pull/5710" target="_blank" rel="noopener noreferrer" class="">loopback-next#5710</a>; and published in <code>@loopback/build</code> version <code>6.0.0</code>.</p>
<p><a href="https://strongloop.com/authors/Miroslav_Bajto%C5%A1" target="_blank" rel="noopener noreferrer" class="">Miroslav</a> benchmarked the performance of LoopBack and found an opportunity for a quick but significant improvement. By changing the algorithm used in <code>@loopback/context</code> to generate unique context instance names, we managed to improve the performance of our REST API layer by 45%! Learn more in the blog post <a href="https://strongloop.com/strongblog/2020-improve-looopback-performance-uuid/" target="_blank" rel="noopener noreferrer" class="">How We Improved LoopBack REST Performance by 45%</a>.</p>
<p>A new method <code>exportOpenApiSpec()</code> was added to the <code>RestServer</code> for generating OpenAPI specs in JSON or YAML format. This method can be called from the project directory by running the <code>openapi-spec</code> script.</p>
<p>When a binding key is not bound,<code>ResolutionError</code> now captures more contextual information. Earlier it used to print a long stack trace and was not easy to find out where the failure happened.</p>
<p>The implementation of binding cache was <a href="https://github.com/strongloop/loopback-next/pull/5731" target="_blank" rel="noopener noreferrer" class="">improved</a> to prevent race conditions and better handle bindings in async conditions.</p>
<p><code>CoreBindings.APPLICATION_INSTANCE</code> now has corresponding <code>@config()</code> decorator.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="july-milestones">July Milestones<a href="https://loopback.io/blog/june-2020-milestone#july-milestones" class="hash-link" aria-label="Direct link to July Milestones" title="Direct link to July Milestones" translate="no">​</a></h2>
<p>In the month of July we will continue focusing on improving the documentation. You can see the whole list on the <a href="https://github.com/strongloop/loopback-next/issues/5837" target="_blank" rel="noopener noreferrer" class="">July milestone issue</a>.</p>
<p>There is also ongoing work to have <a href="https://github.com/strongloop/loopback-next/pull/5545" target="_blank" rel="noopener noreferrer" class="">native GraphQL support</a> and a <a href="https://github.com/strongloop/loopback-next/pull/5681" target="_blank" rel="noopener noreferrer" class="">new extension for pooling service</a>. Your feedback is welcome.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="welcome-and-goodbyes">Welcome and Goodbyes<a href="https://loopback.io/blog/june-2020-milestone#welcome-and-goodbyes" class="hash-link" aria-label="Direct link to Welcome and Goodbyes" title="Direct link to Welcome and Goodbyes" translate="no">​</a></h2>
<p>We're pleased to welcome <a href="https://github.com/codechennerator" target="_blank" rel="noopener noreferrer" class="">Nathan Chen</a> as the maintainer of the <a href="https://github.com/strongloop/strong-globalize" target="_blank" rel="noopener noreferrer" class="">strong-globalize</a> repo. Thank you Nathan for all the good work you've done. On the other hand, it's sad to see <a href="https://strongloop.com/authors/Deepak_Rajamohan/" target="_blank" rel="noopener noreferrer" class="">Deepak</a> leaving the LoopBack team. We wish him best of luck in his new adventure.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="call-to-action">Call to Action<a href="https://loopback.io/blog/june-2020-milestone#call-to-action" class="hash-link" aria-label="Direct link to Call to Action" title="Direct link to Call to Action" translate="no">​</a></h2>
<p>In 2020, we look forward to helping you and seeing you around! LoopBack's success depends on you. We appreciate your continuous support and engagement to make LoopBack even better and meaningful for your API creation experience. Here's how you can join us and help the project:</p>
<ul>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues" target="_blank" rel="noopener noreferrer" class="">Report issues</a>.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/blob/master/docs/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer" class="">Contribute</a> code and documentation.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/labels/good%20first%20issue" target="_blank" rel="noopener noreferrer" class="">Open a pull request on one of our "good first issues"</a>.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues/110" target="_blank" rel="noopener noreferrer" class="">Join</a> our user group.</li>
</ul>]]></content:encoded>
            <category>Milestone update</category>
        </item>
        <item>
            <title><![CDATA[Community Q&A Monthly Digest - May 2020]]></title>
            <link>https://loopback.io/blog/2020-may-slack-qa</link>
            <guid>https://loopback.io/blog/2020-may-slack-qa</guid>
            <pubDate>Thu, 11 Jun 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>Since we made the <a href="https://loopbackio.slack.com/" target="_blank" rel="noopener noreferrer" class="">LoopBack Slack community</a> available, we are happy to see more and more users are joining. Let's see some of the questions and answers that we've highlighted below.</p>
<hr>
<p><strong>Question</strong>: In the <a href="https://loopback.io/doc/en/lb4/Model.html#using-the-juggler-bridge" target="_blank" rel="noopener noreferrer" class="">Model documentation page</a>, it says "To define a model for use with the juggler bridge, extend your classes from Entity". What's the juggler bridge?</p>
<p><strong>Answer</strong>: the Juggler bridge is used to bridge the gap between <code>@loopback/repository</code> and <code>loopback-datasource-juggler</code>. The former is used by LoopBack 4 to help define Models, Repositories, etc. It also allows for cross-datasource relations, etc. as they are enforced at the application level instead of the database.</p>
<p>The latter is the ORM/ODM that builds the queries and interacts with the database. It's from LoopBack 3 and is probably the only major component that didn't get revamped to keep backwards-compatibility.</p>
<p>Hence, the Juggler bridge helps bridge the gaps between these Node.js packages.</p>
<p><code>Entity</code> is, at it's core, a model that has an ID property. Looking at the source code for <code>Entity</code>, there's quite a bit of boilerplate code added.</p>
<hr>
<p><strong>Question:</strong> Is there a way to change the application port to string ? I am trying to deploy the application under Azure web app where the port is a string.</p>
<p><strong>Answer</strong>: Use <code>port: +(process.env.BILLING_PORT || 3000),</code>. The <code>+</code> converts a string to number. For the pipe, you should use <code>path</code> property instead of <code>port</code>. See <a href="https://github.com/strongloop/loopback-next/blob/master/packages/http-server/src/__tests__/integration/http-server.integration.ts#L272" target="_blank" rel="noopener noreferrer" class="">https://github.com/strongloop/loopback-next/blob/master/packages/http-server/src/<strong>tests</strong>/integration/http-server.integration.ts#L272</a>.</p>
<hr>
<p><strong>Question:</strong> I have a model with a field which is defined as “number”. Working with Postgres. How should I define it to have the field as a double and not an integer ?</p>
<p><strong>Answer:</strong> You can specify the dataType field to define a certain type of that column. For type Double, for example,</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">model</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">Item</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">extends</span><span class="token plain"> </span><span class="token class-name">Entity</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">property</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    type</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'number'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    id</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    generated</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  id</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token decorator at operator" style="color:#393A34">@</span><span class="token decorator function" style="color:#d73a49">property</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    type</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'number'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    postgresql</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      dataType</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'double precision'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  price</span><span class="token operator" style="color:#393A34">?</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">number</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token operator" style="color:#393A34">...</span><span class="token punctuation" style="color:#393A34">.</span><br></span></code></pre></div></div>
<p>Then run <code>npm run build</code> and then <code>npm run migrate</code> commands, the table should have columns:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">price       |                | double precision</span><br></span></code></pre></div></div>
<p>Besides the data type, LB4 also allows you to describe tables via the model definition and/or property definition. See <a href="https://loopback.io/doc/en/lb4/Model.html#data-mapping-properties" target="_blank" rel="noopener noreferrer" class="">Data Mapping Properties</a> for information.</p>
<hr>
<p><strong>Question:</strong> Is there client sdk for lb4 for api code generation? I tried with swagger codegen, but the generated code seems doesn't work.</p>
<p><strong>Answer:</strong> You should try <code>lb4 openapi --client</code>. It generates strongly-typed LoopBack service proxies over openapi spec using TypeScript. We use it to generate SDKs in TS.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="interested-to-join-our-slack-workspace">Interested to Join our Slack Workspace?<a href="https://loopback.io/blog/2020-may-slack-qa#interested-to-join-our-slack-workspace" class="hash-link" aria-label="Direct link to Interested to Join our Slack Workspace?" title="Direct link to Interested to Join our Slack Workspace?" translate="no">​</a></h2>
<p>Simply click <a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">this invitation link</a> to join. You can also find more channel details here: <a href="https://github.com/strongloop/loopback-next/issues/5048" target="_blank" rel="noopener noreferrer" class="">https://github.com/strongloop/loopback-next/issues/5048</a>.</p>]]></content:encoded>
            <category>Community</category>
            <category>Slack</category>
            <category>Q&amp;A</category>
        </item>
        <item>
            <title><![CDATA[How We Improved LoopBack REST Performance by 45%]]></title>
            <link>https://loopback.io/blog/2020-improve-looopback-performance-uuid</link>
            <guid>https://loopback.io/blog/2020-improve-looopback-performance-uuid</guid>
            <pubDate>Tue, 09 Jun 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Originally published on strongloop.com]]></description>
            <content:encoded><![CDATA[<p><em>Originally published on <a href="https://strongloop.com/" target="_blank" rel="noopener noreferrer" class="">strongloop.com</a></em></p>
<p>Recently, I measured the performance of LoopBack 4 and found an opportunity for an easy but significant improvement in the way how we are building per-request context instances.</p>
<p>I have been always interested in performance, from high-level design patterns like caching &amp; memoization, to micro-optimizations at language level (anybody remembers <a href="https://stackoverflow.com/a/44765284/69868" target="_blank" rel="noopener noreferrer" class="">CrankShaftScript</a> from Node.js 0.10 days?), all the way down to Mechanical Sympathy.</p>
<p>Since we started rewritting LoopBack from scratch in 2016/17, our primary focus was on features; performance aspects were a bit off the radar. (Not entirely, we were careful to design our HTTP routing layer to avoid the low performance of regexp-matching approach used by Express.) Now that LoopBack 4 is pretty mature, I though it's a good time to take a quick look on how fast is our framework.</p>
<p>To quickly get a high-level overview, I installed <a href="https://clinicjs.org/" target="_blank" rel="noopener noreferrer" class="">Clinic.js</a> and benchmarked our <a href="https://loopback.io/doc/en/lb4/todo-list-tutorial.html" target="_blank" rel="noopener noreferrer" class="">TodoList example application</a>. I used the following TodoList query (<code>filter</code>) for all benchmarks:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"include"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"relation"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"todos"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>The filter value needs to be URL-encoded, producing the following URL to pass to Clinic.js - let's save it to a shell variable for later use.</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$ URL="/todo-lists?filter=%7B%0A%20%20%22include%22%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22relation%22%3A%20%22todos%22%0A%20%20%20%20%7D%0A%20%20%5D%0A%7D"</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="clinicjs-doctor">Clinic.js Doctor<a href="https://loopback.io/blog/2020-improve-looopback-performance-uuid#clinicjs-doctor" class="hash-link" aria-label="Direct link to Clinic.js Doctor" title="Direct link to Clinic.js Doctor" translate="no">​</a></h2>
<p>The Doctor component performs an overall diagnosis looking for common anti-patterns. After installing Clinic.js globally, I ran the following command in <code>examples/todo-list</code> directory of loopback-next monorepo:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$ clinic doctor --debug --autocannon $URL -- node .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Server is running at http://127.0.0.1:3000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Running 10s test @ http://localhost:3000/todo-lists?filter=(...)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">10 connections</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">(...)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">18k requests in 11.05s, 11.1 MB read</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Analysing data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Generated HTML file is file:///(...)/todo-list/.clinic/41598.clinic-doctor.html</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">You can use this command to upload it:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">clinic upload .clinic/41598.clinic-doctor</span><br></span></code></pre></div></div>
<p>The report says there were no issue detected, hooray!</p>
<img class="aligncenter size-full" src="https://loopback.io/blog/images/uuid-clinic-doctor.png">
<p>A closer inspection shows that our process is consuming quite a lot of memory.  We don't have any memory leaks, which is most important. However, excessive allocations put more pressure on garbage collector which does impact application's performance. Let's set the memory usage aside for now and check how much time is the application spending on waiting for asynchronous operations.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="clinicjs-bubbleprof">Clinic.js Bubbleprof<a href="https://loopback.io/blog/2020-improve-looopback-performance-uuid#clinicjs-bubbleprof" class="hash-link" aria-label="Direct link to Clinic.js Bubbleprof" title="Direct link to Clinic.js Bubbleprof" translate="no">​</a></h2>
<p>Quoting from <a href="https://www.thoughtworks.com/radar/languages-and-frameworks/clinic-js-bubbleprof" target="_blank" rel="noopener noreferrer" class="">ThoughtWorks Technology Radar</a>:</p>
<blockquote>
<p>Clinic.js Bubbleprof represents visually the async operations in Node.js processes, drawing a map of delays in the application's flow. We like this tool because it helps developers to easily identify and prioritize what to improve in the code.</p>
</blockquote>
<p>Let's see how the bubbles look like for a LoopBack application!</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$ clinic bubbleprof --debug --autocannon $URL -- node .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Warning: The code is transpiled, bubbleprof does not support source maps yet.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Server is running at http://127.0.0.1:3000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Running 10s test @ http://localhost:3000/todo-lists?filter=(...)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">10 connections</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">(...)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">2k requests in 10.06s, 1.28 MB read</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Analysing data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Generated HTML file is file:///(...)/todo-list/.clinic/42229.clinic-bubbleprof.html</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">You can use this command to upload it:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">clinic upload .clinic/42229.clinic-bubbleprof</span><br></span></code></pre></div></div>
<p>There isn't much to see in the report, the application spent less than 20ms waiting for async operations. I guess that was kind of expected considering that our example application is using in-memory storage and not communicating with any external service.</p>
<img class="aligncenter size-full" src="https://loopback.io/blog/images/uuid-clinic-bubbleprof.png">
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="clinicjs-flame">Clinic.js Flame<a href="https://loopback.io/blog/2020-improve-looopback-performance-uuid#clinicjs-flame" class="hash-link" aria-label="Direct link to Clinic.js Flame" title="Direct link to Clinic.js Flame" translate="no">​</a></h2>
<p>The last item in Clinic.js toolbox is Flame. Quoting from Clinic's website:</p>
<blockquote>
<p>(...)  flamegraphs are a visualization of profiled software, allowing the most frequent code-paths to be identified quickly and accurately. Clinic.js Flame is specifically for Node.js and is built into Clinic.js. It collects metrics using by CPU sampling, then tracks top-of-the-stack frequency and creates flamegraphs.</p>
</blockquote>
<p>Can we find anything interesting in the flames? Let's see.</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$ clinic flame --debug --autocannon $URL -- node .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Server is running at http://127.0.0.1:3000</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Running 10s test @ http://localhost:3000/todo-lists?filter=(...)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">10 connections</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">15k requests in 10.03s, 9.44 MB read</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Analysing data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">Generated HTML file is file:///(...)/todo-list/.clinic/42454.clinic-flame.html</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">You can use this command to upload it:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">clinic upload .clinic/42454.clinic-flame</span><br></span></code></pre></div></div>
<p>There is a lot of information packaged into a flame graph. Initially, Clinic.js is selecting the hottest frame - the stack that was observed most often while running the application. In our case, the hottest frame is pointing to Node.js internals dealing with writing data to streams.</p>
<img class="aligncenter size-full" src="https://loopback.io/blog/images/uuid-clinic-flame-1.png">
<p><img decoding="async" loading="lazy" src="https://loopback.io/blog/assets/images/uuid-clinic-flame-1-8efb456149e922b8f5bf9c3322ce3d14.png" width="2538" height="1312" class="img_ev3q"></p>
<p>There isn't much we can do about Node.js streams. Our application is writing HTTP responses so it has to spend some time writing the data. The third hottest frame is <code>parseQueryStringValues</code> from the module <code>qs</code>, this is again not something we can easily improve. Let's remove all components except <code>dist</code> in the check-box list at the bottom of the screen to focus on LoopBack code only.</p>
<p><img decoding="async" loading="lazy" src="https://loopback.io/blog/assets/images/uuid-clinic-flame-2-e69cba5738c76e48971ad0fa70b7e523.png" width="2538" height="1312" class="img_ev3q"></p>
<p>Now the list of hot frames looks much more actionable! Here are the top entries:</p>
<ol>
<li class=""><code>handle</code> in <code>sequence.js</code> was 11.4% of time on top of stack</li>
<li class=""><code>buildLookupMap</code> in <code>relation.helpers.js</code> was 6.3% of time on top of stack</li>
<li class=""><code>findByForeignKeys</code> in <code>relation.helpers.js</code> was 5.7% of time on top of stack</li>
</ol>
<p>And so the list goes on. The entry number 7 caught my attention: the application is spending 1.3% of the time in <code>generateName</code> from <code>context.js</code>.  That's suspicious, why is generating context names so expensive?</p>
<p>It turns out we are generating unique context names to make it easier to debug binding-related issues. Our initial implementation was based on <a href="https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)" target="_blank" rel="noopener noreferrer" class="">UUID version 4 (random)</a> algorithm. Universally unique ids are great when you are aggregating debug logs from a mesh of microservices. However, most of the time, context names are just a hidden property of context instances that's not surfaced anywhere.  Applications shouldn't be paying performance tax for something they don't use. Let's see if we can find a better solution.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="uuid-alternatives">UUID Alternatives<a href="https://loopback.io/blog/2020-improve-looopback-performance-uuid#uuid-alternatives" class="hash-link" aria-label="Direct link to UUID Alternatives" title="Direct link to UUID Alternatives" translate="no">​</a></h2>
<p>What other options are there to generate unique ids?</p>
<ul>
<li class="">We can use UUID version 1 that's based on date-time and MAC address.</li>
<li class="">If we didn't need universally unique values, then a simple counter (perhaps prefixed with the current process id) could be a viable alternative.</li>
<li class="">Surely somebody else must have encountered this problem before us. Aren't there any fast id generators on npmjs.com? Of course there are! The search for <a href="https://www.npmjs.com/search?q=fast%20unique%20id" target="_blank" rel="noopener noreferrer" class="">"fast unique id"</a> returned
<a href="https://www.npmjs.com/package/hyperid" target="_blank" rel="noopener noreferrer" class="">hyperid</a> as the best match.</li>
</ul>
<p>Let's compare the performance of these alternatives. I wrote a simple benchmark which you can find in this <a href="https://gist.github.com/bajtos/6343512b171156872d3b701b2c10a682" target="_blank" rel="noopener noreferrer" class="">Gist</a> and measured the following data:</p>
<table><thead><tr><th>method</th><th style="text-align:right">ids/second</th></tr></thead><tbody><tr><td>numeric counter</td><td style="text-align:right"><code>11095k</code></td></tr><tr><td>hyperid</td><td style="text-align:right"><code>10234k</code></td></tr><tr><td>UUID v1</td><td style="text-align:right"><code>1649k</code></td></tr><tr><td>UUID v4</td><td style="text-align:right"><code>325k</code></td></tr></tbody></table>
<p>Initially, I wanted to use a numeric counter because it has the best performance. However, that would mean losing uniqueness of context names.  At the end, I decided to go with <code>hyperid</code>. It combines UUID v4 with a counter to achieve almost the same performance as the counter-only algorithm while preserving universal uniqueness of the generated ids.</p>
<p>To better measure the impact on performance, I created a small REST application that does not parse the query string and returns the response data directly, without going through <code>@loopback/repository</code>. Replacing <code>uuid/v4</code> with <code>hyperid</code> improved the performance of my test application from <code>~2.4k</code> requests/second to <code>~3.5k</code> requests/second on average. The average request latency has improved from <code>3.8ms</code> to <code>2.6ms</code>.</p>
<p>The pull request <a href="https://github.com/strongloop/loopback-next/pull/5628" target="_blank" rel="noopener noreferrer" class="">loopback-next#5628</a> improving <code>generateName</code> performance has been already landed and will become publicly available in the next framework release.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://loopback.io/blog/2020-improve-looopback-performance-uuid#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h2>
<p>As the popular saying goes, performance is not a problem until it becomes a problem. Even if your project is not performance sensitive, it's still good to pay attention to how much resources it consumes at runtime.</p>
<ol>
<li class="">
<p>Watch for warning signs. Maybe an existing test has suddenly started to fail on a timeout? When that happens, try to take the hard path: investigate the problem, dig deep to find the root cause and fix it.</p>
</li>
<li class="">
<p>Measure, measure, measure. Always create a reproducible benchmark to measure the effect of the changes you are going to make. Performance tuning is full of surprises and not all changes are for better.</p>
</li>
<li class="">
<p>Know the tooling. Node.js is compatible with many tools provided by Chrome's Developer Tools, it provides also tracing functionality for a more fine-grained analysis. You can learn more in Node.js documentation, starting from <a href="https://nodejs.org/en/docs/guides/debugging-getting-started/" target="_blank" rel="noopener noreferrer" class="">Debugging - Getting Started</a>, <a href="https://nodejs.org/en/docs/guides/simple-profiling/" target="_blank" rel="noopener noreferrer" class="">Easy profiling for Node.js Applications</a> and <a href="https://nodejs.org/en/docs/guides/diagnostics-flamegraph/" target="_blank" rel="noopener noreferrer" class="">Flame Graphs</a>.</p>
</li>
<li class="">
<p>Optimize hot paths. A semi-expensive function can become a performance problem when it's called for every incoming request.</p>
</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="call-to-action">Call to Action<a href="https://loopback.io/blog/2020-improve-looopback-performance-uuid#call-to-action" class="hash-link" aria-label="Direct link to Call to Action" title="Direct link to Call to Action" translate="no">​</a></h2>
<p>LoopBack's success depends on you. We appreciate your continuous support and engagement to make LoopBack even better and meaningful for your API creation experience. Here's how you can join us and help the project:</p>
<ul>
<li class=""><a href="https://join.slack.com/t/loopbackio/shared_invite/zt-8lbow73r-SKAKz61Vdao~_rGf91pcsw" target="_blank" rel="noopener noreferrer" class="">Join the community Slack chat</a></li>
<li class=""><a href="https://github.com/strongloop/loopback-next/issues" target="_blank" rel="noopener noreferrer" class="">Report issues</a>.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/blob/master/docs/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer" class="">Contribute</a> code and documentation.</li>
<li class=""><a href="https://github.com/strongloop/loopback-next/labels/good%20first%20issue" target="_blank" rel="noopener noreferrer" class="">Open a pull request on one of our "good first issues"</a>.</li>
</ul>]]></content:encoded>
            <category>REST</category>
            <category>Performance</category>
        </item>
    </channel>
</rss>