<?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>Wing Blog</title>
        <link>https://www.winglang.io/blog</link>
        <description>Wing Blog</description>
        <lastBuildDate>Wed, 09 Apr 2025 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[Saying Goodbye]]></title>
            <link>https://www.winglang.io/blog/2025/04/09/shutdown</link>
            <guid>https://www.winglang.io/blog/2025/04/09/shutdown</guid>
            <pubDate>Wed, 09 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[We are shutting down the company]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>After an amazing ride, we’ve made the tough decision to shut down our company, Wing (previously Monada).</p>
</blockquote>
<p>We started this journey with a bold idea: what if building in the cloud didn’t have to be so hard? What if infrastructure and application code could live together—beautifully and seamlessly? So we created Winglang—a programming language designed to realize that vision.</p>
<p>We open-sourced it, and the response blew us away: over 100 contributors, lots of excitement, and an awesome community that formed around it.</p>
<p>But when we tried to turn that energy into a business, we hit some tough reality checks. While developer experience is something engineers care deeply about, it’s not always seen as business-critical by most companies. That made it hard to build a sustainable business around it.</p>
<p>Over the past year, we explored various different directions in the cloud space—looking for a problem we were both passionate about and could build a company around. In the end, we didn’t find the right fit.</p>
<p>So, we’re bringing this chapter to a close. It’s bittersweet, but we’re deeply proud of what we built—and even more grateful for the amazing people who joined us along the way. Winglang was a labor of love, and building it was an absolute blast.</p>
<p>Huge shoutout to all the incredible Wingians/Monadians who were part of this journey—and a massive thank you to our amazing investors for believing in us and backing this wild ride. Your trust and support meant the world. 🙏</p>
<p>And in case you missed it: the first (and quirkiest) episode of The Wingly Update will always be a reminder of how much fun this all was: <a href="https://lnkd.in/dByGyq9m" target="_blank" rel="noopener noreferrer">https://lnkd.in/dByGyq9m</a></p>]]></content:encoded>
            <author>eladb@wing.cloud (Elad Ben-Israel)</author>
            <category>cloud-oriented programming</category>
            <category>winglang</category>
        </item>
        <item>
            <title><![CDATA[Inflight Magazine no. 11]]></title>
            <link>https://www.winglang.io/blog/2024/09/24/magazine-011</link>
            <guid>https://www.winglang.io/blog/2024/09/24/magazine-011</guid>
            <pubDate>Tue, 24 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Updates from the Wing project]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>The 11th issue of the Wing Inflight Magazine.</p>
</blockquote>
<p>Howdy Wingnuts!</p>
<p>We are back with another monthly issue of the&nbsp;Wing Inflight Magazine&nbsp;and excited to share some updates about&nbsp;<a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">Winglang</a>,&nbsp;an open source-programming language for the cloud.</p>
<p>New to Wing? Let’s get you up to date. Wing is a new programming language designed to help developers and platform engineers build cloud first applications with the best developer experience. The language combines cloud infrastructure&nbsp;<em>and</em>&nbsp;runtime into a single programming model and&nbsp;compiles to Terraform/CloudFormation and JavaScript&nbsp;that are ready to deploy to AWS, GCP and Azure (see our&nbsp;<a href="https://www.winglang.io/docs/api/standard-library/compatibility-matrix" target="_blank" rel="noopener noreferrer">support matrix</a>).</p>
<p>We are designing Wing to be&nbsp;familiar and friendly&nbsp;for developers who come from modern object-oriented background, so it will take you&nbsp;<a href="https://github.com/winglang/workshop-react/blob/main/cheatsheet.md" target="_blank" rel="noopener noreferrer">5 minutes</a>&nbsp;to learn.</p>
<p>Check out our&nbsp;<a href="https://www.winglang.io/docs/" target="_blank" rel="noopener noreferrer">getting started tutorial</a>&nbsp;or hit the&nbsp;Wing Playground&nbsp;for an online experience.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="in-todays-issue">In today’s issue<a class="hash-link" aria-label="Direct link to In today’s issue" title="Direct link to In today’s issue" href="https://www.winglang.io/blog/2024/09/24/magazine-011#in-todays-issue">​</a></h2>
<ul>
<li><a href="https://www.winglang.io/blog/2024/09/24/magazine-011#new-homepage-for-wing">New homepage for Wing</a></li>
<li><a href="https://www.winglang.io/blog/2024/09/24/magazine-011#introducing-wing-by-example">Introducing Wing by example</a></li>
<li><a href="https://www.winglang.io/blog/2024/09/24/magazine-011#new-bytes-type-in-wing">New Bytes type in Wing</a></li>
<li><a href="https://www.winglang.io/blog/2024/09/24/magazine-011#cors-configuration-for-cloud-buckets">CORS Configuration for Cloud Buckets</a></li>
<li><a href="https://www.winglang.io/blog/2024/09/24/magazine-011#new-wing-intrinsics-for-app-and-filename">New Wing intrinsics for @app and @filename</a></li>
<li><a href="https://www.winglang.io/blog/2024/09/24/magazine-011#generate-api-documentation-using-the-wing-cli">Generate API documentation using the Wing CLI</a></li>
<li><a href="https://www.winglang.io/blog/2024/09/24/magazine-011#wing-console-updates">Wing Console updates</a>
<ul>
<li><a href="https://www.winglang.io/blog/2024/09/24/magazine-011#presigned-urls-now-supported-in-the-console">Presigned URLS now supported in the console</a></li>
</ul>
</li>
<li><a href="https://www.winglang.io/blog/2024/09/24/magazine-011#winglibs">winglibs</a>
<ul>
<li><a href="https://www.winglang.io/blog/2024/09/24/magazine-011#new-wing-packages">New email winglib</a></li>
<li><a href="https://www.winglang.io/blog/2024/09/24/magazine-011#new-wing-packages">DynamoDB billing mode and deletion protection now enabled</a></li>
</ul>
</li>
<li><a href="https://www.winglang.io/blog/2024/09/24/magazine-011#summary">Summary</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="new-homepage-for-wing">New homepage for Wing<a class="hash-link" aria-label="Direct link to New homepage for Wing" title="Direct link to New homepage for Wing" href="https://www.winglang.io/blog/2024/09/24/magazine-011#new-homepage-for-wing">​</a></h2>
<p>We’re excited to unveil the updated <a href="http://winglang.io/" target="_blank" rel="noopener noreferrer">Winglang.io</a> landing page. It now features live Wing code examples, a streamlined search function to quickly find documentation, and easy access to the broader Wing ecosystem and programming language resources.</p>
<a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">
  <img decoding="async" loading="lazy" src="https://www.winglang.io/img/inflight-11/landing-page.png" class="img_ev3q">
</a>
<!-- -->
<p>If you encounter any issues or have feedback, please share them with us via our <a href="https://github.com/winglang/docsite" target="_blank" rel="noopener noreferrer">docs site repository</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="introducing-wing-by-example">Introducing Wing by example<a class="hash-link" aria-label="Direct link to Introducing Wing by example" title="Direct link to Introducing Wing by example" href="https://www.winglang.io/blog/2024/09/24/magazine-011#introducing-wing-by-example">​</a></h2>
<p>Many programming languages, such as <a href="https://gobyexample.com/" target="_blank" rel="noopener noreferrer">Go</a>, <a href="https://doc.rust-lang.org/rust-by-example/" target="_blank" rel="noopener noreferrer">Rust</a>, <a href="https://lotz84.github.io/haskellbyexample/" target="_blank" rel="noopener noreferrer">Haskell</a>, and <a href="https://www.learnbyexample.org/python/" target="_blank" rel="noopener noreferrer">Python</a>, feature "by example" pages. These resources offer quick code snippets and examples to help developers grasp various language concepts efficiently.</p>
<p>Drawing inspiration from these, we’ve launched our own <a href="https://www.winglang.io/docs/learn" target="_blank" rel="noopener noreferrer">Wing by Example</a> page. It provides a hands-on introduction to Wing through annotated example programs. <a href="https://www.winglang.io/docs/learn" target="_blank" rel="noopener noreferrer">You can explore over 30 examples on our website.</a></p>
<a href="https://winglang.io/docs/learn" target="_blank" rel="noopener noreferrer">
  <img decoding="async" loading="lazy" src="https://www.winglang.io/img/inflight-11/wing-by-example.png" class="img_ev3q">
</a>
<p>Feel free to contribute any missing examples or suggest improvements to our documentation through our <a href="https://www.winglang.io/docs/learn" target="_blank" rel="noopener noreferrer">docs site repository</a>. Your feedback and contributions help us enhance the learning experience for the entire community.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="new-bytes-type-in-wing">New Bytes type in Wing<a class="hash-link" aria-label="Direct link to New Bytes type in Wing" title="Direct link to New Bytes type in Wing" href="https://www.winglang.io/blog/2024/09/24/magazine-011#new-bytes-type-in-wing">​</a></h2>
<p>When working with binary files like images, audio, or other binary formats, you often need to manipulate data at the byte level. Wing now introduces a new <code>bytes</code> type, allowing you to easily handle byte values from strings, hexadecimal values, and files.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// get bytes from raw value</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> </span><span class="token literal-property property">rawData</span><span class="token operator">:</span><span class="token plain"> bytes </span><span class="token operator">=</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromRaw</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token number">104</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">101</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">108</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">108</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">111</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// get the bytes from a string</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> </span><span class="token literal-property property">rawString</span><span class="token operator">:</span><span class="token plain"> bytes </span><span class="token operator">=</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"hello"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// get bytes from base64 encoded value</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> </span><span class="token literal-property property">base64</span><span class="token operator">:</span><span class="token plain"> bytes </span><span class="token operator">=</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromBase64</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"aGVsbG8="</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// get bytes from hex value</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> </span><span class="token literal-property property">hex</span><span class="token operator">:</span><span class="token plain"> bytes </span><span class="token operator">=</span><span class="token plain"> bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromHex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"68656c6c6f"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You can also use the <a href="https://www.winglang.io/docs/api/standard-library/fs/api-reference" target="_blank" rel="noopener noreferrer"><code>fs</code> module</a> to read and write bytes to disk, making it easier to manage binary data in your applications.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring fs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// get bytes from file</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> </span><span class="token literal-property property">rawData</span><span class="token operator">:</span><span class="token plain"> bytes </span><span class="token operator">=</span><span class="token plain"> fs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">readBytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"path/to/file"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// write bytes to a file</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">fs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">writeBytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"path/to/file"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> rawData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>bytes</code> type in Wing is immutable. While mutable bytes (<code>mutbytes</code>) are not currently supported, they are on <a href="https://github.com/winglang/wing/issues/7144" target="_blank" rel="noopener noreferrer">our roadmap</a>. If you'd like to see this feature added, please consider upvoting the issue to show your support.</p>
<p>To learn more, you can refer to the new <code>bytes</code> type in the <a href="https://www.winglang.io/docs/api/language-reference#114-bytes-type" target="_blank" rel="noopener noreferrer">Language Reference</a> or try it out yourself with this playground example for a hands-on experience.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="cors-configuration-for-cloud-buckets">CORS Configuration for Cloud Buckets<a class="hash-link" aria-label="Direct link to CORS Configuration for Cloud Buckets" title="Direct link to CORS Configuration for Cloud Buckets" href="https://www.winglang.io/blog/2024/09/24/magazine-011#cors-configuration-for-cloud-buckets">​</a></h2>
<p>CORS (Cross-Origin Resource Sharing) support for <a href="https://www.winglang.io/docs/api/standard-library/cloud/bucket" target="_blank" rel="noopener noreferrer"><code>cloud.Bucket</code></a> has now been added with the default option set to true. <code>cors</code> and <code>corsOptions</code> have now been added as properties on the <code>cloud.Bucket</code> resource.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> uploads </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// these are the default values, override them if you need too</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">public</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">cors</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">corsOptions</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">allowedMethods</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">HttpMethod</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">GET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">HttpMethod</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">POST</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">HttpMethod</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">PUT</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">HttpMethod</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DELETE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">HttpMethod</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">HEAD</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">allowedOrigins</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"*"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">allowedHeaders</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"*"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">exposeHeaders</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">maxAge</span><span class="token operator">:</span><span class="token plain"> 0s</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You can disable the CORS configuration and apply custom rules to your buckets as needed.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> bucket </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">cors</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// disable any default CORS rules</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// example of custom CORS rule</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">addCorsRule</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">allowedOrigins</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"https://example.com"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">allowedMethods</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">HttpMethod</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">GET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>When CORS is enabled (<code>cors: true</code>), signed URLs will work automatically, allowing you to upload or download files directly from your browser to your bucket without additional configuration.</p>
<p>If your bucket is public or you're heavily using signed URLs, you may want to customize the <code>corsOptions</code> settings or disable CORS entirely based on the needs of your application.</p>
<p>For more details, you can <a href="https://www.winglang.io/docs/api/standard-library/cloud/bucket#configuring-cors" target="_blank" rel="noopener noreferrer">read the documentation</a> or try it out in our playground.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="new-wing-intrinsics-for-app-and-filename">New Wing intrinsics for @app and @filename<a class="hash-link" aria-label="Direct link to New Wing intrinsics for @app and @filename" title="Direct link to New Wing intrinsics for @app and @filename" href="https://www.winglang.io/blog/2024/09/24/magazine-011#new-wing-intrinsics-for-app-and-filename">​</a></h2>
<p><strong>Intrinsic functions</strong> are a special call-like expressions built into the Wing compiler. Wing now supports two new instrinc functions called <code>@filename</code> and <code>@app</code>.</p>
<ul>
<li><code>@filename</code> can be used to get the absolute path of the source file (example)</li>
<li><code>@app</code> represents a wing application (<a href="https://www.winglang.io/docs/api/standard-library/std/node#iapp-" target="_blank" rel="noopener noreferrer">see documentation</a>)</li>
</ul>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// bring http;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// absolute path of the source file</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> name </span><span class="token operator">=</span><span class="token plain"> @filename</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// the root of the construct tree </span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> app </span><span class="token operator">=</span><span class="token plain"> @app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// true if this is a testing environment.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> isTest </span><span class="token operator">=</span><span class="token plain"> app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">isTestEnvironment</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// The application's parameter registrar.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> params </span><span class="token operator">=</span><span class="token plain"> app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">parameters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// The directory of the entrypoint of the current Wing application.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> entrypointDir </span><span class="token operator">=</span><span class="token plain"> app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">entrypointDir</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// The .wing directory into which you can emit intermediate artifacts during preflight.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> workdir </span><span class="token operator">=</span><span class="token plain"> app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">workdir</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Wing application developers and library authors can use intrinsic functions to help them. You can discover and read more intrinsic functions via our documentation.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="generate-api-documentation-using-the-wing-cli">Generate API documentation using the Wing CLI<a class="hash-link" aria-label="Direct link to Generate API documentation using the Wing CLI" title="Direct link to Generate API documentation using the Wing CLI" href="https://www.winglang.io/blog/2024/09/24/magazine-011#generate-api-documentation-using-the-wing-cli">​</a></h2>
<p>Wing now supports a new command called <code>wing docs</code>. Running this command will generate a <a href="http://api.md/" target="_blank" rel="noopener noreferrer"><code>API.md</code></a> file in your current directory. These files can be shared with developers to help them understand your Wing code (see <a href="https://github.com/winglang/winglibs/blob/main/dynamodb/API.md" target="_blank" rel="noopener noreferrer">DynamoDB winglib example</a>).</p>
<p>Here is an example using doc comments (///) in your Wing code. Running <code>wing docs</code> compiles this into a markdown file.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">/// Winglib example that send messages to people</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Email</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/// Name of the person to say hello too</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">name</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/// Say Hello to everyone in the world</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">sendMessage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">message</span><span class="token parameter operator">:</span><span class="token parameter">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Sending message to {this.name}: {message}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token comment" style="color:rgb(98, 114, 164)">// ... logic to send message</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>Generated markdown</strong></p>
<div class="language-md codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-md codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token title important punctuation" style="color:rgb(248, 248, 242)">##</span><span class="token title important"> API Reference</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token title important punctuation" style="color:rgb(248, 248, 242)">###</span><span class="token title important"> Table of Contents</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token list punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token bold punctuation" style="color:rgb(248, 248, 242)">**</span><span class="token bold content">Classes</span><span class="token bold punctuation" style="color:rgb(248, 248, 242)">**</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token list punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">a</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">href</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">#my-wing-app.Email</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain">Email</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">a</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token title important punctuation" style="color:rgb(248, 248, 242)">###</span><span class="token title important"> Email (preflight class) &lt;a class="wing-docs-anchor" id="my-wing-app.Email"&gt;&lt;/a&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Winglib example that send messages to people</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token title important punctuation" style="color:rgb(248, 248, 242)">####</span><span class="token title important"> Constructor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">``</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">new(name: str): Awesome</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">``</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token title important punctuation" style="color:rgb(248, 248, 242)">####</span><span class="token title important"> Properties</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token table table-header-row punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-header-row table-header important"> </span><span class="token table table-header-row table-header important bold punctuation" style="color:rgb(248, 248, 242)">**</span><span class="token table table-header-row table-header important bold content">Name</span><span class="token table table-header-row table-header important bold punctuation" style="color:rgb(248, 248, 242)">**</span><span class="token table table-header-row table-header important"> </span><span class="token table table-header-row punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-header-row table-header important"> </span><span class="token table table-header-row table-header important bold punctuation" style="color:rgb(248, 248, 242)">**</span><span class="token table table-header-row table-header important bold content">Type</span><span class="token table table-header-row table-header important bold punctuation" style="color:rgb(248, 248, 242)">**</span><span class="token table table-header-row table-header important"> </span><span class="token table table-header-row punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-header-row table-header important"> </span><span class="token table table-header-row table-header important bold punctuation" style="color:rgb(248, 248, 242)">**</span><span class="token table table-header-row table-header important bold content">Description</span><span class="token table table-header-row table-header important bold punctuation" style="color:rgb(248, 248, 242)">**</span><span class="token table table-header-row table-header important"> </span><span class="token table table-header-row punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-header-row"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token table table-header-row"></span><span class="token table table-line punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(248, 248, 242)">---</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(248, 248, 242)">---</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(248, 248, 242)">---</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-line"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token table table-line"></span><span class="token table table-data-rows punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-data-rows table-data"> </span><span class="token table table-data-rows table-data tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token table table-data-rows table-data tag" style="color:rgb(255, 121, 198)">code</span><span class="token table table-data-rows table-data tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token table table-data-rows table-data">name</span><span class="token table table-data-rows table-data tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token table table-data-rows table-data tag" style="color:rgb(255, 121, 198)">code</span><span class="token table table-data-rows table-data tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token table table-data-rows table-data"> </span><span class="token table table-data-rows punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-data-rows table-data"> </span><span class="token table table-data-rows table-data tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token table table-data-rows table-data tag" style="color:rgb(255, 121, 198)">code</span><span class="token table table-data-rows table-data tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token table table-data-rows table-data">str</span><span class="token table table-data-rows table-data tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token table table-data-rows table-data tag" style="color:rgb(255, 121, 198)">code</span><span class="token table table-data-rows table-data tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token table table-data-rows table-data"> </span><span class="token table table-data-rows punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-data-rows table-data"> Name of the person to say hello too </span><span class="token table table-data-rows punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-data-rows"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token table table-data-rows"></span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token title important punctuation" style="color:rgb(248, 248, 242)">####</span><span class="token title important"> Methods</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token table table-header-row punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-header-row table-header important"> </span><span class="token table table-header-row table-header important bold punctuation" style="color:rgb(248, 248, 242)">**</span><span class="token table table-header-row table-header important bold content">Signature</span><span class="token table table-header-row table-header important bold punctuation" style="color:rgb(248, 248, 242)">**</span><span class="token table table-header-row table-header important"> </span><span class="token table table-header-row punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-header-row table-header important"> </span><span class="token table table-header-row table-header important bold punctuation" style="color:rgb(248, 248, 242)">**</span><span class="token table table-header-row table-header important bold content">Description</span><span class="token table table-header-row table-header important bold punctuation" style="color:rgb(248, 248, 242)">**</span><span class="token table table-header-row table-header important"> </span><span class="token table table-header-row punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-header-row"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token table table-header-row"></span><span class="token table table-line punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(248, 248, 242)">---</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(248, 248, 242)">---</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-line"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token table table-line"></span><span class="token table table-data-rows punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-data-rows table-data"> </span><span class="token table table-data-rows table-data tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token table table-data-rows table-data tag" style="color:rgb(255, 121, 198)">code</span><span class="token table table-data-rows table-data tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token table table-data-rows table-data">sendMessage(message: str): void</span><span class="token table table-data-rows table-data tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token table table-data-rows table-data tag" style="color:rgb(255, 121, 198)">code</span><span class="token table table-data-rows table-data tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token table table-data-rows table-data"> </span><span class="token table table-data-rows punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token table table-data-rows table-data"> Say Hello to everyone in the world </span><span class="token table table-data-rows punctuation" style="color:rgb(248, 248, 242)">|</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><code>wing docs</code> can be useful for developers building <a href="https://www.winglang.io/docs/winglibs/all-winglibs" target="_blank" rel="noopener noreferrer">winglibs</a>. Using this new command can help you document your libraries and examples for other wing developers.</p>
<p>If you want to learn more about winglibs or start creating your own you can read our <a href="https://www.winglang.io/docs/winglibs/creating-winglibs" target="_blank" rel="noopener noreferrer">getting started guide</a>.</p>
<h1>Wing console updates</h1>
<p><a href="https://www.winglang.io/docs/tools/wing-console" target="_blank" rel="noopener noreferrer">The Wing Console</a> is a web application that is designed to enhance the developer experience when viewing, exploring and interacting with your Wing applications. The wing console provides instant feedback during cloud application development process.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="presigned-urls-now-supported-in-the-console">Presigned URLS now supported in the console<a class="hash-link" aria-label="Direct link to Presigned URLS now supported in the console" title="Direct link to Presigned URLS now supported in the console" href="https://www.winglang.io/blog/2024/09/24/magazine-011#presigned-urls-now-supported-in-the-console">​</a></h2>
<p>Uploading and downloading files using presigned URLS with the <code>cloud.Bucket</code> resource is now also supported in the Wing console. When your application uploads files to the bucket you can now visually see the files, interact with them and delete them.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Create a new bucket</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> bucket </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cors</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// create new function</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token comment" style="color:rgb(98, 114, 164)">// generate presigned url</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> url </span><span class="token operator">=</span><span class="token plain"> bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">signedUrl</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"my-key"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">action</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">BucketSignedUrlAction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">UPLOAD</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">duration</span><span class="token operator">:</span><span class="token plain"> 2m</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// Example uploading file using the url</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// This would be your web application...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">put</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string-property property">"Content-Type"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"text/plain"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string-property property">"Content-Disposition"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"attachment; filename=text.txt"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hello world"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// 200</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Upload file using presigned url"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Wing console output. You can see and explore this example in our playground.</p>
<p><img decoding="async" loading="lazy" alt="Wing Console" src="https://www.winglang.io/assets/images/console-example-7912367738443e2a11c460a2c0c4d762.png" width="2552" height="978" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="winglibs">winglibs<a class="hash-link" aria-label="Direct link to winglibs" title="Direct link to winglibs" href="https://www.winglang.io/blog/2024/09/24/magazine-011#winglibs">​</a></h2>
<p><a href="https://www.winglang.io/docs/winglibs/what-are-winglibs" target="_blank" rel="noopener noreferrer">Wing libraries</a> (winglibs) are packages you can <a href="https://www.winglang.io/docs/winglibs/using-winglibs" target="_blank" rel="noopener noreferrer">import into your wing application</a>. Anybody can <a href="https://www.winglang.io/docs/winglibs/creating-winglibs" target="_blank" rel="noopener noreferrer">create a winglib</a> and add them to our <a href="https://github.com/winglang/winglibs" target="_blank" rel="noopener noreferrer">ecosystem of libraries</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="new-wing-packages">New wing packages<a class="hash-link" aria-label="Direct link to New wing packages" title="Direct link to New wing packages" href="https://www.winglang.io/blog/2024/09/24/magazine-011#new-wing-packages">​</a></h2>
<p>Here is a list of new wing packages or improvements that have been made</p>
<ul>
<li><a href="https://www.winglang.io/docs/winglibs/winglibs/email" target="_blank" rel="noopener noreferrer">@winglibs/email</a> - Send emails using Wing.</li>
<li><a href="https://www.winglang.io/docs/winglibs/dynamodb" target="_blank" rel="noopener noreferrer">@winglibs/dynamodb</a> - Now supports <a href="https://www.winglang.io/docs/winglibs/dynamodb#@winglibs/dynamodb.BillingMode" target="_blank" rel="noopener noreferrer">BillingMode</a> and <a href="https://www.winglang.io/docs/winglibs/dynamodb#tableprops-struct-" target="_blank" rel="noopener noreferrer">deletion protection</a>.</li>
</ul>
<p>Have an idea for a new winglib? Feel free to <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">reach out to us on Discord</a> or make a <a href="https://github.com/winglang/winglibs" target="_blank" rel="noopener noreferrer">pull request on GitHub</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" href="https://www.winglang.io/blog/2024/09/24/magazine-011#summary">​</a></h3>
<p>That’s it for this edition!</p>
<p>You are invited to join the&nbsp;<a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">Wing Discord</a>! Come say hello and hang out with fellow Wingnuts! Give&nbsp;<a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">winglang.io</a>&nbsp;a visit and take Wing out for a spin. If you're not already, stay updated on the latest changes in our&nbsp;<a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">repo</a>.</p>
<p>Catch you next month!</p>
<p><em>- The Wing Team</em></p>]]></content:encoded>
            <author>davidb@wing.cloud (David Boyne)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>winglang</category>
            <category>changelog</category>
            <category>newsletter</category>
        </item>
        <item>
            <title><![CDATA[The road to Wing 1.0]]></title>
            <link>https://www.winglang.io/blog/2024/08/29/updated-roadmap</link>
            <guid>https://www.winglang.io/blog/2024/08/29/updated-roadmap</guid>
            <pubDate>Thu, 29 Aug 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Our goals and vision of what we want to include in Wing 1.0]]></description>
            <content:encoded><![CDATA[<p>Hello Wingnuts!</p>
<p>We recently updated the project's roadmap to share more details about our vision for the project. As the Wing language and toolchain has an ambitious goal, we're hoping this gives you a better idea of what to expect in the coming months.</p>
<p>We want to stabilize as many of the items below as possible and we're eagerly interested in you feedback and collaboration, either <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">through GitHub</a> or our <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">Discord server</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="toolchain">Toolchain<a class="hash-link" aria-label="Direct link to Toolchain" title="Direct link to Toolchain" href="https://www.winglang.io/blog/2024/08/29/updated-roadmap#toolchain">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="wing-cli">Wing CLI<a class="hash-link" aria-label="Direct link to Wing CLI" title="Direct link to Wing CLI" href="https://www.winglang.io/blog/2024/08/29/updated-roadmap#wing-cli">​</a></h3>
<ul>
<li>
<p>We want to provide a robust CLI for people to <a href="https://www.winglang.io/docs/platforms/platforms">compile</a>, <a href="https://www.winglang.io/docs/concepts/tests">test</a>, and perform other essential functions with their Wing code.</p>
</li>
<li>
<p>We want the CLI to be easy to <a href="https://www.winglang.io/docs/#install">install</a>, update, and set up on a variety of systems.</p>
</li>
<li>
<p>Dependency management should be simple and insulated from problems specific to individual Node package managers (e.g npm, pnpm, yarn).</p>
</li>
<li>
<p>The Wing toolchain makes it easy to create and publish Wing libraries (<a href="https://www.winglang.io/docs/winglibs/what-are-winglibs">winglibs</a>) with automatically generated API docs, and it doesn't require existing knowledge of node package managers.</p>
</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="wing-platforms">Wing Platforms<a class="hash-link" aria-label="Direct link to Wing Platforms" title="Direct link to Wing Platforms" href="https://www.winglang.io/blog/2024/08/29/updated-roadmap#wing-platforms">​</a></h3>
<ul>
<li>
<p><a href="https://www.winglang.io/docs/platforms/platforms">Wing Platforms</a> allow you to specify a layer of infrastructure customizations that apply to all application code written in Wing. It should be simple to create new Wing platforms or extend existing platforms.</p>
</li>
<li>
<p>With Wing Platforms it's possible to specify both multi-cloud abstractions in Wing as well as the actual platform (for example, the implementation of cloud.Bucket) in Wing.</p>
</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="testing">Testing<a class="hash-link" aria-label="Direct link to Testing" title="Direct link to Testing" href="https://www.winglang.io/blog/2024/08/29/updated-roadmap#testing">​</a></h3>
<ul>
<li>
<p>Wing lets you <a href="https://www.winglang.io/docs/concepts/tests">easily write tests</a> that run both locally and on the cloud.</p>
</li>
<li>
<p>Wing test runner can be customized per platform.</p>
</li>
<li>
<p>Tests in Wing can be run in a variety of means -- via the CLI, via the <a href="https://www.winglang.io/docs/tools/wing-console">Wing Console</a>, and in CI/CD.</p>
</li>
<li>
<p>The design of the test system should make it easy for developers to write reproducible (or deterministic) tests, and also provide facilities for debugging.</p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="compiler">Compiler<a class="hash-link" aria-label="Direct link to Compiler" title="Direct link to Compiler" href="https://www.winglang.io/blog/2024/08/29/updated-roadmap#compiler">​</a></h2>
<ul>
<li>
<p>Wing's syntax and type system is robust, well documented, and easy for developers to learn.</p>
</li>
<li>
<p>Developers coming from other mainstream languages with C-like syntax (Java, C++, TypeScript) should feel right at home.</p>
</li>
<li>
<p>Most Wing code is statically typed in order to support automatic permissions.</p>
</li>
<li>
<p>Wing should be able to <a href="https://www.winglang.io/docs/faq/why-start-with-js-interop">interoperate</a> with a vast majority of TypeScript libraries.</p>
</li>
<li>
<p>It should be straightforward to import libraries that are available on npm and automatically have corresponding Wing types generated for them based on the TypeScript type information.</p>
</li>
<li>
<p>The language also has mechanisms for more advanced users to use custom JavaScript code in Wing.</p>
</li>
<li>
<p>We want Wing to have friendly, easy to understand error messages that point users towards how to fix their problems.</p>
</li>
<li>
<p>Wing has a built-in language server that gives users a first-class editing and refactoring experience in their IDEs.</p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="standard-library-and-ecosystem">Standard Library and Ecosystem<a class="hash-link" aria-label="Direct link to Standard Library and Ecosystem" title="Direct link to Standard Library and Ecosystem" href="https://www.winglang.io/blog/2024/08/29/updated-roadmap#standard-library-and-ecosystem">​</a></h2>
<ul>
<li>
<p>Wing provides a batteries-included experience for performing common programming tasks like working with data structures, <a href="https://www.winglang.io/docs/api/standard-library/fs/api-reference">file systems</a>, <a href="https://www.winglang.io/docs/api/standard-library/math/api-reference">calculations</a>, random number generation, <a href="https://www.winglang.io/docs/api/standard-library/http/api-reference">HTTP requests</a>, and other common needs.</p>
</li>
<li>
<p>Wing also has a ecosystem of Wing libraries (<a href="https://www.winglang.io/docs/winglibs/what-are-winglibs">"winglibs"</a>) that make it easy to write cloud applications by providing easy-to-use abstractions over popular cloud resources.</p>
</li>
<li>
<p>This includes a []<code>cloud</code> module](/docs/api/category/cloud) that is an opinionated set of resources for writing applications on the most popular public clouds.</p>
</li>
<li>
<p>The cloud primitives are designed to be cloud-agnostic (we aren't biased towards a specific cloud provider).</p>
</li>
<li>
<p>These cloud primitives all can be run to a high degree of fidelity and performance with <a href="https://www.winglang.io/docs/platforms/sim">the local simulator</a>.</p>
</li>
<li>
<p>Not all <a href="https://www.winglang.io/docs/winglibs/what-are-winglibs">winglibs</a> may be fully stable when the language reaches 1.0.</p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="wing-console--simulator">Wing Console / Simulator<a class="hash-link" aria-label="Direct link to Wing Console / Simulator" title="Direct link to Wing Console / Simulator" href="https://www.winglang.io/blog/2024/08/29/updated-roadmap#wing-console--simulator">​</a></h2>
<ul>
<li>
<p>We want to provide a first class local development experience for Wing that makes it easy and fast to test your applications locally.</p>
</li>
<li>
<p>It gives you observability into your running application and interact live with different components.</p>
</li>
<li>
<p>It gives you a clearer picture of your infrastructure graph and how <a href="https://www.winglang.io/docs/concepts/inflights">preflight and inflight code</a> are related.</p>
</li>
<li>
<p>It complements the experience of writing code in a dedicated editor.</p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="documentation">Documentation<a class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" href="https://www.winglang.io/blog/2024/08/29/updated-roadmap#documentation">​</a></h2>
<ul>
<li>
<p>We want it to be easy for people to get exposed to Wing code and have ways to try applications without having to install Wing locally.</p>
</li>
<li>
<p>The Wing docs should provide content appealing to different kinds of developers trying to acquire different kinds of information at different stages -- from tutorials to references to how-to-guides (<a href="https://docs.divio.com/documentation-system/" target="_blank" rel="noopener noreferrer">documentation quadrants</a>)</p>
</li>
<li>
<p>Wing docs need to have content for both the personas of developers writing their own applications and platform engineers aiming to provide simpler abstractions and tools for their teams.</p>
</li>
<li>
<p>We want to provide hundreds of <a href="https://www.winglang.io/docs/examples">examples and code snippets</a> to make it easy to learn the syntax of the language and easy to see how to solve common use cases.</p>
</li>
</ul>
<hr>
<p>If you have any questions, would like to contribute feel free to reach out to us and join us on our mission to make cloud development easier for everyone.</p>
<p><em>- The Wing Team</em></p>]]></content:encoded>
            <author>chrisr@wing.cloud (Chris Rybicki)</author>
            <author>davidb@wing.cloud (David Boyne)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>winglang</category>
            <category>roadmap</category>
        </item>
        <item>
            <title><![CDATA[Inflight Magazine no. 10]]></title>
            <link>https://www.winglang.io/blog/2024/08/28/magazine-010</link>
            <guid>https://www.winglang.io/blog/2024/08/28/magazine-010</guid>
            <pubDate>Wed, 28 Aug 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Updates from the Wing project]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>The 10th issue of the Wing Inflight Magazine.</p>
</blockquote>
<p>Howdy Wingnuts!</p>
<p>We are back with another monthly issue of the&nbsp;Wing Inflight Magazine&nbsp;and excited to share some updates about&nbsp;<a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">Winglang</a>,&nbsp;an open source-programming language for the cloud.</p>
<p>New to Wing? Let’s get you up to date. Wing is a new programming language designed to help developers and platform engineers build cloud first applications with the best developer experience. The language combines cloud infrastructure&nbsp;<em>and</em>&nbsp;runtime into a single programming model and&nbsp;compiles to Terraform/CloudFormation and JavaScript&nbsp;that are ready to deploy to AWS, GCP and Azure (see our&nbsp;<a href="https://www.winglang.io/docs/api/standard-library/compatibility-matrix" target="_blank" rel="noopener noreferrer">support matrix</a>).</p>
<p>We are designing Wing to be&nbsp;familiar and friendly&nbsp;for developers who come from modern object-oriented background, so it will take you&nbsp;<a href="https://github.com/winglang/workshop-react/blob/main/cheatsheet.md" target="_blank" rel="noopener noreferrer">5 minutes</a>&nbsp;to learn.</p>
<p>Check out our&nbsp;<a href="https://www.winglang.io/docs/" target="_blank" rel="noopener noreferrer">getting started tutorial</a>&nbsp;or hit the&nbsp;Wing Playground&nbsp;for an online experience.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="in-todays-issue">In today’s issue<a class="hash-link" aria-label="Direct link to In today’s issue" title="Direct link to In today’s issue" href="https://www.winglang.io/blog/2024/08/28/magazine-010#in-todays-issue">​</a></h2>
<ul>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#wing-10-roadmap">Wing 1.0 roadmap</a></li>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#language-updates">Language updates</a>
<ul>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#internal-access-modifier">Internal access modifier</a></li>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#new-cloud-resource-cloudservice">New cloud resource <code>cloud.Service</code></a></li>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#aws-lambda-layer-api-for-wing">AWS Lambda Layer API for Wing</a></li>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#logging-now-supports-more-values">Logging now supports more values</a></li>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#breaking-changes">Breaking changes</a>
<ul>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#goodbye-elif-hello-else-if">Goodbye elif, hello else if</a></li>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#inflight-intrinsic-has-been-removed">inflight intrinsic has been removed</a></li>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#cloudfunction-now-accepts-json"><code>cloud.Function</code> now accepts Json</a></li>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#additional-breaking-changes">Additional breaking changes</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#wing-console-updates">Wing Console updates</a>
<ul>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#new-table-component-uitable">New table component <code>ui.Table</code></a></li>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#nodes-can-now-be-collapsed-and-expanded">Nodes can be collapsed or expanded</a></li>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#ability-to-filter-logs-in-the-wing-console">Ability to filter logs in the Wing console</a></li>
</ul>
</li>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#winglibs">WingLibs</a>
<ul>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#new-wing-packages">New wing packages</a></li>
</ul>
</li>
<li><a href="https://www.winglang.io/blog/2024/08/28/magazine-010#summary">Summary</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="wing-10-roadmap">Wing 1.0 roadmap<a class="hash-link" aria-label="Direct link to Wing 1.0 roadmap" title="Direct link to Wing 1.0 roadmap" href="https://www.winglang.io/blog/2024/08/28/magazine-010#wing-10-roadmap">​</a></h2>
<p>We're excited to share our <a href="https://www.winglang.io/contributing/roadmap" target="_blank" rel="noopener noreferrer">1.0 roadmap</a>, outlining our vision and the goals we aim to achieve in Wing 1.0.</p>
<p>Our mission with Wing is to empower developers to build cloud applications with an exceptional developer experience. To do this, we're focusing on establishing a stable foundation for the Wing programming language, defining <a href="https://www.winglang.io/docs/api/category/cloud" target="_blank" rel="noopener noreferrer">essential cloud primitives</a>, enabling the creation of libraries <a href="https://www.winglang.io/docs/winglibs/what-are-winglibs" target="_blank" rel="noopener noreferrer">(winglibs)</a> and <a href="https://www.winglang.io/docs/platforms/platforms" target="_blank" rel="noopener noreferrer">custom platforms</a>, and <a href="https://www.winglang.io/docs/tools/wing-console" target="_blank" rel="noopener noreferrer">providing tools to simulate the cloud</a> locally on your machine.</p>
<p>Building on the cloud shouldn’t be difficult, and we believe Wing can be a key part of the solution.</p>
<p>As we progress toward Wing 1.0, we'll be experimenting, learning, and making necessary adjustments. If you'd like to contribute or join us on this journey, we'd love to connect with you on <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">GitHub</a> or through our <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">Discord server</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="language-updates">Language updates<a class="hash-link" aria-label="Direct link to Language updates" title="Direct link to Language updates" href="https://www.winglang.io/blog/2024/08/28/magazine-010#language-updates">​</a></h2>
<p>To get the latest language updates you will need to update your wing version running the command below</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-sh codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">npm install -g winglang</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="internal-access-modifier">Internal access modifier<a class="hash-link" aria-label="Direct link to Internal access modifier" title="Direct link to Internal access modifier" href="https://www.winglang.io/blog/2024/08/28/magazine-010#internal-access-modifier">​</a></h3>
<p>Wing now supports the <code>internal</code> access modifier, which is particularly useful for library authors (<a href="https://www.winglang.io/docs/winglibs/what-are-winglibs" target="_blank" rel="noopener noreferrer">winglib authors)</a>. This modifier allows you to make classes or methods accessible only within the module or library you’re developing, keeping them hidden from external consumers.</p>
<p>Previously, the only option if you were splitting definitions across multiple files was to make everything public, exposing all methods and classes to the library users. With <code>internal</code>, you gain finer control over what parts of your code are exposed, ensuring that only what’s necessary is accessible.</p>
<p>This example shows a  <code>internal</code> class called <code>OrderProcessingUtils</code>. As a library author you can call <code>OrderProcessingUtils.calculateTax</code> within the module itself, but library consumers cannot (as it’s not exposed).</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">internal </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">OrderProcessingUtils</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">calculateTax</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">amount</span><span class="token operator">:</span><span class="token plain"> num</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> num </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token comment" style="color:rgb(98, 114, 164)">// Internal method to calculate tax</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> amount </span><span class="token operator">*</span><span class="token plain"> </span><span class="token number">0.1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// OK inside the module we are building</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> value </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">OrderProcessingUtils</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">calculateTax</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">10</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Will not work if we try to use the code outside the module</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> value </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">OrderProcessingUtils</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">calculateTax</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">10</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// error</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You can read more on our documentation <a href="https://www.winglang.io/contributing/rfcs/language-spec#15-access-modifiers" target="_blank" rel="noopener noreferrer">about access modifiers</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-cloud-resource-cloudservice">New cloud resource <code>cloud.Service</code><a class="hash-link" aria-label="Direct link to new-cloud-resource-cloudservice" title="Direct link to new-cloud-resource-cloudservice" href="https://www.winglang.io/blog/2024/08/28/magazine-010#new-cloud-resource-cloudservice">​</a></h3>
<p>We have released the new <a href="https://www.winglang.io/docs/api/standard-library/cloud/service" target="_blank" rel="noopener noreferrer"><code>cloud.Service</code> resource.</a> The <code>cloud.Service</code> class in Wing represents a cloud service with a defined lifecycle, including a start and an optional stop phase.</p>
<p>Example usage includes long-running processes like microservices or background data processing.</p>
<p>Cloud services will automatically start once deployed, you can opt out of this by specifying the <code>autoStart</code> option.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// inflight (runtime code) that is run within the service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token comment" style="color:rgb(98, 114, 164)">// Code is run on init/start of service</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token comment" style="color:rgb(98, 114, 164)">// This example we can start a custom HTTP server</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Service started..."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> server </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">startHttpServer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// Code is run when service stops</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Service stopped..."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// Example would be to stop the HTTP server</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    server</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">close</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// By default services are started when deployed</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> autoStartService </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// You can configure services not to start on deploy</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> manualStartService </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token literal-property property">autoStart</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Cloud services also have an inflight API that allows you to start or stop the service yourself, if you want more fine-grained control.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> startCounter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"start counter"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> stopCounter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"stop counter"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> i </span><span class="token operator">=</span><span class="token plain"> startCounter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">inc</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Service started for the ${i}th time..."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> i </span><span class="token operator">=</span><span class="token plain"> stopCounter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">inc</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Service stopped for the ${i}th time..."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> service </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token literal-property property">autoStart</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Access service inflight API to start/stop the service in functions</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">start</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">assert</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">started</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"start service"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stop</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">assert</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">started</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"stop service"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><code>cloud.Service</code>  currently supports the AWS platform (terraform and CDK), if you would like <a href="https://github.com/winglang/wing/issues/1307" target="_blank" rel="noopener noreferrer">Azure</a> or <a href="https://github.com/winglang/wing/issues/1308" target="_blank" rel="noopener noreferrer">Google Cloud (GCP)</a> support please comment and upvote the GitHub issues.</p>
<p>You can get started or <a href="https://www.winglang.io/docs/api/standard-library/cloud/service" target="_blank" rel="noopener noreferrer">read more in the documentation</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="aws-lambda-layer-api-for-wing">AWS Lambda Layer API for Wing<a class="hash-link" aria-label="Direct link to AWS Lambda Layer API for Wing" title="Direct link to AWS Lambda Layer API for Wing" href="https://www.winglang.io/blog/2024/08/28/magazine-010#aws-lambda-layer-api-for-wing">​</a></h3>
<p>When compiling <code>cloud.Function</code> resources to the <a href="https://www.winglang.io/docs/category/aws" target="_blank" rel="noopener noreferrer">AWS platform</a>, AWS Lambda is used.</p>
<p>AWS Lambda supports <a href="https://docs.aws.amazon.com/lambda/latest/dg/chapter-layers.html" target="_blank" rel="noopener noreferrer">lambda layers</a>, which contain supplementary code or data for your Lambda functions. These can be useful for sharing library dependencies, a <a href="https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html" target="_blank" rel="noopener noreferrer">custom runtime</a> or configuration files across your Lambda functions.</p>
<p>Wing now supports adding Lambda layers to <code>cloud.Function</code>. To add a Lambda layer to your function, you can now use the <code>aws.Function</code> class as shown below.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring aws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// define your cloud function</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> f </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello world!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// attach lambda layer to the function</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> lambdaFn </span><span class="token operator">=</span><span class="token plain"> aws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">f</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token comment" style="color:rgb(98, 114, 164)">// add your lambda layer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  lambdaFn</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">addLambdaLayer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"arn:aws:lambda:us-west-2:123456789012:layer:my-layer:1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You can also attach Lambda layers to all your cloud functions by using a classe’s inflight method and the onLift hook. This allows you abstract and apply layers at a global level, ideal if you want to create <a href="https://www.winglang.io/docs/winglibs/what-are-winglibs" target="_blank" rel="noopener noreferrer">winglibs</a> for your developers.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring aws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Create Datadog class for wing application</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Datadog</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">fetchMetrics</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// ...implementation...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// onLift hook, attach the lambda layer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub </span><span class="token function" style="color:rgb(80, 250, 123)">onLift</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">host</span><span class="token parameter operator">:</span><span class="token parameter"> std</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token parameter property-access maybe-class-name">IInflightHost</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> </span><span class="token parameter literal-property property">ops</span><span class="token parameter operator">:</span><span class="token parameter"> </span><span class="token parameter known-class-name class-name">Array</span><span class="token parameter operator">&lt;</span><span class="token parameter">str</span><span class="token parameter operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> lambdaFn </span><span class="token operator">=</span><span class="token plain"> aws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">host</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      lambdaFn</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">addLambdaLayer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"arn:aws:lambda:us-west-2:123456789012:layer:datadog-layer:1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> d </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Datadog</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> api </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Lambda layer is attached to inflight function</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"/metrics"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  d</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fetchMetrics</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If you want to learn more you can <a href="https://www.winglang.io/docs/api/standard-library/cloud/function#adding-lambda-layers" target="_blank" rel="noopener noreferrer">read the documentation</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="logging-now-supports-more-values">Logging now supports more values<a class="hash-link" aria-label="Direct link to Logging now supports more values" title="Direct link to Logging now supports more values" href="https://www.winglang.io/blog/2024/08/28/magazine-010#logging-now-supports-more-values">​</a></h3>
<p>Logging now supports stringable values directly rather than wrapping them with quotes.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">enum</span><span class="token plain"> </span><span class="token maybe-class-name">MyEnum</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">A</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">B</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">C</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> x </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">5</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// before</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{x}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"my string"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{42}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{true}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{Json { "</span><span class="token plain">cool</span><span class="token string" style="color:rgb(255, 121, 198)">": "</span><span class="token plain">beans</span><span class="token string" style="color:rgb(255, 121, 198)">" }}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{MyEnum.A}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// now</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"my string"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">42</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token string-property property">"cool"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"beans"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">MyEnum</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">A</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="breaking-changes">Breaking changes<a class="hash-link" aria-label="Direct link to Breaking changes" title="Direct link to Breaking changes" href="https://www.winglang.io/blog/2024/08/28/magazine-010#breaking-changes">​</a></h2>
<p>As we move towards Wing 1.0, we will be making changes along the way. Some of these changes may break existing code, but we will do our best to document these and keep you updated.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="goodbye-elif-hello-else-if">Goodbye elif, hello else if<a class="hash-link" aria-label="Direct link to Goodbye elif, hello else if" title="Direct link to Goodbye elif, hello else if" href="https://www.winglang.io/blog/2024/08/28/magazine-010#goodbye-elif-hello-else-if">​</a></h3>
<p>To align with other imperative languages and improve the ease of picking up Wing we have removed elif and replaced it with <code>else if</code> .</p>
<p>We recommend running a simple find and replacement over your codebase (like&nbsp;<code>find . -type f -name "*.w" -exec perl -pi -e 's/\belif\b/else if/g' {} +</code>) to update to the new syntax.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> </span><span class="token literal-property property">x</span><span class="token operator">:</span><span class="token plain"> num </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">11</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// before</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> x </span><span class="token operator">&lt;=</span><span class="token plain"> </span><span class="token number">10</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{x} is less than or equal to 10"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> elif x </span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">10</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{x} is greater than 10"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// after</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> x </span><span class="token operator">&lt;=</span><span class="token plain"> </span><span class="token number">10</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{x} is less than or equal to 10"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> x </span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">10</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{x} is greater than 10"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Read more in the pull request (<a href="https://github.com/winglang/wing/pull/6976" target="_blank" rel="noopener noreferrer">https://github.com/winglang/wing/pull/6976</a>)</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="extable-and-exredis-are-now-winglibs">ex.Table and ex.Redis are now winglibs<a class="hash-link" aria-label="Direct link to ex.Table and ex.Redis are now winglibs" title="Direct link to ex.Table and ex.Redis are now winglibs" href="https://www.winglang.io/blog/2024/08/28/magazine-010#extable-and-exredis-are-now-winglibs">​</a></h3>
<p><code>ex.Redis</code> and <code>ex.Table</code> have not been removed from <a href="https://www.winglang.io/docs/api/standard-library" target="_blank" rel="noopener noreferrer">the standard library</a> in favour of dedicated libraries. You can now use the winglibs for <a href="https://www.winglang.io/docs/winglibs/winglibs/redis" target="_blank" rel="noopener noreferrer">Redis</a>, <a href="https://github.com/winglang/winglibs/tree/main/dynamodb" target="_blank" rel="noopener noreferrer">DynamoDB</a> and <a href="https://www.winglang.io/docs/winglibs/winglibs/postgres" target="_blank" rel="noopener noreferrer">Postgres</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="inflight-intrinsic-has-been-removed">@inflight intrinsic has been removed<a class="hash-link" aria-label="Direct link to @inflight intrinsic has been removed" title="Direct link to @inflight intrinsic has been removed" href="https://www.winglang.io/blog/2024/08/28/magazine-010#inflight-intrinsic-has-been-removed">​</a></h3>
<p>Wing supports interoperating with TypeScript and JavaScript code, these methods were previously using <code>externs</code> or <code>@inflight</code>. The interoperating with TypeScript allows you to use TypeScript code within your Wing applications.</p>
<p>After using <code>@inflight</code> and through user feedback we found a few DX issues with the intrinsic (<a href="https://github.com/winglang/wing/pull/6988" target="_blank" rel="noopener noreferrer">read pull request for more information</a>). For this reason we decided to remove the intrinsic and recommend developers to use the <a href="https://www.winglang.io/docs/api/language/using-javascript#using-extern-to-expose-javascripttypescript-functions-in-preflight-and-inflight" target="_blank" rel="noopener noreferrer"><code>extern</code>&nbsp;method</a> .</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="cloudfunction-now-accepts-json"><code>cloud.Function</code> now accepts Json<a class="hash-link" aria-label="Direct link to cloudfunction-now-accepts-json" title="Direct link to cloudfunction-now-accepts-json" href="https://www.winglang.io/blog/2024/08/28/magazine-010#cloudfunction-now-accepts-json">​</a></h3>
<p>The input and return types for <code>cloud.Function</code> has been changed from optional string (<code>str?</code>) to optional JSON (<code>Json?</code>) to align with event formats used by major cloud providers like AWS, GCP and Azure.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// before</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> x </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">payload</span><span class="token parameter operator">:</span><span class="token parameter"> str</span><span class="token parameter operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> data </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">payload</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// after </span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> x </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">payload</span><span class="token parameter operator">:</span><span class="token parameter"> </span><span class="token parameter maybe-class-name">Json</span><span class="token parameter operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">payload</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="additional-breaking-changes">Additional breaking changes<a class="hash-link" aria-label="Direct link to Additional breaking changes" title="Direct link to Additional breaking changes" href="https://www.winglang.io/blog/2024/08/28/magazine-010#additional-breaking-changes">​</a></h3>
<ul>
<li>winglib <code>cdk8s</code> has been renamed to <code>k8s</code> (<a href="https://github.com/winglang/winglibs/pull/298" target="_blank" rel="noopener noreferrer">https://github.com/winglang/winglibs/pull/298</a>)</li>
<li><code>.node</code> has been removed in favor of <code>nodeof()</code> - <a href="https://github.com/winglang/wing/pull/6721" target="_blank" rel="noopener noreferrer">https://github.com/winglang/wing/pull/6721</a></li>
<li>Removed “Optional test” operator - <a href="https://github.com/winglang/wing/pull/6804" target="_blank" rel="noopener noreferrer">https://github.com/winglang/wing/pull/6804</a></li>
<li>change <code>cloud.Function</code> event type from <code>str</code> to <code>Json</code> - <a href="https://github.com/winglang/wing/pull/6219" target="_blank" rel="noopener noreferrer">https://github.com/winglang/wing/pull/6219</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="wing-console-updates">Wing console updates<a class="hash-link" aria-label="Direct link to Wing console updates" title="Direct link to Wing console updates" href="https://www.winglang.io/blog/2024/08/28/magazine-010#wing-console-updates">​</a></h2>
<p><a href="https://www.winglang.io/docs/tools/wing-console" target="_blank" rel="noopener noreferrer">The Wing Console</a> is a web application that is designed to enhance the developer experience when viewing, exploring and interacting with your Wing applications. The wing console provides instant feedback during cloud application development process.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-table-component-uitable">New table component <code>ui.Table</code><a class="hash-link" aria-label="Direct link to new-table-component-uitable" title="Direct link to new-table-component-uitable" href="https://www.winglang.io/blog/2024/08/28/magazine-010#new-table-component-uitable">​</a></h3>
<p>Wing allows developers to create their own resources. These resources are shown in the Wing console. Using the <code>ui</code> <a href="https://www.winglang.io/docs/api/category/ui" target="_blank" rel="noopener noreferrer">standard library</a> it’s possible to add custom components for interacting with your resources and displaying information, like <a href="https://www.winglang.io/docs/api/standard-library/ui/api-reference#button-" target="_blank" rel="noopener noreferrer">Buttons</a>, <a href="https://www.winglang.io/docs/api/standard-library/ui/api-reference#field-" target="_blank" rel="noopener noreferrer">Fields</a>, <a href="https://www.winglang.io/docs/api/standard-library/ui/api-reference#filebrowser-" target="_blank" rel="noopener noreferrer">FileBrowsers</a> and now <a href="https://www.winglang.io/docs/api/standard-library/ui/api-reference#table-" target="_blank" rel="noopener noreferrer">Tables</a>.</p>
<p>In this example we create a new <code>Stripe</code> resource with a few public methods. When developers interact with this resource using the Wing console they can also see a list of customers in a table (using the <code>ui.Table</code> resource and populating it with custom data).</p>
<p><img decoding="async" loading="lazy" alt="ui.Table" src="https://www.winglang.io/assets/images/ui-table-607c6c19198a2bda1128ea3c06ed2399.png" width="3470" height="1328" class="img_ev3q"></p>
<p>Tables can be used to show any information represented by JSON into the wing console.</p>
<p>To learn more and <a href="https://www.winglang.io/docs/api/standard-library/ui/api-reference#table-" target="_blank" rel="noopener noreferrer">get started you can read the documentation</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="nodes-can-now-be-collapsed-and-expanded"><strong>Nodes can now be collapsed and expanded</strong><a class="hash-link" aria-label="Direct link to nodes-can-now-be-collapsed-and-expanded" title="Direct link to nodes-can-now-be-collapsed-and-expanded" href="https://www.winglang.io/blog/2024/08/28/magazine-010#nodes-can-now-be-collapsed-and-expanded">​</a></h2>
<p>Nodes in the Wing console can now be <strong>expanded or collapsed, helping you navigate the map view in the Wing console.</strong></p>
<p>You can try it out yourself in our playground.</p>
<p><img decoding="async" loading="lazy" alt="expand nodes in Wing console" src="https://www.winglang.io/assets/images/expand-nodes-d06e600200c8eaa5755d31787291a7c6.png" width="1422" height="424" class="img_ev3q"></p>
<p><img decoding="async" loading="lazy" src="https://prod-files-secure.s3.us-west-2.amazonaws.com/ddd63f57-ffaf-47d4-86d3-9e104107b65c/cd39a4b1-1e12-4279-b9e7-2303500154d9/Screenshot_2024-08-28_at_15.52.38.png" alt="Screenshot 2024-08-28 at 15.52.38.png" class="img_ev3q"></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="ability-to-filter-logs-in-the-wing-console">Ability to filter logs in the Wing console<a class="hash-link" aria-label="Direct link to Ability to filter logs in the Wing console" title="Direct link to Ability to filter logs in the Wing console" href="https://www.winglang.io/blog/2024/08/28/magazine-010#ability-to-filter-logs-in-the-wing-console">​</a></h3>
<p>New filter capabilities have now been added to the console. This gives developers the ability to quickly filter logs within the Wing Console.</p>
<p><img decoding="async" loading="lazy" alt="log filters in Wing console" src="https://www.winglang.io/assets/images/log-filter-90cbd54683f95e3b7d3bd961786a7bf0.png" width="2158" height="490" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="winglibs">Winglibs<a class="hash-link" aria-label="Direct link to Winglibs" title="Direct link to Winglibs" href="https://www.winglang.io/blog/2024/08/28/magazine-010#winglibs">​</a></h2>
<p><a href="https://www.winglang.io/docs/winglibs/what-are-winglibs" target="_blank" rel="noopener noreferrer">Wing libraries</a> (winglibs) are packages you can <a href="https://www.winglang.io/docs/winglibs/using-winglibs" target="_blank" rel="noopener noreferrer">import into your wing application</a>. Anybody can <a href="https://www.winglang.io/docs/winglibs/creating-winglibs" target="_blank" rel="noopener noreferrer">create a winglib</a> and add them to our <a href="https://github.com/winglang/winglibs" target="_blank" rel="noopener noreferrer">eco system of libraries</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-wing-packages">New wing packages<a class="hash-link" aria-label="Direct link to New wing packages" title="Direct link to New wing packages" href="https://www.winglang.io/blog/2024/08/28/magazine-010#new-wing-packages">​</a></h3>
<p>Here is a list of new wing packages that have been released</p>
<ul>
<li><a href="https://www.winglang.io/docs/winglibs/winglibs/momento" target="_blank" rel="noopener noreferrer">@winglibs/momento</a> -  Use the <a href="https://www.gomomento.com/" target="_blank" rel="noopener noreferrer">Momento</a> cache with Wing.</li>
<li><a href="https://www.winglang.io/docs/winglibs/winglibs/slack" target="_blank" rel="noopener noreferrer">@winglibs/slack</a> - Integrate with <a href="https://slack.com/intl/en-gb" target="_blank" rel="noopener noreferrer">Slack</a> using Wing.</li>
<li><a href="https://www.winglang.io/docs/winglibs/winglibs/ses" target="_blank" rel="noopener noreferrer">@winglibs/ses</a> - Interact with the AWS SES ervice</li>
<li><a href="https://www.winglang.io/docs/winglibs/winglibs/sns" target="_blank" rel="noopener noreferrer">@winglibs/sns</a> - Interact with the AWS SNS service</li>
</ul>
<p>Have an idea for a new winglib? Feel free to <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">reach out to us on Discord</a> or make a <a href="https://github.com/winglang/winglibs" target="_blank" rel="noopener noreferrer">pull request on GitHub</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" href="https://www.winglang.io/blog/2024/08/28/magazine-010#summary">​</a></h3>
<p>That’s it for this edition!</p>
<p>You are invited to join the&nbsp;<a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">Wing Discord</a>! Come say hello and hang out with fellow Wingnuts! Give&nbsp;<a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">winglang.io</a>&nbsp;a visit and take Wing out for a spin. If you're not already, stay updated on the latest changes in our&nbsp;<a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">repo</a>.</p>
<p>Catch you next month!</p>
<p><em>- The Wing Team</em></p>]]></content:encoded>
            <author>davidb@wing.cloud (David Boyne)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>winglang</category>
            <category>changelog</category>
            <category>newsletter</category>
        </item>
        <item>
            <title><![CDATA[Ported to Cloud with Winglang (Part One)]]></title>
            <link>https://www.winglang.io/blog/2024/6/12/ported-to-cloud</link>
            <guid>https://www.winglang.io/blog/2024/6/12/ported-to-cloud</guid>
            <pubDate>Wed, 12 Jun 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Ported to Cloud with Winglang (Part One)]]></description>
            <content:encoded><![CDATA[<div textalign:="">
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="blue-zone-application-from-hexagonal-architecture-explained">Blue Zone Application from “Hexagonal Architecture Explained<a class="hash-link" aria-label="Direct link to Blue Zone Application from “Hexagonal Architecture Explained" title="Direct link to Blue Zone Application from “Hexagonal Architecture Explained" href="https://www.winglang.io/blog/2024/6/12/ported-to-cloud#blue-zone-application-from-hexagonal-architecture-explained">​</a></h3>
</div>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:720/format:webp/1*tTBv4c0Uyl_W678h7IUDLg.jpeg" class="img_ev3q">
<p>Fig 1: The “Blue Zone” Application Ported to Cloud with Wing</p>
</div>
<p>Directly porting software applications to the cloud often results in inefficient and hard-to-maintain code. However, using the new cloud-oriented programming language <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> in combination with <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Architecture</a> has proven to be a winning combination. This approach strikes the right balance between cost, performance, flexibility, and security.</p>
<p>In this series, I will share my experiences migrating various applications from mainstream programming languages to <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>. My first experience implementing the <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Architecture</a> in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> was reported in the article "<a href="https://medium.com/itnext/hello-winglang-hexagon-6f2bdb550f37" target="_blank" rel="noopener noreferrer">Hello, Winglang Hexagon!</a>”. While it was enough to acquire confidence in this combination, it was built on an oversimplified "Hello, World" greeting service, and as such lacked some essential ingredients and was insufficient to prove the ability of such an approach to work at scale.</p>
<p>In Part One, I focus on porting the “<a href="https://github.com/HexArchBook/bluezone_pro/tree/main" target="_blank" rel="noopener noreferrer">Blue Zone</a>” application, featured in the recently published book “<a href="https://store7710079.company.site/Hexagonal-Architecture-Explained-p655931616" target="_blank" rel="noopener noreferrer">Hexagonal Architecture Explained</a>”, from <a href="https://www.java.com/en/" target="_blank" rel="noopener noreferrer">Java</a> to <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a>. The “<a href="https://github.com/HexArchBook/bluezone_pro/tree/main" target="_blank" rel="noopener noreferrer">Blue Zone</a>” application brings in a substantial code base, still not too huge to dive into unmanageable complexity, yet representative of a large class of applications. Also, the fact that it was originally written in mainstream <a href="https://www.java.com/en/" target="_blank" rel="noopener noreferrer">Java</a> brings an interesting case study of creating a cloud-native variant of such applications.</p>
<p>This report also serves as a tribute to <a href="https://jmgarridopaz.github.io/" target="_blank" rel="noopener noreferrer">Juan Manuel Garrido de Paz</a>, the book's co-author, who sadly passed away in April 2024.</p>
<p>Before we proceed, let's recap the fundamentals of the <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Architecture</a> pattern.</p>
<h1>The Hexagonal Architecture Pattern Essentials</h1>
<p>Refer to Chapter Two of the “<a href="https://store7710079.company.site/Hexagonal-Architecture-Explained-p655931616" target="_blank" rel="noopener noreferrer">Hexagonal Architecture Explained</a>” book for a detailed and formal pattern description. Here, I will bring an abridged recap of the main sense of the pattern in my own words.</p>
<p>The <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Architecture</a> pattern suggests a simple yet practical approach to separate concerns in software. Why is the separation of concerns important? Because the software code base quickly grows even for a modest in terms of delivered value application. There are too many things to take care of. Preserving cognitive control requires a high-level organization in groups or categories. To confront this challenge the <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Architecture</a> pattern suggests splitting all elements involved in a particular software application into five distinct categories and dealing with each one separately:</p>
<ol>
<li><strong>The Application itself.</strong> This category encapsulates the real value delivered to prospective customers and users. This is the reason why software is going to be developed and used in the first place. Sometimes, it’s called the <strong>Core</strong> or <strong>System Under Development (SuD).</strong> Another possible name for this part could be <strong>Computation</strong> - where external inputs are processed and final results are produced. Visually, the <strong>Application</strong> part of the system is represented in the form of a hexagon. There is nothing special or magic in this shape. As the “<a href="https://store7710079.company.site/Hexagonal-Architecture-Explained-p655931616" target="_blank" rel="noopener noreferrer">Hexagonal Architecture Explained</a>” book authors explain:</li>
</ol>
<blockquote>
<p><em>“Hexagonal Architecture” has served well as a hook to the pattern. It’s easy to remember and generates conversation. However, in this book we want to be correct: The name of the pattern is “Ports &amp; Adapters”, because there really are ports, and there really are adapters, and your architecture will show them.</em></p>
</blockquote>
<ol start="2">
<li>
<p><strong>External Actors</strong> that communicate with or are communicated by the <strong>Application</strong>. These could be human end users, electronic devices, or other <strong>Applications</strong>. The original pattern suggests further separation into <strong>Primary (or Driving) Actors</strong> - those who initiate an interaction with the <strong>Application</strong>, and <strong>Secondary (or Driven)</strong> <strong>Actors</strong> - those with whom the <strong>Application</strong> initiates communication.</p>
</li>
<li>
<p><strong>Ports</strong> - a fancy name for formal specification of <strong>Interfaces</strong> the <strong>Primary Actors</strong> could use (aka <strong>Driving Ports)</strong> or <strong>Secondary Actors</strong> need to implement (aka <strong>Driven Ports)</strong> to communicate with the <strong>Application</strong>. In addition to the formal specification of the interface verbs (e.g. <code>BuyParkingTicket</code>) <strong>Ports</strong> also provide detailed specifications of data structures that are exchanged through these interfaces.</p>
</li>
<li>
<p><strong>Adapters</strong> fill the gaps between <strong>External Actors</strong> and <strong>Ports</strong>. As the name suggests, <strong>Adapters</strong> are not supposed to perform any meaningful computations, but rather basically convert data from/to formats the <strong>Actors</strong> understand to/from data ****the <strong>Application</strong> understands.</p>
</li>
<li>
<p><strong>Configurator</strong> pulls everything together by connecting <strong>External Actors</strong> to the <strong>Application</strong> through <strong>Ports</strong> using corresponding <strong>Adapters</strong>. Depending on the architectural decisions made and price/performance/flexibility requirements these decisions were trying to address, a specific <em>Configuration</em> can be produced statically before the <strong>Application</strong> deployment or dynamically during the <strong>Application</strong> run.</p>
</li>
</ol>
<p>Contrary to popular belief, the pattern does not imply that one category, e.g. <strong>Application,</strong> is more important than others, nor does it suggest ultimately that one should be larger while others smaller. Without <strong>Ports</strong> and <strong>Adapters,</strong> no <strong>Application</strong> could be practically used. Relative sizes are often determined by non-functional requirements such as scalability, performance, cost, availability, and security.</p>
<p>The pattern suggests reducing complexity and risk by focusing on one problem at a time, temporally ignoring other aspects. It also suggests a practical way to ensure the existence of multiple configurations of the same computation each one addressing some specific needs be it test automation or operation in different environments.</p>
<p>The picture below from “<a href="https://store7710079.company.site/Hexagonal-Architecture-Explained-p655931616" target="_blank" rel="noopener noreferrer">Hexagonal Architecture Explained</a>” book nicely summarizes all main elements of the pattern:</p>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:720/format:webp/1*c8EmFj6hq4kJF_f8alZFDw.jpeg" class="img_ev3q">
<p>Fig 2: The Hexagonal Architecture Patterns in a Nutshell</p>
</div>
<h1>“Blue Zone” Sample Application</h1>
<p>From the application <a href="https://github.com/HexArchBook/bluezone_pro/tree/main" target="_blank" rel="noopener noreferrer"><code>README</code></a>:</p>
<blockquote>
<p><strong>BlueZone</strong> allows car drivers to pay remotely for parking cars at regulated zones in a city, instead of paying with coins using parking meters.</p>
</blockquote>
<ol>
<li><strong>Driving actors</strong> using the application are car drivers and *parking inspectors.</li>
</ol>
<blockquote>
</blockquote>
<ol start="2">
<li><strong>Car drivers</strong> will access the application using a Web UI (User Interface), and they can do the following:</li>
</ol>
<ul>
<li>Ask for the available rates in the city, in order to choose the one of the zone they want to park the car at.</li>
<li>Buy a ticket for parking the car during a period of time at a regulated zone. This period starts at current date-time. The ending date-time is calculated from the paid amount, according to the rate (euros/hour) of the zone.</li>
</ul>
<blockquote>
</blockquote>
<ol start="3">
<li><strong>Parking inspectors</strong> will access the application using a terminal with a CLI (Command Line Interface), and they can do the following:</li>
</ol>
<blockquote>
</blockquote>
<ul>
<li>Check a car for issuing a fine, in case that the car is illegally parked at a zone. This will happen if there is no active ticket for the car and the rate of the zone. A ticket is active if current date-time is between the starting and ending date-time of the ticket period.</li>
</ul>
<blockquote>
</blockquote>
<ol start="4">
<li><strong>Driven actors</strong> needed by the application are:</li>
</ol>
<ul>
<li>Repository with the data (rates and tickets) used in the application. It also has a sequence for getting ticket codes as they are needed.</li>
<li>Payment service that allows the car driver to buy tickets using a card. Obviously, no adapter for a real service has been developed, just a test-double (mock).</li>
<li>Date-time service for obtaining the current date-time when needed, for buying a ticket and for checking a car.</li>
</ul>
<blockquote>
</blockquote>
<p>I chose this application for two primary reasons. First, it was recommended by the “<a href="https://store7710079.company.site/Hexagonal-Architecture-Explained-p655931616" target="_blank" rel="noopener noreferrer">Hexagonal Architecture Explained</a>” book as a canonical example. Second, it was originally developed in <a href="https://www.java.com/en/" target="_blank" rel="noopener noreferrer">Java</a>. I was curious to see what is involved in porting a non-trivial <a href="https://www.java.com/en/" target="_blank" rel="noopener noreferrer">Java</a> application to the cloud using the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> programming language.</p>
<h1>Where Do You Start From?</h1>
<p>The “<a href="https://store7710079.company.site/Hexagonal-Architecture-Explained-p655931616" target="_blank" rel="noopener noreferrer">Hexagonal Architecture Explained</a>” book provides reasonable recommendations in Chapter 4.9, “What is development sequence?”. It makes sense to start with “Test-to-Test” and proceed further. However,  I did what most software engineers normally do— starting with translating the <a href="https://www.java.com/en/" target="_blank" rel="noopener noreferrer">Java</a> code to <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a>. Within a couple of part-time days, I reached a stage where I had something working locally in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> with all external interfaces simulated.</p>
<p>While technically it worked, the resulting code was far too big relative to the size of the application, hard to understand even for me, aesthetically unappealing, and completely non-Wingish. Then, I embarked on a two-week refactoring cycle, looking for the most idiomatic expression of the core pattern ideas adapted to the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> language and cloud environment specifics.</p>
<p>What comes next is different from how I worked. It was a long series of chaotic back-and-forth movements with large portions of code produced, evaluated, and scrapped. This usually happens in software development when dealing with unfamiliar technology and domains.</p>
<p>Finally, I’ve come up with something that hopefully could be gradually codified into a more structured and systematic process so that it will be less painful and more productive the next time. Therefore, I will present my findings in the conceptually desirable sequence to be used next time, rather than how it happened in reality.</p>
<h1>Thou Shalt Start with Tests</h1>
<p>To be more accurate, the best and most cost-effective way is to start with a series of acceptance tests for the system's architecturally essential <a href="https://www.ivarjacobson.com/publications/articles/use-cases-ultimate-guide" target="_blank" rel="noopener noreferrer">use cases</a>. Chapter 5.1 of the “<a href="https://store7710079.company.site/Hexagonal-Architecture-Explained-p655931616" target="_blank" rel="noopener noreferrer">Hexagonal Architecture Explained</a>” book, titled “How does this relate to use cases?”, elaborates on the deep connection between use case modeling and Hexagonal Architecture. It’s worth reading carefully.</p>
<p>Even the previous statement wasn’t 100% accurate. We are supposed to start with identifying <strong>Primary External Actors</strong> and their most characteristic ways of interacting with the system. In the case of the “<a href="https://github.com/HexArchBook/bluezone_pro/tree/main" target="_blank" rel="noopener noreferrer">Blue Zone</a>” application, there are two <strong>Primary External Actors</strong>:</p>
<ol>
<li>Card Driver</li>
<li>Parking Inspector</li>
</ol>
<p>For the Car Drive actor, her primary use case would be “Buy Ticket”; for the Parking Inspector, his primary use case would be “Check Car”. By elaborating on these use cases’ implementation we will identify <strong>Secondary External Actors</strong> and the rest of the elements.</p>
<p>The preliminary use case model resulting from this analysis is presented below:</p>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:640/format:webp/1*UPfGJ7n8hRu_N7YRTOWt8w.png" class="img_ev3q">
<p>Fig 3: “Blues Zone” Application Use Case Mode</p>
</div>
<p>Notice that the diagram above contains only one <strong>Secondary Actor</strong> - the Payment Service and does not include any internal <strong>Secondary Actors</strong> such as a database. While these technology elements will eventually be isolated from the <strong>Application</strong> by corresponding <strong>Driven Ports</strong> they do not represent any <strong>Use Case External Actor</strong>, at least in traditional interpretation of Use Case Actors.</p>
<p>Specifying use case acceptance criteria <em>before</em> starting the development is a very effective technique to ensure system stability while performing internal restructurings. In the case of the “<a href="https://github.com/HexArchBook/bluezone_pro/tree/main" target="_blank" rel="noopener noreferrer">Blue Zone</a>”  application, the use case acceptance tests were specified in <a href="https://cucumber.io/docs/gherkin/" target="_blank" rel="noopener noreferrer">Gherkin language</a> using the <a href="https://cucumber.io/docs/installation/java/" target="_blank" rel="noopener noreferrer">Cucumber for Java</a> framework.</p>
<p>Currently, a Cucumber framework for <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> does not exist for an obvious reason - it’s a very young language. While an official <a href="https://cucumber.io/docs/installation/javascript/" target="_blank" rel="noopener noreferrer">Cucumber for JavaScript</a> does exist, and there is a <a href="https://scriptable.com/typescript/typescript-cucumber-bdd/" target="_blank" rel="noopener noreferrer">TypeScript Cucumber Tutorial</a> I decided to postpone the investigation of this technology and try to reproduce a couple of tests directly in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a>.</p>
<p>Surprisingly, it was possible and worked fairly well, at least for my purposes. Here is an example of the Buy Ticket use case happy path acceptance test specified completely in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a>:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"../src"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> src</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./steps"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> steps</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">/*</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">Use Case: Buy Ticket</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">  AS</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">  a car driver</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">  I WANT TO</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">  a) obtain a list of available rates</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">  b) submit a "buy a ticket" request with the selected rate</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">  SO THAT</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">  I can park the car without being fined</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> _configurator </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">src</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Configurator</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"BuyTicketFeatureTest"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> _testFixture </span><span class="token operator">=</span><span class="token plain"> _configurator</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getForAdministering</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> _systemUnderTest </span><span class="token operator">=</span><span class="token plain"> _configurator</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getForParkingCars</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> _ </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">steps</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">BuyTicketTestSteps</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">_testFixture</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> _systemUnderTest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"Buy ticket for 2 hours; no error"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/* Given */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"name"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"eurosPerHour"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"Blue"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"0.80"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"Green"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">   </span><span class="token string" style="color:rgb(255, 121, 198)">"0.85"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"Orange"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"0.75"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">next_ticket_code_is</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"1234567890"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">current_datetime_is</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"2024/01/02 17:00"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">no_error_occurs_while_paying</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/* When */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">I_do_a_get_available_rates_request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/* Then */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">I_should_obtain_these_rates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"name"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"eurosPerHour"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"Blue"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"0.80"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"Green"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">   </span><span class="token string" style="color:rgb(255, 121, 198)">"0.85"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"Orange"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"0.75"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/* When */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">I_submit_this_buy_ticket_request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"carPlate"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"rateName"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"euros"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"card"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"6989GPJ"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"Green"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"1.70"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"1234567890123456-123-062027"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/* Then */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">this_pay_request_should_have_been_done</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"euros"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"card"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"1.70"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"1234567890123456-123-062027"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/* And */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">this_ticket_should_be_returned</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"ticketCode"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"carPlate"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"rateName"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"startingDateTime"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"endingDateTime"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">   </span><span class="token string" style="color:rgb(255, 121, 198)">"price"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"1234567890"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"6989GPJ"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"Green"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"2024/01/02 17:00"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2024/01/02 19:00"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"1.70"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/* And */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">the_buy_ticket_response_should_be_the_ticket_stored_with_code</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"1234567890"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>While it’s not a truly human-readable text, it’s close enough and not hard to understand. There are quite a few things to unpack here. Let’s proceed with them one by one.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-test-structure">The Test Structure<a class="hash-link" aria-label="Direct link to The Test Structure" title="Direct link to The Test Structure" href="https://www.winglang.io/blog/2024/6/12/ported-to-cloud#the-test-structure">​</a></h2>
<p>The test above assumes a particular project folder structure and reflects the <a href="https://www.winglang.io/docs/language-reference#4-module-system" target="_blank" rel="noopener noreferrer">Wing module and import conventions</a>, which states</p>
<blockquote>
<p>It's also possible to import a directory as a module. The module will contain all public types defined in the directory's files. If the directory has subdirectories, they will be available under the corresponding names.</p>
</blockquote>
<p>From the first two lines, we can conclude that the project has two main folders: <code>src</code> where all source code is located, and <code>test</code> where all tests are located. Further, there is a <code>test\steps</code> subfolder where individual test step implementations are kept.</p>
<p>The next three lines allocate a <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">preflight</a> <code>Configurator</code> object and extract from it two pointers:</p>
<ol>
<li><code>_testFixture</code> pointing to a <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">preflight</a> class responsible for the test setup</li>
<li><code>_systemUnderTest</code> which points to a <strong>Primary Port Interface</strong> intended for Car Drivers.</li>
</ol>
<p>Within the “Buy ticket for 2 hours; no errors”, we allocate an <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">inflight</a> <code>BuyTicketTestSteps</code> object responsible for implementing individual steps. Conventionally, this object gets an almost invisible name underscore, which improves the overall test readability. This is a common technique for developing a <a href="https://www.martinfowler.com/dsl.html" target="_blank" rel="noopener noreferrer">Domain-Specific Language</a> (DSL) embedded in a general-purpose host language.</p>
<p>It’s important to stress, that while it did not happen in my case, it’s fully conceivable to start the project with a simple <code>src</code> and <code>test\steps</code> folder structure and a simple test setup to drive other architectural decisions.</p>
<p>Of course, with no steps implemented, the test will not even pass compilation. To make progress, we need to look inside the <code>BuyTicketTestSteps</code> class.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="test-steps-class">Test Steps Class<a class="hash-link" aria-label="Direct link to Test Steps Class" title="Direct link to Test Steps Class" href="https://www.winglang.io/blog/2024/6/12/ported-to-cloud#test-steps-class">​</a></h2>
<p>The test steps class for the Buy Ticket Use Case is presented below:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./Parser.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./TestStepsBase.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> base</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"../../src/application/ports"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">BuyTicketTestSteps</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name">base</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">TestStepsBase</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _systemUnderTest</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForParkingCars</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">var</span><span class="token plain"> _currentAvailableRates</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Set</span><span class="token operator">&lt;</span><span class="token plain">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Rate</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">var</span><span class="token plain"> _currentBoughtTicket</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Ticket</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        testFixture</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForAdministering</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        systemUnderTest</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForParkingCars</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">testFixture</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_systemUnderTest</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> systemUnderTest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_currentBoughtTicket</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> nil</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_currentAvailableRates</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token known-class-name class-name">Set</span><span class="token operator">&lt;</span><span class="token plain">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Rate</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">the_existing_rates_in_the_repository_are</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        sRates</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">testFixture</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">initializeRates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Rates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sRates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">toArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">next_ticket_code_is</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">ticketCode</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">testFixture</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">changeNextTicketCode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">ticketCode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">no_error_occurs_while_paying</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">testFixture</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">setPaymentError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">PaymentError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">NONE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">I_do_a_get_available_rates_request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_currentAvailableRates</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_systemUnderTest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getAvailableRates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">I_should_obtain_these_rates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sRates</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> expected </span><span class="token operator">=</span><span class="token plain"> parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Rates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sRates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_currentAvailableRates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> expected</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">I_submit_this_buy_ticket_request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sRequest</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> request </span><span class="token operator">=</span><span class="token plain"> parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">BuyRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">setCurrentThrownException</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">nil</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_currentBoughtTicket</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> nil</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_currentBoughtTicket</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_systemUnderTest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">buyTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> err </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">setCurrentThrownException</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">this_ticket_should_be_returned</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sTicket</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> sTicketFull </span><span class="token operator">=</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            sTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">at</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">concat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"paymentId"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            sTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">at</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">concat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">testFixture</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getLastPayResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> expected </span><span class="token operator">=</span><span class="token plain"> parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Ticket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sTicketFull</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_currentBoughtTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> expected</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">this_pay_request_should_have_been_done</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sRequest</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> expected </span><span class="token operator">=</span><span class="token plain"> parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">PayRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> actual </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">testFixture</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getLastPayRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">actual</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> expected</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">the_buy_ticket_response_should_be_the_ticket_stored_with_code</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">code</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> actual </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">testFixture</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getStoredTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">code</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">actual</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_currentBoughtTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">an_error_occurs_while_paying</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">error</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">testFixture</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">setPaymentError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">PaymentError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">a_PayErrorException_with_the_error_code_that_occurred_should_have_been_thrown</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">code</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token comment" style="color:rgb(98, 114, 164)">//TODO: make it more specific</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> err </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getCurrentThrownException</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">ok</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">contains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">code</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">no_ticket_with_code_should_have_been_stored</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">code</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">testFixture</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getStoredTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">code</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">ok</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Should never get there"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> err </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">ok</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">contains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"KeyError"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This class is straightforward: it parses the input data, uniformly presented as <code>Array&lt;Array&lt;str&gt;&gt;</code>, into application-specific data structures, sends them to either <code>testFixture</code> or <code>_systemUnderTest</code> objects, keeps intermediate results, and compares expected vs actual results where appropriate.</p>
<p>The only specifics to pay attention to are the proper handling of <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">preflight</a> and <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">inflight</a> definitions. I’m grateful to <a href="https://www.linkedin.com/in/cristian-pallar%C3%A9s-88139916/" target="_blank" rel="noopener noreferrer">Cristian Pallares</a>, who helped me to make it right.</p>
<p>We have three additional elements with clearly delineated responsibilities:</p>
<ol>
<li><strong>Parser</strong> - ****Responsible for converting a uniform array of string inputs to the application-specific data structures.</li>
<li><strong>Test Fixture</strong> - ****Responsible for backdoor communication with the system for preconditions setting and postconditions verification.</li>
<li><strong>System Under Test</strong> - ****Responsible for implementing the application logic.</li>
</ol>
<p>Let’s take a closer look at each one.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="parser">Parser<a class="hash-link" aria-label="Direct link to Parser" title="Direct link to Parser" href="https://www.winglang.io/blog/2024/6/12/ported-to-cloud#parser">​</a></h2>
<p>The source code of the <strong>Parser</strong> module is presented below:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring structx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring datetimex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"../../src/application/ports"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Util</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">Rates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sRates</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Set</span><span class="token operator">&lt;</span><span class="token plain">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Rate</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">unsafeCast</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            structx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromFieldArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                sRates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Rate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">schema</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">BuyRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    sRequest</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">BuyTicketRequest</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> requestSet</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Set</span><span class="token operator">&lt;</span><span class="token plain">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">BuyTicketRequest</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">unsafeCast</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            structx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromFieldArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                sRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">BuyTicketRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">schema</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> requestSet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">toArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">at</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">Tickets</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    sTickets</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Set</span><span class="token operator">&lt;</span><span class="token plain">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Ticket</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">unsafeCast</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            structx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromFieldArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                sTickets</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Ticket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">schema</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                datetimex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">DatetimeFormat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">YYYYMMDD_HHMM</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">Ticket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sTicket</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Ticket</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token maybe-class-name">Util</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Tickets</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">toArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">at</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">PayRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    sRequest</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">PayRequest</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> requestSet</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Set</span><span class="token operator">&lt;</span><span class="token plain">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">PayRequest</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">unsafeCast</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            structx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromFieldArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                sRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">PayRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">schema</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> requestSet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">toArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">at</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">CheckCarRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    sRequest</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">CheckCarRequest</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> requestSet</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Set</span><span class="token operator">&lt;</span><span class="token plain">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">CheckCarRequest</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">unsafeCast</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            structx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromFieldArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                sRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">CheckCarRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">schema</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> requestSet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">toArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">at</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">CheckCarResult</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    sResult</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">CheckCarResult</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> resultSet</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Set</span><span class="token operator">&lt;</span><span class="token plain">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">CheckCarResult</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">unsafeCast</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            structx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromFieldArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                sResult</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">CheckCarResult</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">schema</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> resultSet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">toArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">at</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">DateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">dateTime</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Datetime</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> datetimex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            dateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            datetimex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">DatetimeFormat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">YYYYMMDD_HHMM</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token known-class-name class-name">PaymentError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">error</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">PaymentError</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">PaymentError</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"NONE"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">PaymentError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">NONE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"GENERIC_ERROR"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">PaymentError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">GENERIC_ERROR</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"CARD_DECLINED"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">PaymentError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">CARD_DECLINED</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This class, while not sophisticated from the algorithmic point of view, reflects some important architectural decisions with far-reaching consequences.</p>
<p>First, it announces a dependency on the system <strong>Ports</strong> located in the <code>src\application\ports</code> folder.  Chapter 4.8 of the “<a href="https://store7710079.company.site/Hexagonal-Architecture-Explained-p655931616" target="_blank" rel="noopener noreferrer">Hexagonal Architecture Explained</a>” book, titled “Where do I put my files?”, makes a clear statement:</p>
<blockquote>
<p>The folder structure is not covered by the pattern, nor is it the same in all languages. Some languages (Java), require interface definitions. Some (Python, Ruby) don't. And some, such as Smalltalk, don't even have the concept of files!</p>
</blockquote>
<p>It warns, however, that “we’ve observed that folder structures that don't match the intentions of the pattern end up causing damage”. For strongly typed languages like <a href="https://www.java.com/en/" target="_blank" rel="noopener noreferrer">Java</a><strong>,</strong> it recommends keeping specifications of <strong>Driving</strong> and <strong>Driven Ports</strong> in separate folders.</p>
<p>I started with such a structure, but very soon realized that it just enlarges the size of the code and prevents it from taking full advantage of the <a href="https://www.winglang.io/docs/language-reference#4-module-system" target="_blank" rel="noopener noreferrer">Wing module and import conventions</a>. Based on this I decided to keep all <strong>Ports</strong> in one dedicated folder. Considering the current size of the application, this decision looks justified.</p>
<p>Second, it exploits an undocumented <a href="https://www.winglang.io/docs/language-reference#4-module-system" target="_blank" rel="noopener noreferrer">Wing module and import</a> feature that makes all public static <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">inflight</a> methods of a class named <code>Util</code> directly accessible by the client modules, which improves the code readability.</p>
<p>Third, it uses two <a href="https://www.winglang.io/docs/category/standard-library" target="_blank" rel="noopener noreferrer">Wing Standard Library</a> extensions, <code>datetimex</code>, and <code>structx</code> developed to compensate for some features I needed. These extensions were part of my “In Search for Winglang Middleware” project <code>endor.w</code>, I reported about <a href="https://medium.com/itnext/in-search-for-winglang-middleware-9d1be0782108" target="_blank" rel="noopener noreferrer">here</a>, <a href="https://medium.com/itnext/in-search-for-winglang-middleware-868443bd81f2" target="_blank" rel="noopener noreferrer">here</a>, and <a href="https://medium.com/itnext/managing-winglang-libraries-with-aws-codeartifact-e0929ee94fe9" target="_blank" rel="noopener noreferrer">here</a>.</p>
<p>Justification for these extensions will be clarified when we look at the core architectural decision about representing the <strong>Port Interfaces and Data</strong>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="representing-port-interfaces-and-data">Representing Port Interfaces and Data<a class="hash-link" aria-label="Direct link to Representing Port Interfaces and Data" title="Direct link to Representing Port Interfaces and Data" href="https://www.winglang.io/blog/2024/6/12/ported-to-cloud#representing-port-interfaces-and-data">​</a></h2>
<p>Traditional strongly typed Object-Oriented languages like <a href="https://www.java.com/en/" target="_blank" rel="noopener noreferrer">Java</a> advocate encapsulating all domain elements as objects. If I followed this advice, the <code>Ticket</code> object would look something like this:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Ticket</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub ticketCode</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub carPlate</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub rateName</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub startingDateTime</span><span class="token operator">:</span><span class="token plain"> std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Datetime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub endingDateTime</span><span class="token operator">:</span><span class="token plain"> std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Datetime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub price</span><span class="token operator">:</span><span class="token plain"> num</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub paymentId</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">ticketCode</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token spread operator">...</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">ticketCode</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> ticketCode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token spread operator">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub </span><span class="token function" style="color:rgb(80, 250, 123)">toJson</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">       ticketCode </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">ticketCode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">       </span><span class="token spread operator">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">fromJson</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">data</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Ticket</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Ticket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"ticketCode"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">asStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token spread operator">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">   </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub </span><span class="token function" style="color:rgb(80, 250, 123)">toFieldArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">ticketCode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token spread operator">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">fromFieldArray</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">records</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Set</span><span class="token operator">&lt;</span><span class="token maybe-class-name">Ticket</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> result </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">MutSet</span><span class="token class-name operator">&lt;</span><span class="token class-name">Ticket</span><span class="token class-name operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> record </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> records </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">add</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Ticket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        record</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">at</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token spread operator">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">copy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> such</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Such an approach introduces 6 extra lines of code per data field for initialization and conversation plus some fixed overhead of method definition. This creates a significant boilerplate overhead.</p>
<p>Mainstream languages like <a href="https://www.java.com/en/" target="_blank" rel="noopener noreferrer">Java</a> and <a href="https://www.python.org/" target="_blank" rel="noopener noreferrer">Python</a> try alleviating this pain with various meta-programming automation tools, such as decorators, abstract base classes, or meta-classes.</p>
<p>In <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a>, all this proved to be sub-optimal and unnecessary, provided minor adjustments were made to the <a href="https://www.winglang.io/docs/category/standard-library" target="_blank" rel="noopener noreferrer">Wing Standard Library</a>.</p>
<p>Here is how the <code>Ticket</code> data structure can be defined:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub struct </span><span class="token maybe-class-name">Ticket</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">                 </span><span class="token comment" style="color:rgb(98, 114, 164)">//Data structure representing objects </span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">																		</span><span class="token comment" style="color:rgb(98, 114, 164)">//with the data of a parking ticket:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    ticketCode</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">                </span><span class="token comment" style="color:rgb(98, 114, 164)">//Unique identifier of the ticket;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                                    </span><span class="token comment" style="color:rgb(98, 114, 164)">//It is a 10-digit number with leading zeros</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                                    </span><span class="token comment" style="color:rgb(98, 114, 164)">//if necessary</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    carPlate</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">                  </span><span class="token comment" style="color:rgb(98, 114, 164)">//Plate of the car that has been parked</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    rateName</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">                  </span><span class="token comment" style="color:rgb(98, 114, 164)">//Rate name of the zone where </span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">																    </span><span class="token comment" style="color:rgb(98, 114, 164)">//the car is parked at</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    startingDateTime</span><span class="token operator">:</span><span class="token plain"> std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Datetime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">//When the parking period begins</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    endingDateTime</span><span class="token operator">:</span><span class="token plain"> std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Datetime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">   </span><span class="token comment" style="color:rgb(98, 114, 164)">//When the parking period expires</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    price</span><span class="token operator">:</span><span class="token plain"> num</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">                     </span><span class="token comment" style="color:rgb(98, 114, 164)">//Amount of euros paid for the ticket</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    paymentId</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">                 </span><span class="token comment" style="color:rgb(98, 114, 164)">//Unique identifier of the payment </span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">																    </span><span class="token comment" style="color:rgb(98, 114, 164)">//made to get the ticket.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>In <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a>, structures are immutable by default, and that eliminates a lot of access control problems.</p>
<p>Without any change, the <a href="https://www.winglang.io/docs/category/standard-library" target="_blank" rel="noopener noreferrer">Wing Standard Library</a> will support out-of-the-box <code>Json.stringify(ticket)</code> serialization to <code>Json</code> string and <code>Ticket.fromJson(data)</code> de-serialization. That’s not enough for the following reasons:</p>
<ol>
<li>For data storage, we need conversion of the <code>Ticket</code> objects to <code>Json</code> rather than a <code>Json string</code></li>
<li><code>Json</code> serialization and de-serialization functions need to handle the <code>std.Datetime</code> fields correctly. Currently the <code>Json.stringify()</code> will convert any <code>std.Datetime</code> to an ISO string, but <code>Ticket.fromJson()</code> will fail.</li>
<li>To support test automation and different CSV formats, we need the ability to convert data structures to and from an array of strings.</li>
<li>There is a need for a more flexible conversion of strings to <code>std.Datetime</code>. For example, the “Blue Zone” application uses the YYYYMM HH:MM format.</li>
</ol>
<p>All these additional needs were addressed in two <a href="https://www.winglang.io/docs/libraries#creating-a-wing-library" target="_blank" rel="noopener noreferrer">Trusted Wing Libraries</a>: <code>datetimex</code> and <code>struct</code>. While the implementation was not trivial and required a good understanding of how <a href="https://www.winglang.io/docs/typescript/" target="_blank" rel="noopener noreferrer">Wing and TypeScript</a> interoperability works, it was doable with reasonable effort. Hopefully, these extensions can be included in future versions of the <a href="https://www.winglang.io/docs/category/standard-library" target="_blank" rel="noopener noreferrer">Wing Standard Library</a>.</p>
<p>The special, <code>unsafeCast</code> function helped to overcome the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> strong type checking limitations. To provide better support for actual vs expected comparison in tests, I decided that <code>fromFieldArray(...)</code> will return <code>Set&lt;...&gt;</code> objects. Occasionally it required <code>toArray()</code> conversion, but I found this affordable.</p>
<p>Now, let’s take a look at the main <code>_systemUnderTest</code> object.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="forparkingcars-port">ForParkingCars Port<a class="hash-link" aria-label="Direct link to ForParkingCars Port" title="Direct link to ForParkingCars Port" href="https://www.winglang.io/blog/2024/6/12/ported-to-cloud#forparkingcars-port">​</a></h2>
<p>Following the “<a href="https://store7710079.company.site/Hexagonal-Architecture-Explained-p655931616" target="_blank" rel="noopener noreferrer">Hexagonal Architecture Explained</a>” book recommendations, port naming adopts the <strong>ForActorName</strong> convention. Here is how it is defined for the <strong>ParkingCar External Actor</strong>:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub struct </span><span class="token maybe-class-name">BuyTicketRequest</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> 	</span><span class="token comment" style="color:rgb(98, 114, 164)">//Input data needed for buying a ticket </span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">																</span><span class="token comment" style="color:rgb(98, 114, 164)">//to park a car:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		carPlate</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">		</span><span class="token comment" style="color:rgb(98, 114, 164)">//Plate of the car that has been parked</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    rateName</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">		</span><span class="token comment" style="color:rgb(98, 114, 164)">//Rate name of the zone where the car is parked at</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    euros</span><span class="token operator">:</span><span class="token plain"> num</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">				</span><span class="token comment" style="color:rgb(98, 114, 164)">//Euros amount to be paid</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    card</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">				</span><span class="token comment" style="color:rgb(98, 114, 164)">//Card used for paying, in the format 'n-c-mmyyyy', where</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	              			</span><span class="token comment" style="color:rgb(98, 114, 164)">//	'n' is the card number (16 digits)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	              			</span><span class="token comment" style="color:rgb(98, 114, 164)">//	'c' is the verification code (3 digits),</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	              			</span><span class="token comment" style="color:rgb(98, 114, 164)">//	'mmyyyy' is the expiration month and year (6 digits)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"> * DRIVING PORT (Provided Interface)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">interface</span><span class="token plain"> </span><span class="token class-name">ForParkingCars</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * @return	A set with the existing rates for parking a car in regulated </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * zones of the city.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * If no rates exist, an empty set is returned.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">     </span><span class="token function" style="color:rgb(80, 250, 123)">getAvailableRates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Set</span><span class="token operator">&lt;</span><span class="token plain">rate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Rate</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * Pay for a ticket to park a car at a zone regulated by a rate,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * and save the ticket in the repository.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * The validity period of the ticket begins at the current date-time,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * and its duration is calculated in minutes by applying the rate,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * based on the amount of euros paid.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * @param request	Input data needed for buying a ticket.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * 					@see BuyTicketRequest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * @return	A ticket valid for parking the car at a zone regulated by the rate,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * 			paying the euros amount using the card.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * 			The ticket holds a reference to the identifier of the payment </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 *      that was made.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * @throws	BuyTicketRequestException</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * 			If any input data in the request is not valid.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * @throws	PayErrorException</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 * 			If any error occurred while paying.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">	 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token function" style="color:rgb(80, 250, 123)">buyTicket</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">BuyTicketRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ticket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Ticket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>As with <code>Ticket</code> and <code>Rate</code> objects, the <code>BuyTicketRequest</code> object is defined as a plain <a href="https://www.winglang.io/docs/language-reference#31-structs" target="_blank" rel="noopener noreferrer">Wing <code>struct</code></a> relying on the automatic conversion infrastructure described above.</p>
<p>The <code>ForParkingCars</code> is defined as the <a href="https://www.winglang.io/docs/language-reference#34-interfaces" target="_blank" rel="noopener noreferrer">Wing <code>interface</code></a>. Unlike the original “Blue Zone” <a href="https://github.com/HexArchBook/bluezone_pro/blob/main/src/application/bluezone-app/src/main/java/io/github/hexarchbook/bluezone/app/ports/driving/forparkingcars/BuyTicketRequest.java" target="_blank" rel="noopener noreferrer">implementation</a>, this one does not include <code>BuyTicketRequest</code> validation in the port specification. This was done on purpose.</p>
<p>While strong object encapsulation would encourage including the <code>validate()</code> method in the <code>BuyTicketRequest</code> class, with open immutable data structures like the ones adopted here, it could be done where it belongs - in the use case implementation. On the other hand, including the request validation logic in port specification brings in too many implementation details, too early.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="foradministering-port">ForAdministering Port<a class="hash-link" aria-label="Direct link to ForAdministering Port" title="Direct link to ForAdministering Port" href="https://www.winglang.io/blog/2024/6/12/ported-to-cloud#foradministering-port">​</a></h2>
<p>This one is used for providing <code>testFixture</code> functionality, and while it is long, it is also completely straightforward:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./Rate.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> rate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./Ticket.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> ticket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./ForPaying.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> forPaying</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"> * DRIVING PORT (Provided Interface)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"> * For doing administration tasks like initializing, load data in the repositories,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"> * configuring the services used by the app, etc.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"> * Typically, it is used by:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"> *      - Tests (driving actors) for setting up the test-fixture (driven actors).</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"> *      - The start-up for initializing the app.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">interface</span><span class="token plain"> </span><span class="token class-name">ForAdministering</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    * Load the given rates into the data repository,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    * deleting previously existing rates if any.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">initializeRates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">newRates</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">rate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Rate</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    * Load the given tickets into the data repository,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    * deleting previously existing tickets if any.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">initializeTickets</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">newTickets</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">ticket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Ticket</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    * Make the given ticket code the next to be returned when asking for it.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">changeNextTicketCode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">newNextTicketCode</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    * Return the ticket stored in the repository with the given code</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">getStoredTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">ticketCode</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ticket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Ticket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    * Return the last request done to the "pay" method</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">getLastPayRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> forPaying</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">PayRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    * Return the last response returned by the "pay" method.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    * It is an identifier of the payment made.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">getLastPayResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    * Make the probability of a payment error the "percentage" given as a parameter</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">setPaymentError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">errorCode</span><span class="token operator">:</span><span class="token plain"> forPaying</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">PaymentError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    * Return the code of the error that occurred when running the "pay" method</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">getPaymentError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> forPaying</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">PaymentError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    * Set the given date-time as the current date-time</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">    */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">changeCurrentDateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">newCurrentDateTime</span><span class="token operator">:</span><span class="token plain"> std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Datetime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now, we need to dive one level deeper and look at the application logic implementation.</p>
<h1>Implementation Details</h1>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="forparkingcarsbackend">ForParkingCarsBackend<a class="hash-link" aria-label="Direct link to ForParkingCarsBackend" title="Direct link to ForParkingCarsBackend" href="https://www.winglang.io/blog/2024/6/12/ported-to-cloud#forparkingcarsbackend">​</a></h2>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"../../application/ports"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"../../application/usecases"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> usecases</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">ForParkingCarsBackend</span><span class="token plain"> impl ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForParkingCars</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _buyTicket</span><span class="token operator">:</span><span class="token plain"> usecases</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">BuyTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _getAvailableRates</span><span class="token operator">:</span><span class="token plain"> usecases</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">GetAvailableRates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        dataRepository</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForStoringData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        paymentService</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForPaying</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        dateTimeService</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForObtainingDateTime</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_buyTicket</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">usecases</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">BuyTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">dataRepository</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> paymentService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> dateTimeService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_getAvailableRates</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">usecases</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">GetAvailableRates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">dataRepository</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">getAvailableRates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Set</span><span class="token operator">&lt;</span><span class="token plain">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Rate</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getAvailableRates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">apply</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">buyTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">BuyTicketRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Ticket</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_buyTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">apply</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This class resides in the <code>src/outside/backend</code> folder and provides an implementation of the <code>ports.ForParkingCars</code> interface that is suitable for a direct function call. As we can see, it assumes two additional <strong>Secondary Ports</strong>: <code>ports.ForStoringData</code> and <code>ports.ForObtainingTime</code> and delegates actual implementation to two Use Case implementations: <code>BuyTicket</code> and <code>GetAvailableRates</code>. The <code>BuyTicket</code> Use Case implementation is where the core system logic resides, so let’s look at it.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="buyticket-use-case">BuyTicket Use Case<a class="hash-link" aria-label="Direct link to BuyTicket Use Case" title="Direct link to BuyTicket Use Case" href="https://www.winglang.io/blog/2024/6/12/ported-to-cloud#buyticket-use-case">​</a></h2>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring math</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring datetimex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring exception</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"../ports"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./Verifier.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> validate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">BuyTicket</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _dataRepository</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForStoringData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _paymentService</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForPaying</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _dateTimeService</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForObtainingDateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        dataRepository</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForStoringData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        paymentService</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForPaying</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        dateTimeService</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForObtainingDateTime</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_dataRepository</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> dataRepository</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_paymentService</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> paymentService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_dateTimeService</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> dateTimeService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">    </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">apply</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">BuyTicketRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Ticket</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> currentDateTime </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_dateTimeService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getCurrentDateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_validateRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> currentDateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> paymentId </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_paymentService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">pay</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            euros</span><span class="token operator">:</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">euros</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            card</span><span class="token operator">:</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">card</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> ticket </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_buildTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> paymentId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> currentDateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_dataRepository</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">saveTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">ticket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> ticket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">    </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    inflight </span><span class="token function" style="color:rgb(80, 250, 123)">_validateRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">BuyTicketRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> currentDateTime</span><span class="token operator">:</span><span class="token plain"> std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Datetime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> requestErrors </span><span class="token operator">=</span><span class="token plain"> validate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">BuyTicketRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> currentDateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> requestErrors</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">0</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> exception</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">ValueError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"Buy ticket request is not valid"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                requestErrors</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    inflight </span><span class="token function" style="color:rgb(80, 250, 123)">_buildTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        request</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">BuyTicketRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        paymentId</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        currentDateTime</span><span class="token operator">:</span><span class="token plain"> std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Datetime</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Ticket</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> ticketCode </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_dataRepository</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">nextTicketCode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> rate </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_dataRepository</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getRateByName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">rateName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> endingDateTime </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">BuyTicket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_calculateEndingDateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            currentDateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">euros</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            rate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">eurosPerHour</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Ticket</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            ticketCode</span><span class="token operator">:</span><span class="token plain"> ticketCode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            carPlate</span><span class="token operator">:</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">carPlate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            rateName</span><span class="token operator">:</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">rateName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            startingDateTime</span><span class="token operator">:</span><span class="token plain"> currentDateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            endingDateTime</span><span class="token operator">:</span><span class="token plain"> endingDateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            price</span><span class="token operator">:</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">euros</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            paymentId</span><span class="token operator">:</span><span class="token plain"> paymentId</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">     * minutes = (euros * minutesPerHour) / eurosPerHour</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">     * endingDateTime = startingDateTime + minutes</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">     </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> inflight </span><span class="token function" style="color:rgb(80, 250, 123)">_calculateEndingDateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        startingDateTime</span><span class="token operator">:</span><span class="token plain"> std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Datetime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        euros</span><span class="token operator">:</span><span class="token plain"> num</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        eurosPerHour</span><span class="token operator">:</span><span class="token plain"> num</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Datetime</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">MINUTES_PER_HOUR</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">60</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> minutes </span><span class="token operator">=</span><span class="token plain"> math</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">round</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token constant" style="color:rgb(189, 147, 249)">MINUTES_PER_HOUR</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> euros</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">/</span><span class="token plain"> eurosPerHour</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> datetimex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">plus</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">startingDateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> duration</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromMinutes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">minutes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The “Buy Ticket” Use Case implementation class resides within the <code>src/application/usescases</code> folder. It returns an <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">inflight</a> function responsible for executing the Use Case logic:</p>
<ol>
<li>Validate Request</li>
<li>Pay for a new <code>Ticket</code></li>
<li>Create the <code>Ticket</code> record</li>
<li>Store the <code>Ticket</code> record in the database</li>
</ol>
<p>The main reason for implementing Use Cases as <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">inflight</a> functions is that all <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> event handlers are <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">inflight</a> functions. While direct function calls are useful for local testing, they will typically be HTTP REST or GraphQL API calls in a real deployment.</p>
<p>The actual validation of the <code>BuyTicketRequest</code> is delegated to an auxiliary <code>Util</code> class within the <code>Verifier.w</code> module. The main reason is that individual field validation might be very detailed and involve many low-level specifics, contributing little to the overall use case logic understanding.</p>
<h1>Pulling all Components Together</h1>
<p>Following the “<a href="https://store7710079.company.site/Hexagonal-Architecture-Explained-p655931616" target="_blank" rel="noopener noreferrer">Hexagonal Architecture Explained</a>” book recommendations, this is implemented within a <code>Configurator</code> class as follows:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring util</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./outside"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> outside</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./application/ports"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">enum</span><span class="token plain"> </span><span class="token maybe-class-name">ApiType</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token constant" style="color:rgb(189, 147, 249)">DIRECT_CALL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token constant" style="color:rgb(189, 147, 249)">HTTP_REST</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">enum</span><span class="token plain"> </span><span class="token maybe-class-name">ProgramType</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token constant" style="color:rgb(189, 147, 249)">UNKNOWN</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token constant" style="color:rgb(189, 147, 249)">TEST</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token constant" style="color:rgb(189, 147, 249)">SERVICE</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Configurator</span><span class="token plain"> impl outside</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">BlueZoneApiFactory</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _apiFactory</span><span class="token operator">:</span><span class="token plain"> outside</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">BlueZoneApiFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> mockService </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">outside</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">mock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">MockDataRepository</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> programType </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getProgramType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> mode </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getMode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">programType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> apiType </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getApiType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">programType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_apiFactory</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getApiFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            apiType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            mockService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            mockService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            mockService</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">_getProgramType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">ProgramType</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">//TODO: migrate to endor??</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">endsWith</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Test"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token maybe-class-name">ProgramType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TEST</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> elif name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">endsWith</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Service"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">||</span><span class="token plain"> name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">endsWith</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Application"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token maybe-class-name">ProgramType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">SERVICE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> elif std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">of</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">isTestEnvironment</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token maybe-class-name">ProgramType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TEST</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token maybe-class-name">ProgramType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">UNKNOWN</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">_getMode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">programType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">ProgramType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> mode </span><span class="token operator">=</span><span class="token plain"> util</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryEnv</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MODE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">//TODO Migrate this function to endor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"DEV"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEV</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"TEST"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TEST</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"STAGE"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">STAGE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"PROD"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">PROD</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> elif programType </span><span class="token operator">==</span><span class="token plain"> </span><span class="token maybe-class-name">ProgramType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TEST</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TEST</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> elif programType </span><span class="token operator">==</span><span class="token plain"> </span><span class="token maybe-class-name">ProgramType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">SERVICE</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">STAGE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEV</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">_getApiType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        programType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">ProgramType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        mode</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">ApiType</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> apiType </span><span class="token operator">=</span><span class="token plain"> util</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryEnv</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"API_TYPE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token maybe-class-name">ApiType</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"DIRECT_CALL"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token maybe-class-name">ApiType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DIRECT_CALL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"HTTP_REST"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token maybe-class-name">ApiType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">HTTP_REST</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">apiType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> elif programType </span><span class="token operator">==</span><span class="token plain"> </span><span class="token maybe-class-name">ProgramType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">SERVICE</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token maybe-class-name">ApiType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">HTTP_REST</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> target </span><span class="token operator">=</span><span class="token plain"> util</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"WING_TARGET"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> target</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">contains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"sim"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token maybe-class-name">ApiType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DIRECT_CALL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token maybe-class-name">ApiType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">HTTP_REST</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">        </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">_getApiFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        mode</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        apiType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">ApiType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        dataService</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForStoringData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        paymentService</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForPaying</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        dateTimeService</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForObtainingDateTime</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> outside</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">BlueZoneApiFactory</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> directCall </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">outside</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">DirectCallApiFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            dataService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            paymentService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            dateTimeService</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> apiType </span><span class="token operator">==</span><span class="token plain"> </span><span class="token maybe-class-name">ApiType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DIRECT_CALL</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> directCall</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> elif apiType </span><span class="token operator">==</span><span class="token plain"> </span><span class="token maybe-class-name">ApiType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">HTTP_REST</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">outside</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">HttpRestApiFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                directCall</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">getForAdministering</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForAdministering</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_apiFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getForAdministering</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">getForParkingCars</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForParkingCars</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_apiFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getForParkingCars</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">getForIssuingFines</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ForIssuingFines</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_apiFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getForIssuingFines</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This is an experimental, still not final, implementation, but it could be extended to address the production deployment needs. It adopts a static system configuration by exploiting the <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">Wing preflight</a> machinery.</p>
<p>In this implementation, a special <code>MockDataStore</code> object implements all three <strong>Secondary Ports</strong>: data service, paying service, and date-time service. It does not have to be this way and was created to save time during the scaffolding development.</p>
<p>The main responsibility of the <code>Configuratior</code> class is to determine which type of API should be used:</p>
<ol>
<li>Direct call</li>
<li>Local HTTP REST</li>
<li>Remote HTTP REST</li>
<li>Local HTTP REST plus HTML</li>
<li>Remote HTTP REST plus HTML</li>
</ol>
<p>The actual API creation is delegated to corresponding <code>ApiFactory</code> classes.</p>
<p>What is remarkable about such an implementation is that the same test suite is used for all configurations, except for real HTML-based UI mode. The latter could also be achieved but would require some HTML test drivers like <a href="https://www.selenium.dev/" target="_blank" rel="noopener noreferrer">Selenium</a>.</p>
<p>It is the first time I have achieved such a level of code reuse. As a result, I run local direct call configuration most of the time, especially when I perform code structure refactoring, with full confidence that it will run in a remote test and production environment without a change. This proves that the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> cloud-oriented programming language and <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Architecture</a> is truly a winning combination.</p>
<h1>The Big Picture</h1>
<p>Including the full source code of every module would increase this article's size too much. Access to the GitHub repository for this project is available on demand.</p>
<p>Instead, I will present the overall folder structure, two UML class diagrams, and a cloud resources diagram reflecting the main program elements and their relationships.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-folder-structure">The Folder Structure<a class="hash-link" aria-label="Direct link to The Folder Structure" title="Direct link to The Folder Structure" href="https://www.winglang.io/blog/2024/6/12/ported-to-cloud#the-folder-structure">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── src</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   ├── application</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   ├── ports</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── ForAdministering.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── ForIssuingFines.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── ForObtainingDateTime.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── ForParkingCars.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── ForPaying.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── ForStoringData.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── Rate.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   └── Ticket.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   ├── usecases</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── BuyTicket.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── CheckCar.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── GetAvailableRates.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   └── Veryfier.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   ├── outside</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   ├── backend</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── ForAdministeringBackend.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── ForIssuingFinesBackend.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   └── ForParkingCarsBackend.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   ├── http</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── html</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   │    ├── _htmlForParkingCarsFormatter.ts</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   │    └── htmlForParkingCarsFormatter.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── json</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   │    ├── jsonForIssuingFinesFormatter.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   │    └── jsonForParkingCarsFormatter.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── ForIssuingFinesClient.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── ForIssuingFinesController.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── ForParkingCarsClient.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   ├── ForParkingCarsController.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   └── middleware.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   ├── mock</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   │   └── MockDataRepository.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   ├── ApiFactory.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   ├── BlueZoneAplication.main.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   ├── DirectCallApiFactory.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   └── HttpRestApiFactory.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── Configurator.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">test</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   ├── steps</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   ├── BuyTicketTestSteps.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   ├── CheckCarTestSteps.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   ├── Parser.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   │   └── TestStepsBase.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   ├── usecase.BuyTicketTest.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── usecase.CheckCarTest.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── .gitignore</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── LICENSE</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── Makefile</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── README.md</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── package-lock.json</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── package.json</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">└── tsconfig.json</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Fig 4: Folder Structure</p>
<p>Application logic-wise the project is small. Yet, it is already sizable to pose enough challenges for cognitive control over its structure. The current version attempts to strike a reasonable balance between multiple criteria:</p>
<ol>
<li>Maximal depth of file structure.</li>
<li>Complexity and amount of import statements.</li>
<li>The ratio between code that delivers intended value and code required to organize, test, and deliver it.</li>
</ol>
<p>While computing all sets of desirable metrics is beyond the scope of this publication, one back-of-envelope calculation could be performed here and now manually: the percentage of files under the <code>application</code> and <code>outside</code> folders, including intermediate folders (let’s call “value”) and the total number of files and folders (let’s call it “stuff”). In the current version, the numbers are:</p>
<p><strong>Total:</strong> 55</p>
<p><strong>src/application:</strong> 16</p>
<p><strong>src/:</strong>  41</p>
<p><strong>Files:</strong> 43</p>
<p><strong>Strict Value to Stuff Ratio:</strong> 16*100/55 = 29.09%</p>
<p><strong>Extended Value to Stuff Ratio:</strong> (15+19)*100/42 = 74.55%</p>
<p>Is it big or little? Good or Bad? It’s hard to say at the moment. The initial impression is that the numbers are healthy, yet coming up with more founded conclusions needs additional research and experimentation. A real production system will require a significantly larger number of tests.</p>
<p>From the cognitive load perspective, 43 files is a large number exceeding the famous 7 +/- 2 limit of human communication channels and short memory. It requires some organization. In the current version, the maximal number of files at one level is 8 - within the limit.</p>
<p>The presented hierarchical diagram only partially reflects the real graph picture - cross-file dependencies resulting from the <code>bring</code> statement are not visible. Also, the <code>__node_files__</code> folder reflecting external dependencies and having an impact on resulting package size is omitted as well.</p>
<p>In short, without additional investment in tooling and methodology of metrics, the picture is only partial.</p>
<p>We still can formulate some desirable direction: we prefer to deal as much as possible with assets generating the direct value and as little as possible with supporting stuff required to make it work. Ideally, a healthy Value to Stuff ratio would come from language and library support. Automatic code generation, including that performed by Generative AI, would reduce the typing but not the overall cognitive load.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="class-diagram">Class Diagram<a class="hash-link" aria-label="Direct link to Class Diagram" title="Direct link to Class Diagram" href="https://www.winglang.io/blog/2024/6/12/ported-to-cloud#class-diagram">​</a></h2>
<p>Depicting all “Blue Zone” application elements in a single UML Class Diagram would be impractical. Among other things, UML does not support directly separate representation of <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">preflight</a> and <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">inflight</a> elements. We can visualize separately the most important parts of the system. For example, here is a UML Class Diagram for the <code>application</code> part:</p>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:640/format:webp/1*cNjyYYT451PkmTSDqLBnew.png" class="img_ev3q">
<p>Fig 5: `src/application` Class Diagram</p>
</div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">DO NOT PUBLISH</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">@startuml</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">left to right direction</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">hide members</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">struct Ticket</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">struct Rate</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">struct BuyTicketRequest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">interface ForDrivingCars </span><span class="token operator">&lt;&lt;</span><span class="token plain">primary</span><span class="token operator">&gt;&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ForDrivingCars </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> BuyTicketRequest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ForDrivingCars </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> Ticket</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">interface ForStoringData</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ForStoringData </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> Rate</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ForStoringData </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> Ticket</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">struct PayRequest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">enum PaymentError</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">interface ForPaying</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ForPaying </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> PayRequest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ForPaying </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> PaymentError</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">interface ForObtainingDateTime</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">class BuyTicket </span><span class="token operator">&lt;&lt;</span><span class="token plain">function</span><span class="token operator">&gt;&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">class Veryfier</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Veryfier </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> BuyTicketRequest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">BuyTicket --</span><span class="token operator">&gt;</span><span class="token plain"> Veryfier</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">BuyTicket </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> BuyTicketRequest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">BuyTicket --</span><span class="token operator">&gt;</span><span class="token plain"> ForObtainingDateTime</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">BuyTicket --</span><span class="token operator">&gt;</span><span class="token plain"> ForStoringData</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">BuyTicket --</span><span class="token operator">&gt;</span><span class="token plain"> ForPaying</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">interface ForIssuingFines </span><span class="token operator">&lt;&lt;</span><span class="token plain">primary</span><span class="token operator">&gt;&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">struct CheckCarRequest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">struct CheckCarResponse</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ForIssuingFines </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> CheckCarRequest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ForIssuingFines </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> CheckCarResponse</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">class CheckCar </span><span class="token operator">&lt;&lt;</span><span class="token plain">function</span><span class="token operator">&gt;&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">CheckCar --</span><span class="token operator">&gt;</span><span class="token plain"> ForStoringData</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">CheckCar --</span><span class="token operator">&gt;</span><span class="token plain"> ForObtainingDateTime</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">CheckCar </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> CheckCarRequest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">CheckCar </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> CheckCarResponse</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">@enduml</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Notice that the <code>IForParkingCars</code> and <code>ForIssuingFines</code> primary interfaces are named differently from the <code>Car Driver</code> and <code>Parking Inspector</code> primary actors and <code>BuyTicket</code> and <code>CheckCar</code> use cases. This is not a mistake. <strong>Primary Port Interface</strong> names should reflect the <strong>Primary Actor</strong> role in a particular use case. There are no automatic rules for such a naming. Hopefully, the selected names are intuitive enough.</p>
<p>Notice also, that the <strong>Primary Interfaces</strong> are not directly implemented within the <code>application</code> module and there is a disconnect between these interfaces and use case implementations.</p>
<p>This is also not a mistake. The concrete connection between the <strong>Primary Interface</strong> and the corresponding use case implementation depends on configuration, as reflected in the UML Class Diagram Below:</p>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:640/format:webp/1*H21ofXTPkgZ0UwkcvZkrOQ.png" class="img_ev3q">
<p>Fig 6: Configurator Class Diagram (”Buy Ticket” Use Case only)</p>
</div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">DO NOT PUBLISH</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">@startuml</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">hide members</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">interface ForDrivingCars </span><span class="token operator">&lt;&lt;</span><span class="token plain">primary</span><span class="token operator">&gt;&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">interface ForStoringData</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">interface ForPaying</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">interface ForObtainingDateTime</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">class BuyTicket </span><span class="token operator">&lt;&lt;</span><span class="token plain">function</span><span class="token operator">&gt;&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">BuyTicket --</span><span class="token operator">&gt;</span><span class="token plain"> ForObtainingDateTime</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">BuyTicket --</span><span class="token operator">&gt;</span><span class="token plain"> ForStoringData</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">BuyTicket --</span><span class="token operator">&gt;</span><span class="token plain"> ForPaying</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">class ForDrivingCarsBackEnd implements ForDrivingCars</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ForDrivingCarsBackEnd --</span><span class="token operator">&gt;</span><span class="token plain"> BuyTicket</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">class ForDrivingCarsClient implements ForDrivingCars</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">class ForDrivingCarsController</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ForDrivingCarsController --</span><span class="token operator">&gt;</span><span class="token plain"> ForDrivingCars</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">class MockDataStore implements ForStoringData, ForPaying, ForObtainingDateTime</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">interface IBlueZoneApiFactory</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">class DirectCallApiFactory implements IBlueZoneApiFactory</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">DirectCallApiFactory </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> ForDrivingCarsBackEnd</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">class HttpRestApiFactory implements IBlueZoneApiFactory</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">class cloud.Api</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">cloud.Api --</span><span class="token operator">&gt;</span><span class="token plain"> ForDrivingCarsController</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">HttpRestApiFactory --</span><span class="token operator">&gt;</span><span class="token plain"> cloud.Api</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">HttpRestApiFactory </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> ForDrivingCarsController</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">HttpRestApiFactory </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> ForDrivingCarsClient</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">HttpRestApiFactory </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token operator">&gt;</span><span class="token plain"> ForDrivingCarsBackend</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">class Configurator</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Configurator --</span><span class="token operator">&gt;</span><span class="token plain"> IBlueZoneApiFactory</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Configurator --</span><span class="token operator">&gt;</span><span class="token plain"> MockDataStore</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">@enduml</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Only elements related to the “Buy Ticket” Use Case implementation and essential connections are depicted to avoid clutter.</p>
<p>According to the class diagram above the <code>Configurator</code> will decide which <code>IBlueZoneApiFactory</code> implementation to use: <code>DirectApiCallFactory</code> for local testing purposes or <code>HttpRestApiFactory</code> for both local and remote testing via HTTP and production deployment.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="cloud-resources">Cloud Resources<a class="hash-link" aria-label="Direct link to Cloud Resources" title="Direct link to Cloud Resources" href="https://www.winglang.io/blog/2024/6/12/ported-to-cloud#cloud-resources">​</a></h2>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:720/format:webp/1*byOcT_aqXWbPF35CqKqDYg.jpeg" class="img_ev3q">
<p>Fig 7: Cloud Resources</p>
</div>
<p>The cloud resources diagram presented above reflects the outcome of the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> compilation to the AWS target platform. It is quite different from the UML Class Diagram presented above and we have to conclude that various types of diagrams complement each other. The Cloud Resources diagram is important for understanding and controlling the system's operational aspects like cost, performance, reliability, resilience, and security.</p>
<p>The main challenge, as with previous diagrams, is the scale. With more cloud resources, the diagram will quickly be cluttered with too many details.</p>
<p>The current versions of all diagrams are more like useful illustrations than formal blueprints. Striking the right balance between accuracy and comprehension is a subject for future research. I addressed this issue in one of my <a href="https://medium.com/hackernoon/documenting-serverless-architectures-69bf63fc67b0" target="_blank" rel="noopener noreferrer">early publications</a>. Probably, it’s time to come back to this research topic.</p>
<h1>Conclusion</h1>
<p>The experience of porting the “<a href="https://github.com/HexArchBook/bluezone_pro/tree/main" target="_blank" rel="noopener noreferrer">Blue Zone</a>” application, featured in the recently published book “<a href="https://store7710079.company.site/Hexagonal-Architecture-Explained-p655931616" target="_blank" rel="noopener noreferrer">Hexagonal Architecture Explained</a>”, from <a href="https://www.java.com/en/" target="_blank" rel="noopener noreferrer">Java</a> to <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> led to the following interim conclusions</p>
<ol>
<li>Directly porting software applications to the cloud often results in inefficient and hard-to-maintain code.</li>
<li>Each programming language has its idiomatic way of expressing design decisions and blind translation from one to another does not work either.</li>
<li>Implementing the <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Architecture</a> pattern in the new cloud-oriented programming language <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> has proven to be a winning combination. This approach strikes the right balance between cost, performance, flexibility, and security.</li>
<li>Codebase size grows fast for even a modest functionality-wise speaking application. Keeping the complexity under control requires methodology and guidelines.</li>
<li>Graphical representations of the application logic and cloud resources are useful for illustration. Turning them into formal blueprints requires additional research.</li>
</ol>
<h1>Acknowledgments</h1>
<p>Throughout the preparation of this publication, I utilized several key tools to enhance the draft and ensure its quality.</p>
<p>The initial draft was crafted with the organizational capabilities of <a href="https://www.notion.so/" target="_blank" rel="noopener noreferrer">Notion</a>'s free subscription, facilitating the structuring and development of ideas.</p>
<p>For grammar and spelling review, the free version of <a href="https://app.grammarly.com/" target="_blank" rel="noopener noreferrer">Grammarly</a> proved useful for identifying and correcting basic errors, ensuring the readability of the text.</p>
<p>The enhancement of stylistic expression and the narrative coherence checks were performed using the paid version of <a href="https://openai.com/gpt-4" target="_blank" rel="noopener noreferrer">ChatGPT 4o</a>. The <a href="https://openai.com/gpt-4" target="_blank" rel="noopener noreferrer">ChatGPT 4o</a> tool was also used to develop critical portions of the <a href="https://www.winglang.io/docs/libraries#creating-a-wing-library" target="_blank" rel="noopener noreferrer">Trusted Wing Libraries</a>: <code>datetimex</code> and <code>struct</code> in TypeScript.</p>
<p>UML Class Diagrams were produced with the free version of the <a href="https://www.planttext.com/" target="_blank" rel="noopener noreferrer">PlantText UML</a> online tool.</p>
<p><a href="https://www.java.com/en/" target="_blank" rel="noopener noreferrer">Java</a> version of the “<a href="https://github.com/HexArchBook/bluezone_pro/tree/main" target="_blank" rel="noopener noreferrer">Blue Zone</a>” application was developed by <a href="https://jmgarridopaz.github.io/" target="_blank" rel="noopener noreferrer">Juan Manuel Garrido de Paz</a>, the book’s co-author. <a href="https://jmgarridopaz.github.io/" target="_blank" rel="noopener noreferrer">Juan Manuel Garrido de Paz</a> sadly passed away in April 2024. May his memory be blessed and this report serves as a tribute to him.</p>
<p>While all advanced tools and resources significantly contributed to the preparation process, the concepts, solutions, and final decisions presented in this article are entirely my own, for which I bear full responsibility.</p>]]></content:encoded>
            <author>asher.sterkin@gmail.com (Asher Sterkin)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>middleware</category>
            <category>platforms</category>
        </item>
        <item>
            <title><![CDATA[Build a QA Bot for your documentation with Langchain]]></title>
            <link>https://www.winglang.io/blog/2024/05/29/qa-bot-for-your-docs-with-langchain</link>
            <guid>https://www.winglang.io/blog/2024/05/29/qa-bot-for-your-docs-with-langchain</guid>
            <pubDate>Wed, 29 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[A ChatGPT client app built with Winglang and NextJS]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithStickyNavbar_LWe7" id="tldr">TL;DR<a class="hash-link" aria-label="Direct link to TL;DR" title="Direct link to TL;DR" href="https://www.winglang.io/blog/2024/05/29/qa-bot-for-your-docs-with-langchain#tldr">​</a></h2>
<p>In this tutorial, we will build an AI-powered Q&amp;A bot for your website documentation.</p>
<ul>
<li>
<p>🌐 Create a user-friendly Next.js app to accept questions and URLs</p>
</li>
<li>
<p>🔧 Set up a Wing backend to handle all the requests</p>
</li>
<li>
<p>💡 Incorporate Langchain for AI-driven answers by scraping and analyzing documentation using RAG</p>
</li>
<li>
<p>🔄 Complete the connection between the frontend input and AI-processed responses.</p>
</li>
</ul>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ykw5f2sos4fdhj8akowt.gif" class="img_ev3q">
</div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-wing">What is Wing?<a class="hash-link" aria-label="Direct link to What is Wing?" title="Direct link to What is Wing?" href="https://www.winglang.io/blog/2024/05/29/qa-bot-for-your-docs-with-langchain#what-is-wing">​</a></h2>
<p><a href="https://wing.cloud/redirect?utm_source=qa-bot-reddit&amp;redirect=https%3A%2F%2Fwww.winglang.io%2Fblog%2F2024%2F05%2F29%2Fqa-bot-for-your-docs-with-langchain" target="_blank" rel="noopener noreferrer">Wing</a> is an open-source framework for the cloud.</p>
<p>It allows you to create your application's infrastructure and code combined as a single unit and deploy them safely to your preferred cloud providers.</p>
<p>Wing gives you complete control over how your application's infrastructure is configured. In addition to its easy-to-learn <a href="https://www.winglang.io/docs/language-reference" target="_blank" rel="noopener noreferrer">programming language</a>, Wing also supports Typescript.</p>
<p>In this tutorial, we'll use TypeScript. So, don't worry—your JavaScript and React knowledge is more than enough to understand this tutorial.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u366v255drbwqmcoagrz.png" alt="Wing Landing Page" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="building-the-frontend-with-nextjs">Building the frontend with Next.js<a class="hash-link" aria-label="Direct link to Building the frontend with Next.js" title="Direct link to Building the frontend with Next.js" href="https://www.winglang.io/blog/2024/05/29/qa-bot-for-your-docs-with-langchain#building-the-frontend-with-nextjs">​</a></h2>
<p>Here, you’ll create a simple form that accepts the documentation URL and the user’s question and then returns a response based on the data available on the website.</p>
<p>First, create a folder containing two sub-folders - <code>frontend</code> and <code>backend</code>.&nbsp;The <code>frontend</code> folder contains the Next.js app, and the <code>backend</code> folder is for Wing.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">mkdir</span><span class="token plain"> qa-bot </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> qa-bot</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">mkdir</span><span class="token plain"> frontend backend</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Within the <strong><code>frontend</code></strong> folder, create a Next.js project by running the following code snippet:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> frontend</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">npx create-next-app ./</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pyq8dnmmmplvzl7g41ir.png" alt="Next App" class="img_ev3q"></p>
<p>Copy the code snippet below into the <code>app/page.tsx</code> file to create the form that accepts the user’s question and the documentation URL:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token string" style="color:rgb(255, 121, 198)">"use client"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> useState </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"react"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">default</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">Home</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">documentationURL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> setDocumentationURL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:rgb(80, 250, 123)">useState</span><span class="token generic-function generic class-name operator">&lt;</span><span class="token generic-function generic class-name builtin" style="color:rgb(189, 147, 249)">string</span><span class="token generic-function generic class-name operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">question</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> setQuestion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:rgb(80, 250, 123)">useState</span><span class="token generic-function generic class-name operator">&lt;</span><span class="token generic-function generic class-name builtin" style="color:rgb(189, 147, 249)">string</span><span class="token generic-function generic class-name operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">disable</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> setDisable</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:rgb(80, 250, 123)">useState</span><span class="token generic-function generic class-name operator">&lt;</span><span class="token generic-function generic class-name builtin" style="color:rgb(189, 147, 249)">boolean</span><span class="token generic-function generic class-name operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> setResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:rgb(80, 250, 123)">useState</span><span class="token generic-function generic class-name operator">&lt;</span><span class="token generic-function generic class-name builtin" style="color:rgb(189, 147, 249)">string</span><span class="token generic-function generic class-name"> </span><span class="token generic-function generic class-name operator">|</span><span class="token generic-function generic class-name"> </span><span class="token generic-function generic class-name keyword" style="color:rgb(189, 147, 249);font-style:italic">null</span><span class="token generic-function generic class-name operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">null</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(80, 250, 123)">handleUserQuery</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">e</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">React</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">FormEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">preventDefault</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token function" style="color:rgb(80, 250, 123)">setDisable</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token console class-name">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> question</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> documentationURL </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">main</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">w-full md:px-8 px-3 py-8</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">h2</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">font-bold text-2xl mb-8 text-center text-blue-600</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">				Documentation Bot with Wing &amp; LangChain</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">h2</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">form</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">onSubmit</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">handleUserQuery</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">mb-8</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">label</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">block mb-2 text-sm text-gray-500</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text">Webpage URL</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">label</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">input</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">type</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">url</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">w-full mb-4 p-4 rounded-md border text-sm border-gray-300</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">placeholder</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">https://www.winglang.io/docs/concepts/why-wing</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">required</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">value</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">documentationURL</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">onChange</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">e</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript arrow operator" style="color:rgb(255, 121, 198)">=&gt;</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript function" style="color:rgb(80, 250, 123)">setDocumentationURL</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">e</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">target</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">value</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">				</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">label</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">block mb-2 text-sm text-gray-500</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">					Ask any questions related to the page URL above</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">label</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">textarea</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">rows</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript number" style="color:rgb(255, 121, 198)">5</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">w-full mb-4 p-4 text-sm rounded-md border border-gray-300</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">placeholder</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">What is Winglang? OR Why should I use Winglang? OR How does Winglang work?</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">required</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">value</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">question</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">onChange</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">e</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript arrow operator" style="color:rgb(255, 121, 198)">=&gt;</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript function" style="color:rgb(80, 250, 123)">setQuestion</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">e</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">target</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">value</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">				</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">button</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">type</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">submit</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">disabled</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">disable</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">					</span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">bg-blue-500 text-white px-8 py-3 rounded</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">				</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">					</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">disable </span><span class="token operator">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Loading..."</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Ask Question"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">button</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">form</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">response </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">bg-gray-100 w-full p-8 rounded-sm shadow-md</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">					</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">p</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">text-gray-600</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">p</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">		</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">main</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The code snippet above displays a form that accepts the user’s question and the documentation URL, and logs them to the console for now.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7b4w3tq0srua93gnk73n.png" alt="QA bot form" class="img_ev3q"></p>
<p>Perfect! 🎉You’ve completed the application's user interface. Next, let’s set up the Wing backend.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-to-set-up-wing-on-your-computer">How to set up Wing on your computer<a class="hash-link" aria-label="Direct link to How to set up Wing on your computer" title="Direct link to How to set up Wing on your computer" href="https://www.winglang.io/blog/2024/05/29/qa-bot-for-your-docs-with-langchain#how-to-set-up-wing-on-your-computer">​</a></h2>
<p>Wing provides a CLI that enables you to perform various actions within your projects.</p>
<p>It also provides&nbsp;<a href="https://marketplace.visualstudio.com/items?itemName=Monada.vscode-wing" target="_blank" rel="noopener noreferrer">VSCode</a>&nbsp;and&nbsp;<a href="https://plugins.jetbrains.com/plugin/22353-wing" target="_blank" rel="noopener noreferrer">IntelliJ</a>&nbsp;extensions that enhance the developer experience with features like syntax highlighting, compiler diagnostics, code completion and snippets, and many others.</p>
<p>Before we proceed, stop your Next.js development server for now and install the Winglang CLI by running the code snippet below in your terminal.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"> -g winglang@latest</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Run the following code snippet to ensure that the Winglang CLI is installed and working as expected:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing --version</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Next, navigate to the <code>backend</code> folder and create an empty Wing Typescript project. Ensure you select the <code>empty</code> template and Typescript as the language.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing new</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ezy04zqvz9lura0d25dj.png" alt="Wing New" class="img_ev3q"></p>
<p>Copy the code snippet below into the <code>backend/main.ts</code> file.</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> cloud</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> inflight</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> lift</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> main </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@wingcloud/framework"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">root</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> fn </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		root</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token string" style="color:rgb(255, 121, 198)">"Function"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"hello, world"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <strong><code>main()</code></strong> function serves as the entry point to Wing.</p>
<p>It creates a cloud function and executes at compile time. The <strong><code>inflight</code></strong> function, on the other hand, runs at runtime and returns a <code>Hello, world!</code> text.</p>
<p>Start the Wing development server by running the code snippet below. It automatically opens the Wing Console in your browser at <code>http://localhost:3000</code>.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing it</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z1ejobkm0dq5akhut732.png" alt="Wing TS minimul console" class="img_ev3q"></p>
<p>You've successfully installed Wing on your computer.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-to-connect-wing-to-a-nextjs-app">How to connect Wing to a Next.js app<a class="hash-link" aria-label="Direct link to How to connect Wing to a Next.js app" title="Direct link to How to connect Wing to a Next.js app" href="https://www.winglang.io/blog/2024/05/29/qa-bot-for-your-docs-with-langchain#how-to-connect-wing-to-a-nextjs-app">​</a></h2>
<p>From the previous sections, you've created the Next.js frontend app within the <code>frontend</code> folder and the Wing backend within the <code>backend</code> folder.</p>
<p>In this section, you'll learn how to communicate and send data back and forth between the Next.js app and the Winglang backend.</p>
<p>First, install the&nbsp;<a href="https://github.com/winglang/winglibs/tree/main/react" target="_blank" rel="noopener noreferrer">Winglang React</a>&nbsp;library within the backend folder by running the code below:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"> @winglibs/react</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Next, update the <code>main.ts</code> file as shown below:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> main</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> cloud</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> inflight</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> lift </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@wingcloud/framework"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">React</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@winglibs/react"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">root</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> api </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">root</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"api"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> cors</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 create an API route</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token string" style="color:rgb(255, 121, 198)">"/test"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hello world"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token comment" style="color:rgb(98, 114, 164)">//👉🏻 placeholder for the POST request endpoint</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 connects to the Next.js project</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> react </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">React</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">App</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">root</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"react"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> projectPath</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"../frontend"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 an environment variable</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	react</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">addEnvironment</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"api_url"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The code snippet above creates an API endpoint (<code>/test</code>) that accepts GET requests and returns a <code>Hello world</code> text. The <code>main</code> function also connects to the Next.js project and adds the <code>api_url</code> as an environment variable.</p>
<p>The API URL contained in the environment variable enables us to send requests to the Wing API route. Now, how do we retrieve the API URL within the Next.js app and make these requests?</p>
<p>Update the <code>RootLayout</code> component within the Next.js <code>app/layout.tsx</code> file as done below:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">default</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">RootLayout</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	children</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Readonly</span><span class="token operator">&lt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	children</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">React</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ReactNode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">html</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">lang</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">en</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">head</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">				</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token comment" style="color:rgb(98, 114, 164)">/** ---👇🏻  Adds this script tag 👇🏻 ---*/</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">				</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">script</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">src</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">./wing.js</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">defer</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">head</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">			</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">body</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">inter</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">className</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">children</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">body</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">		</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">html</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Re-build the Next.js project by running <code>npm run build</code>.</p>
<p>Finally, start the Wing development server. It automatically starts the Next.js server, which can be accessed at <strong><code>http://localhost:3001</code></strong> in your browser.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t7rkxw9bds97a0qzg5vh.gif" alt="Console-to-URL" class="img_ev3q"></p>
<p>You've successfully connected the Next.js to Wing. You can also access data within the environment variables using <code>window.wingEnv.&lt;attribute_name&gt;</code>.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0up5430jmxufmyeb9e4h.gif" alt="window.wingEnv" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="processing-users-requests-with-langchain-and-wing">Processing user's requests with LangChain and Wing<a class="hash-link" aria-label="Direct link to Processing user's requests with LangChain and Wing" title="Direct link to Processing user's requests with LangChain and Wing" href="https://www.winglang.io/blog/2024/05/29/qa-bot-for-your-docs-with-langchain#processing-users-requests-with-langchain-and-wing">​</a></h2>
<p>In this section, you'll learn how to send requests to Wing, process these requests with <a href="https://js.langchain.com/docs/get_started/quickstart#llm-chain" target="_blank" rel="noopener noreferrer">LangChain and OpenA</a>I, and display the results on the Next.js frontend.</p>
<p>First, let's update the Next.js <strong><code>app/page.tsx</code></strong> file to retrieve the API URL and send user's data to a Wing API endpoint.</p>
<p>To do this, extend the JavaScript <strong><code>window</code></strong> object by adding the following code snippet at the top of the <strong><code>page.tsx</code></strong> file.</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token string" style="color:rgb(255, 121, 198)">"use client"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> useState </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"react"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">interface</span><span class="token plain"> </span><span class="token class-name">WingEnv</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	api_url</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">declare</span><span class="token plain"> global </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">interface</span><span class="token plain"> </span><span class="token class-name">Window</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		wingEnv</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">WingEnv</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Next, update the <code>handleUserQuery</code> function to send a POST request containing the user's question and website's URL to a Wing API endpoint.</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 sends data to the api url</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> setResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token generic-function function" style="color:rgb(80, 250, 123)">useState</span><span class="token generic-function generic class-name operator">&lt;</span><span class="token generic-function generic class-name builtin" style="color:rgb(189, 147, 249)">string</span><span class="token generic-function generic class-name"> </span><span class="token generic-function generic class-name operator">|</span><span class="token generic-function generic class-name"> </span><span class="token generic-function generic class-name keyword" style="color:rgb(189, 147, 249);font-style:italic">null</span><span class="token generic-function generic class-name operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">null</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(80, 250, 123)">handleUserQuery</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">e</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">React</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">FormEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">preventDefault</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token function" style="color:rgb(80, 250, 123)">setDisable</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> request </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">fetch</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">window</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">wingEnv</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">api_url</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">/api</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				method</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"POST"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">					</span><span class="token string-property property">"Content-Type"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"application/json"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">JSON</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> question</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> pageURL</span><span class="token operator">:</span><span class="token plain"> documentationURL </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token function" style="color:rgb(80, 250, 123)">setResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token function" style="color:rgb(80, 250, 123)">setDisable</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token console class-name">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token function" style="color:rgb(80, 250, 123)">setDisable</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Before you create the Wing endpoint that accepts the POST request, install the following packages within the <code>backend</code> folder:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">npm install </span><span class="token decorator at operator">@</span><span class="token decorator function" style="color:rgb(80, 250, 123)">langchain</span><span class="token operator">/</span><span class="token plain">community </span><span class="token decorator at operator">@</span><span class="token decorator function" style="color:rgb(80, 250, 123)">langchain</span><span class="token operator">/</span><span class="token plain">openai langchain cheerio</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><a href="https://js.langchain.com/v0.2/docs/integrations/document_loaders/web_loaders/web_cheerio/" target="_blank" rel="noopener noreferrer">Cheerio</a> enables us to scrape the software documentation webpage, while the <a href="https://js.langchain.com/v0.1/docs/get_started/quickstart/" target="_blank" rel="noopener noreferrer">LangChain packages</a> allow us to access its various functionalities.</p>
<p>The LangChain OpenAI integration package uses the OpenAI language model; therefore, you'll need a valid API key. You can get yours from the&nbsp;<a href="https://platform.openai.com/api-keys" target="_blank" rel="noopener noreferrer">OpenAI Developer's Platform</a>.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/omg4o524oklrssso5rqc.png" alt="Langchain" class="img_ev3q"></p>
<p>Next, let’s create the <code>/api</code> endpoint that handle incoming requests.</p>
<p>The endpoint will:</p>
<ul>
<li>accept the questions and documentation URLs from the Next.js application,</li>
<li>load the documentation page using <a href="https://js.langchain.com/v0.1/docs/modules/data_connection/document_loaders/" target="_blank" rel="noopener noreferrer">LangChain document loaders</a>,</li>
<li>split the retrieved documents into chunks,</li>
<li>transform the chunked documents and save them within a <a href="https://js.langchain.com/v0.1/docs/modules/data_connection/vectorstores/" target="_blank" rel="noopener noreferrer">LangChain vector store</a>,</li>
<li>and create a <a href="https://js.langchain.com/v0.1/docs/modules/data_connection/" target="_blank" rel="noopener noreferrer">retriever function</a> that retrieves the documents from the vector store.</li>
</ul>
<p>First, import the following into the <code>main.ts</code> file:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> main</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> cloud</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> inflight</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> lift </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@wingcloud/framework"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">ChatOpenAI</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> </span><span class="token imports maybe-class-name">OpenAIEmbeddings</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@langchain/openai"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">ChatPromptTemplate</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@langchain/core/prompts"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> createStuffDocumentsChain </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"langchain/chains/combine_documents"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">CheerioWebBaseLoader</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@langchain/community/document_loaders/web/cheerio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">RecursiveCharacterTextSplitter</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"langchain/text_splitter"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">MemoryVectorStore</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"langchain/vectorstores/memory"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> createRetrievalChain </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"langchain/chains/retrieval"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">React</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@winglibs/react"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Add the code snippet below within the <code>main()</code> function to create the <code>/api</code> endpoint:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">	api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">post</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token string" style="color:rgb(255, 121, 198)">"/api"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">ctx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 accept user inputs from Next.js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> question</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> pageURL </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token known-class-name class-name">JSON</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 initialize OpenAI Chat for LLM interactions</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> chatModel </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ChatOpenAI</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				apiKey</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"&lt;YOUR_OPENAI_API_KEY&gt;"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				model</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"gpt-3.5-turbo-1106"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 initialize OpenAI Embeddings for Vector Store data transformation</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> embeddings </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">OpenAIEmbeddings</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				apiKey</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"&lt;YOUR_OPENAI_API_KEY&gt;"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 creates a text splitter function that splits the OpenAI result chunk size</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> splitter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">RecursiveCharacterTextSplitter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				chunkSize</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">//👉🏻 characters per chunk</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				chunkOverlap</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">20</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 creates a document loader, loads, and scraps the page</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> loader </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">CheerioWebBaseLoader</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">pageURL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> docs </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> loader</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">load</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 splits the document into chunks </span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> splitDocs </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> splitter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">splitDocuments</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">docs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 creates a Vector store containing the split documents</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> vectorStore </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token maybe-class-name">MemoryVectorStore</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromDocuments</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				splitDocs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				embeddings </span><span class="token comment" style="color:rgb(98, 114, 164)">//👉🏻 transforms the data to the Vector Store format</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 creates a document retriever that retrieves results that answers the user's questions</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> retriever </span><span class="token operator">=</span><span class="token plain"> vectorStore</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">asRetriever</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				k</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">//👉🏻  number of documents to retrieve (default is 2)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 creates a prompt template for the request</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> prompt </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">ChatPromptTemplate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromTemplate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">				Answer this question.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">				Context: {context}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">				Question: {input}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">				</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 creates a chain containing the OpenAI chatModel and prompt</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> chain </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">createStuffDocumentsChain</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				llm</span><span class="token operator">:</span><span class="token plain"> chatModel</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				prompt</span><span class="token operator">:</span><span class="token plain"> prompt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 creates a retrieval chain that combines the documents and the retriever function</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> retrievalChain </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">createRetrievalChain</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				combineDocsChain</span><span class="token operator">:</span><span class="token plain"> chain</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				retriever</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 invokes the retrieval Chain and returns the user's answer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> retrievalChain</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				input</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">question</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">					status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">					body</span><span class="token operator">:</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">answer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">undefined</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The API endpoint accepts the user’s question and the page URL from the Next.js application, initialises <a href="https://js.langchain.com/v0.2/docs/integrations/chat/openai/" target="_blank" rel="noopener noreferrer"><code>ChatOpenAI</code></a> and <a href="https://js.langchain.com/v0.2/docs/integrations/text_embedding/openai/" target="_blank" rel="noopener noreferrer"><code>OpenAIEmbeddings</code></a>, loads the documentation page, and retrieves the answers to the user’s query in the form of documents.</p>
<p>Then, splits the documents into chunks, saves the chunks in the <code>MemoryVectorStore</code>, and enables us to fetch answers to the question using <a href="https://js.langchain.com/v0.1/docs/modules/data_connection/" target="_blank" rel="noopener noreferrer">LangChain retrievers</a>.</p>
<p>From the code snippet above, the OpenAI API key is entered directly into the code; this could lead to security breaches, making the API key accessible to attackers. To prevent this data leak, Winglang allows you to save private keys and credentials in variables called <code>secrets</code>.</p>
<p>When you create a secret, Wing saves this data in a <code>.env</code> file, ensuring it is secured and accessible.</p>
<p>Update the <code>main()</code> function to fetch the OpenAI API key from the Wing Secret.</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">root</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> api </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">root</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"api"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> cors</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token comment" style="color:rgb(98, 114, 164)">//👇🏻 creates the secret variable</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> secret </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Secret</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">root</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"OpenAPISecret"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"open-ai-key"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">post</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token string" style="color:rgb(255, 121, 198)">"/api"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token function" style="color:rgb(80, 250, 123)">lift</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> secret </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">grant</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> secret</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"value"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">ctx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> apiKey </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> ctx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">secret</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> chatModel </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ChatOpenAI</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">					apiKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">					model</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"gpt-3.5-turbo-1106"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> embeddings </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">OpenAIEmbeddings</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">					apiKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				</span><span class="token comment" style="color:rgb(98, 114, 164)">//👉🏻 other code snippets &amp; configurations</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> react </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">React</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">App</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">root</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"react"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> projectPath</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"../frontend"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	react</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">addEnvironment</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"api_url"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ul>
<li>From the code snippet above,
<ul>
<li>The <code>secret</code> variable declares a name for the secret (OpenAI API key).</li>
<li>The <a href="https://www.winglang.io/docs/typescript/inflights#permissions" target="_blank" rel="noopener noreferrer"><code>lift().grant()</code></a> grants the API endpoint access to the secret value stored in the Wing Secret.</li>
<li>The <a href="https://www.winglang.io/docs/typescript/inflights" target="_blank" rel="noopener noreferrer"><code>inflight()</code></a> function accepts the context and request object as parameters, makes a request to LangChain, and returns the result.</li>
<li>Then, you can access the <code>apiKey</code> using the <code>ctx.secret.value()</code> function.</li>
</ul>
</li>
</ul>
<p>Finally, save the OpenAI API key as a secret by running this command in your terminal.</p>
<p><img decoding="async" loading="lazy" alt="Wing Secrets" src="https://www.winglang.io/assets/images/qa-bot-wing-secrets-883db5e81515894ae280d77b7f72bb25.gif" width="3292" height="720" class="img_ev3q"></p>
<p>Great, now our secrets are stored and we can interact with our application. Let's take a look at it in action!</p>
<p>Here is a brief demo:</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ropklqge2xzpibl29vye.gif" alt="QA bot demo 1" class="img_ev3q"></p>
<hr>
<p>Let's dig a little bit deeper into the Winglang docs to see what data our AI bot can extract.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hnmf6n6mszc6go0uiw1v.gif" alt="QA bot demo 2" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="wrapping-it-up">Wrapping It Up<a class="hash-link" aria-label="Direct link to Wrapping It Up" title="Direct link to Wrapping It Up" href="https://www.winglang.io/blog/2024/05/29/qa-bot-for-your-docs-with-langchain#wrapping-it-up">​</a></h2>
<p>So far, we have gone over the following:</p>
<ul>
<li>What is Wing?</li>
<li>How to use Wing and query data using Langchain,</li>
<li>How to connect Wing to a Next.js application,</li>
<li>How to send data between a Next.js frontend and a Wing backend.</li>
</ul>
<blockquote>
<p><a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> aims to bring back your creative flow and close the gap between imagination and creation. Another great advantage of Wing is that it is open-source. Therefore, if you are looking forward to building distributed systems that leverage cloud services or contribute to the future of cloud development, <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a> is your best choice.</p>
</blockquote>
<p>Feel free to&nbsp;contribute&nbsp;to the&nbsp;<a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">GitHub&nbsp;repository,</a>&nbsp;and&nbsp;<a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">share your thoughts</a>&nbsp;with the team and the large community of developrs.</p>
<p>The source code for this tutorial is available <a href="https://github.com/NathanTarbert/wing-langchain-nextjs" target="_blank" rel="noopener noreferrer">here</a>.</p>
<p>Thank you for reading! 🎉</p>]]></content:encoded>
            <author>nathant@wing.cloud (Nathan Tarbert)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>winglang</category>
            <category>platforms</category>
        </item>
        <item>
            <title><![CDATA[Building Slack Apps with Wing]]></title>
            <link>https://www.winglang.io/blog/2024/05/25/bring-slack</link>
            <guid>https://www.winglang.io/blog/2024/05/25/bring-slack</guid>
            <pubDate>Sat, 25 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[How to build Slack apps with Wing]]></description>
            <content:encoded><![CDATA[<p>Building Slack apps can be a daunting task for beginners. Between understanding the Slack API, setting up a server to handle incoming requests, and deploying the app to a cloud provider, there are many steps involved. For instance setting up a slack app locally on your machine is simple enough, but then deploying it to a cloud provider can be challenging and might require re-architecting your app.</p>
<p>In this tutorial, I'm going to show you how to build a Slack app using Wing, making use of the Wing Console for local simulation and then deploying it to AWS with a single command!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="a-quick-introduction-to-wing">A Quick Introduction to Wing<a class="hash-link" aria-label="Direct link to A Quick Introduction to Wing" title="Direct link to A Quick Introduction to Wing" href="https://www.winglang.io/blog/2024/05/25/bring-slack#a-quick-introduction-to-wing">​</a></h2>
<p>Wing is an open source programming language for the cloud, that also provides a powerful and fun local development experience.</p>
<p>Wing combines infrastructure and runtime code in one language, enabling developers to stay in their creative flow, and to deliver better software, faster and more securely.</p>
<p>To take a closer look at Wing checkout our <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Github repository</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="lets-get-started">Let's Get Started<a class="hash-link" aria-label="Direct link to Let's Get Started" title="Direct link to Let's Get Started" href="https://www.winglang.io/blog/2024/05/25/bring-slack#lets-get-started">​</a></h2>
<p>First, you need to install Wing on your machine (you'll need Node.js &gt;= 20.x installed):</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> i -g winglang</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You can check the CLI version like this (the minimum version required by this tutorial is 0.75.0):</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing --version</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token number">0.75</span><span class="token plain">.0</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Ok, now that we have the Wing CLI installed we can use the Slack quick-start template to start building our Slack app.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">$ </span><span class="token function" style="color:rgb(80, 250, 123)">mkdir</span><span class="token plain"> my-slack-app</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">$ </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> my-slack-app</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">$ wing new slack</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This will create the following project structure:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">my-slack-app/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── main.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── package-lock.json</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">└── package.json</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Let's take a look at the <code>main.w</code> file, where we can see a code template for a simple Slack app that updates us on files uploaded to a bucket.</p>
<blockquote>
<p>Note: your template will have more comments and explanations than the one below. I have removed them for brevity.</p>
</blockquote>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring slack</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> botToken </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Secret</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"slack-bot-token"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> slackBot </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">slack</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">App</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">token</span><span class="token operator">:</span><span class="token plain"> botToken</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> inbox </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"file-process-inbox"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">inbox</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">onCreate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> channel </span><span class="token operator">=</span><span class="token plain"> slackBot</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">channel</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"INBOX_PROCESSING_CHANNEL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  channel</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">post</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"New file: {key} was just uploaded to inbox!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">slackBot</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">onEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"app_mention"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">ctx</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> eventText </span><span class="token operator">=</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"event"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"text"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">asStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">eventText</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> eventText</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">contains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"list inbox"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> files </span><span class="token operator">=</span><span class="token plain"> inbox</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">list</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> message </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">slack</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">addSection</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">fields</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token literal-property property">type</span><span class="token operator">:</span><span class="token plain"> slack</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">FieldType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">mrkdwn</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token literal-property property">text</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"*Current Inbox:*\n-{files.join("</span><span class="token plain">\n</span><span class="token operator">-</span><span class="token string" style="color:rgb(255, 121, 198)">")}"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    ctx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">channel</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">postMessage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>Note: Be sure to replace the <code>INBOX_PROCESSING_CHANNEL</code> with the name of the slack channel you want to post to.</p>
</blockquote>
<p>We can see above the very first resource defined is a <code>cloud.Secret</code> which is used to store the Slack bot token. This is a secure way to store sensitive information in Wing. So before we can get started we need to create a Slack app and get the bot token to use in our Wing app.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="creating-a-slack-app">Creating a Slack App<a class="hash-link" aria-label="Direct link to Creating a Slack App" title="Direct link to Creating a Slack App" href="https://www.winglang.io/blog/2024/05/25/bring-slack#creating-a-slack-app">​</a></h2>
<ol>
<li>Head over to the <a href="https://api.slack.com/apps" target="_blank" rel="noopener noreferrer">Slack API Dashboard</a> and create a new app.</li>
<li>Select <code>Create from Scratch</code> and give your app a name and select the workspace you want to deploy it to.
<img decoding="async" loading="lazy" alt="Creating from scratch" src="https://www.winglang.io/assets/images/from-scratch-87634da3be35cac52b7bb9803a9ddc76.png" width="1082" height="1032" class="img_ev3q"></li>
<li>For the sake of our tutorial, we will be building a bot that requires the following permissions:</li>
</ol>
<ul>
<li><code>app_mentions:read</code></li>
<li><code>chat:write</code></li>
<li><code>chat:write.public</code>
to add these head over to the <code>OAuth &amp; Permissions</code> section and add those permissions.
<img decoding="async" loading="lazy" alt="Adding permissions" src="https://www.winglang.io/assets/images/permissions-6565af95000359b9b741301d967cb331.png" width="1020" height="1414" class="img_ev3q"></li>
</ul>
<ol start="4">
<li>Install the app to your workspace and copy the bot token.
<img decoding="async" loading="lazy" alt="Install app" src="https://www.winglang.io/assets/images/install-to-workspace-e548803edde16d80512ed377a8aeed0a.png" width="1000" height="1240" class="img_ev3q"></li>
</ol>
<p>Once its installed you can copy the bot token and let's head back over to our Wing app.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="configuring-slack-bot-token-secret">Configuring Slack Bot Token Secret<a class="hash-link" aria-label="Direct link to Configuring Slack Bot Token Secret" title="Direct link to Configuring Slack Bot Token Secret" href="https://www.winglang.io/blog/2024/05/25/bring-slack#configuring-slack-bot-token-secret">​</a></h2>
<p>Now that we have our bot token, we can add it to our application by running the <code>wing secrets</code> command and pasting the token when prompted:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">❯ wing secrets</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token number">1</span><span class="token plain"> secret</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> found</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">? Enter the secret value </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> slack-bot-token: </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">hidden</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now that our bot token is stored our application is ready to run!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="running-the-app-locally">Running the App Locally<a class="hash-link" aria-label="Direct link to Running the App Locally" title="Direct link to Running the App Locally" href="https://www.winglang.io/blog/2024/05/25/bring-slack#running-the-app-locally">​</a></h2>
<p>To run the app locally we can use the Wing Console, which simulates the cloud environment on your local machine. To start the console run:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing it</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This will open a browser window showing the Wing Console. You should see something similar to this:</p>
<p><img decoding="async" loading="lazy" alt="Wing Console" src="https://www.winglang.io/assets/images/wing-console-c910d4e405ce223c021ab7e9fa344683.png" width="3448" height="1234" class="img_ev3q"></p>
<p>Now in order to see the Slack bot in action, let's add some more code to our <code>main.w</code> file. We will add a function that will make a new file each time it is called.</p>
<p>The following code can be appended to the <code>main.w</code> file:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> counter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> i </span><span class="token operator">=</span><span class="token plain"> counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">inc</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  inbox</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">put</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"file-{i}.txt"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Slack!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Add File"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Once you save the file, the Wing Console will hot reload and you should now see a function resource we can play with that looks like this:</p>
<p><img decoding="async" loading="lazy" alt="Add File Function" src="https://www.winglang.io/assets/images/add-file-function-ec8bfd2cd57f7565b993ce00cd108860.png" width="700" height="750" class="img_ev3q"></p>
<p>So now we can click on the <code>Add File</code> function and interact with it in the right side panel. Go ahead and invoke the function a few times.</p>
<p><img decoding="async" loading="lazy" alt="Invoke Function" src="https://www.winglang.io/assets/images/invoke-function-a8ac74dcea2a8ae64767939ff8b0e234.png" width="2832" height="1230" class="img_ev3q"></p>
<p>And BAM!! You should now be seeing messages in your Slack channel every time you invoke the function!</p>
<p><img decoding="async" loading="lazy" alt="Slack Messages" src="https://www.winglang.io/assets/images/slack-messages-1f7911e817fa201f0e8f4eea856e55e6.png" width="1686" height="698" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="enabling-events">Enabling Events<a class="hash-link" aria-label="Direct link to Enabling Events" title="Direct link to Enabling Events" href="https://www.winglang.io/blog/2024/05/25/bring-slack#enabling-events">​</a></h2>
<p>One thing we will notice is the Slack application is supposed to support the ability to list the files in the inbox. This is done by mentioning the Slack app and saying <code>list inbox</code>.</p>
<p>If you try this now you will see absolutely nothing happens :) —— this is because we need to enable events in our slack app.</p>
<p>To do this head over to the <code>Event Subscriptions</code> section in the Slack API dashboard and enable events. You will need to provide a URL for the Slack API to send events to. Luckily Wing makes providing this URL easy with builtin support for tunneling.</p>
<p>To get the tunnel URL go back to the Wing Console and <code>Open a tunnel for this endpoint</code></p>
<p><img decoding="async" loading="lazy" alt="Open Tunnel" src="https://www.winglang.io/assets/images/open-tunnel-a7a220bae6d3d4ee461d0b902dc71938.png" width="1214" height="942" class="img_ev3q"></p>
<p>After a moment the icon will change to a eye with a slash through it, now we can copy the url by right clicking the endpoint and selecting <code>Copy URL</code>.</p>
<p>Next let's head over to the <code>Event Subscriptions</code> section in the slack API dashboard and paste the URL in the <code>Request URL</code> field. However, we need to append <code>slack/events</code> to the end of the URL. So it should look something like this:</p>
<p><img decoding="async" loading="lazy" alt="Request URL" src="https://www.winglang.io/assets/images/events-sub-url-f1c497b4898ed50d51ca5280273e6734.png" width="1386" height="1086" class="img_ev3q"></p>
<p>This should only take a few seconds to verify, and once its verified you can scroll down to the <code>Subscribe to Bot Events</code> section and add the <code>app_mention</code> event like so:</p>
<p><img decoding="async" loading="lazy" alt="Subscribe to Bot Events" src="https://www.winglang.io/assets/images/event-subscription-3b91e596481c751d8872b2fa4a25aa27.png" width="1348" height="674" class="img_ev3q"></p>
<p>Lastly, don't forget to save your changes!</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="testing-the-event-subscription">Testing the event subscription<a class="hash-link" aria-label="Direct link to Testing the event subscription" title="Direct link to Testing the event subscription" href="https://www.winglang.io/blog/2024/05/25/bring-slack#testing-the-event-subscription">​</a></h3>
<p>Now head back to your Slack channel where you received the messages earlier and mention your app and say <code>list inbox</code>. Our Slack apps may have different names so it wont be exactly the same as the example below:</p>
<p><img decoding="async" loading="lazy" alt="List Inbox" src="https://www.winglang.io/assets/images/list-inbox-12dff7da87f4e9d0f6b9e6c0b7463862.png" width="1070" height="726" class="img_ev3q"></p>
<p>You should now see a message in the channel with the files in the inbox!</p>
<p>Awesome! You have now built a Slack app using Wing and tested it locally. Now let's deploy it to AWS!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="deploying-to-aws">Deploying to AWS<a class="hash-link" aria-label="Direct link to Deploying to AWS" title="Direct link to Deploying to AWS" href="https://www.winglang.io/blog/2024/05/25/bring-slack#deploying-to-aws">​</a></h2>
<p>Before we start you will need the following to follow along:</p>
<ol>
<li>An AWS Account</li>
<li>AWS CLI installed and configured with the necessary permissions.</li>
<li>Terraform installed</li>
</ol>
<p>Getting our code ready for AWS is as simple as running 2 commands. The first thing we need to do is prepare the <code>cloud.Secret</code> for the <code>tf-aws</code> platform. This is done by running the <code>wing secrets</code> command with the <code>--platform</code> flag:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">❯ wing secrets --platform tf-aws             </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token number">1</span><span class="token plain"> secret</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> found</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">? Enter the secret value </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> slack-bot-token: </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">hidden</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Storing secrets </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> AWS Secrets Manager</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Secret slack-bot-token does not exist, creating it.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token number">1</span><span class="token plain"> secret</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> stored AWS Secrets Manager</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This will result in the same prompt as before, but this time the secret will be stored in AWS Secrets Manager.</p>
<p>Next let's compile the application for <code>tf-aws</code>:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">❯ wing compile --platform tf-aws</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This will compile the application and generate all the necessary Terraform files, and assets needed to deploy the application to AWS.</p>
<p>To deploy the code run the following commands:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">terraform -chdir</span><span class="token operator">=</span><span class="token plain">./target/main.tfaws init</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">terraform -chdir</span><span class="token operator">=</span><span class="token plain">./target/main.tfaws apply -auto-approve</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This will begin the deployment process and should only take about a minute to complete (barring internet connection issues). The result will show an output that contains a URL for the API Gateway endpoint and look something like this:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Apply complete</span><span class="token operator">!</span><span class="token plain"> Resources: </span><span class="token number">30</span><span class="token plain"> added, </span><span class="token number">0</span><span class="token plain"> changed, </span><span class="token number">0</span><span class="token plain"> destroyed.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Outputs:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">App_Api_Endpoint_Url_E233F0E8 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://p9y42fs0gg.execute-api.us-east-1.amazonaws.com/prod"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">App_Slack_Request_Url_FF26641D </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://p9y42fs0gg.execute-api.us-east-1.amazonaws.com/prod/slack/events"</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The last step we need to do is to copy that <code>App_Slack_Request_Url</code> and paste it into the <code>Request URL</code> field in the <code>Event Subscriptions</code> section in the Slack API dashboard. This will tell Slack to now send events to our deployed applications API Gateway endpoint.</p>
<p>You should see the URL verified in a few seconds.</p>
<blockquote>
<p>DONT FORGET TO SAVE YOUR CHANGES!</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="Request URL AWS" src="https://www.winglang.io/assets/images/change-events-to-AWS-1b98f593165e0dd77d82826703d1afc0.png" width="1368" height="840" class="img_ev3q"></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="playing-with-the-deployed-app">Playing with the deployed app<a class="hash-link" aria-label="Direct link to Playing with the deployed app" title="Direct link to Playing with the deployed app" href="https://www.winglang.io/blog/2024/05/25/bring-slack#playing-with-the-deployed-app">​</a></h3>
<p>Let's first test adding a file to the inbox, which in AWS is an s3 bucket. Navigate to the S3 console in AWS and find the bucket with the name that contains <code>file-process-inbox</code> there will be some unique hashing to the end of it. For example, my bucket was named: <code>file-process-inbox-c8419ccc-20240530151737187700000004</code></p>
<p>Upload any file on your machine to this bucket, and you should see a message in your Slack channel!</p>
<p><img decoding="async" loading="lazy" alt="AWS Upload Slack Messages" src="https://www.winglang.io/assets/images/aws-upload-82051701afade8a4127c0720d67aed01.png" width="1226" height="838" class="img_ev3q"></p>
<p>Lastly, let's test the <code>list inbox</code> command.</p>
<p><img decoding="async" loading="lazy" alt="AWS List Inbox" src="https://www.winglang.io/assets/images/list-inbox-aws-6254a0e75f3861bcfdc03a8e33dd6f74.png" width="1106" height="1076" class="img_ev3q"></p>
<p>And there you have it! You have successfully built a Slack app using Wing, tested it locally, and deployed it to AWS!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="want-more">Want more?<a class="hash-link" aria-label="Direct link to Want more?" title="Direct link to Want more?" href="https://www.winglang.io/blog/2024/05/25/bring-slack#want-more">​</a></h2>
<p>If you find yourself wanting to learn more about Wing, or had any issues with this tutorial, or just wanna chat, feel free to join our <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">Discord</a> server!</p>]]></content:encoded>
            <author>hasana@wing.cloud (Hasan Abu-Rayyan)</author>
            <category>slack</category>
            <category>winglang</category>
            <category>winglibs</category>
            <category>programming</category>
            <category>bots</category>
        </item>
        <item>
            <title><![CDATA[Managing Winglang Libraries with AWS CodeArtifact]]></title>
            <link>https://www.winglang.io/blog/2024/05/20/managing-winglang-libraries-with-aws-code-artifact</link>
            <guid>https://www.winglang.io/blog/2024/05/20/managing-winglang-libraries-with-aws-code-artifact</guid>
            <pubDate>Mon, 20 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Managing Winglang Libraries with AWS CodeArtifact]]></description>
            <content:encoded><![CDATA[<div fontsize:="">Needs, Challenges, and Solutions</div>
<p><a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> provides a solution for contributing to its <a href="https://github.com/winglang/winglibs" target="_blank" rel="noopener noreferrer">Winglibs</a> project. This is the way to go if you only need to wrap a particular cloud resource on one or more platforms. Just follow the <a href="https://github.com/winglang/winglibs?tab=readme-ov-file#how-do-i-add-a-new-library" target="_blank" rel="noopener noreferrer">guidelines</a>. However, while developing the initial version of the <a href="https://medium.com/itnext/in-search-for-winglang-middleware-868443bd81f2" target="_blank" rel="noopener noreferrer">Endor</a> middleware framework, I had different needs.</p>
<p>First, the <a href="https://medium.com/itnext/in-search-for-winglang-middleware-868443bd81f2" target="_blank" rel="noopener noreferrer">Endor</a> library is in a very initial exploratory phase—far from a maturity level to be considered a contribution candidate for publishing in the public <a href="https://www.npmjs.com/" target="_blank" rel="noopener noreferrer">NPM Registry</a>.</p>
<p>Second, it includes several supplementary and still immature tool libraries, such as Exceptions and Logging. These tools need to be published separately (see explanation below). Therefore, I needed a solution for managing multiple <a href="https://docs.npmjs.com/about-packages-and-modules" target="_blank" rel="noopener noreferrer">NPM Packages</a> in one project.</p>
<p>Third, I wanted to explore how prospective <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> customers will be able to manage their internal libraries.</p>
<p>For that goal, I decided to experiment with the <a href="https://docs.aws.amazon.com/codeartifact/latest/ug/welcome.html" target="_blank" rel="noopener noreferrer">AWS CodeArtifact</a> service configured to play the role of my internal NPM Registry.</p>
<p>This publication is an experience report about the first phase, primarily focused on the developer’s experience with my Multi-Account, Multi-Platform, Multi-User (MAPU) environment, which I reported about <a href="https://medium.com/@asher-sterkin/aws-mapu-65e888009916" target="_blank" rel="noopener noreferrer">here</a>, <a href="https://medium.com/aws-in-plain-english/simplifying-remote-cloud-based-development-connections-58a7b7539cc5" target="_blank" rel="noopener noreferrer">here</a>, and <a href="https://medium.com/aws-in-plain-english/balancing-productivity-and-cost-in-cloud-based-remote-desktop-593408c9db9e" target="_blank" rel="noopener noreferrer">here</a>. Specifically, I configured the AWS CodeArtifact <a href="https://docs.aws.amazon.com/codeartifact/latest/ug/domain-overview.html" target="_blank" rel="noopener noreferrer">Domain</a> and <a href="https://docs.aws.amazon.com/codeartifact/latest/ug/repos.html" target="_blank" rel="noopener noreferrer">Repository</a> within my working account and postponed a more elaborate enterprise-grade system architecture to later stages. Let’s start with the overall solution overview.</p>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:720/format:webp/1*sBhJjRiOgVwh_CZQPd6V8w.jpeg" class="img_ev3q">
</div>
<p>Here is a brief description of the solution:</p>
<ol>
<li>Within my <code>winglang</code> account, I created an AWS CodeArtifact <a href="https://docs.aws.amazon.com/codeartifact/latest/ug/domain-overview.html" target="_blank" rel="noopener noreferrer">Domain</a> tentatively named <code>&lt;organizationID&gt;-platform</code>.</li>
<li>Under this <a href="https://docs.aws.amazon.com/codeartifact/latest/ug/domain-overview.html" target="_blank" rel="noopener noreferrer">Domain</a>, I created an AWS CodeArtifact <a href="https://docs.aws.amazon.com/codeartifact/latest/ug/repos.html" target="_blank" rel="noopener noreferrer">Repository</a> tentatively named <code>winglang-artifacts</code>.</li>
<li>This AWS CodeArtifact <a href="https://docs.aws.amazon.com/codeartifact/latest/ug/repos.html" target="_blank" rel="noopener noreferrer">Repository</a> is connected to the public <a href="https://www.npmjs.com/" target="_blank" rel="noopener noreferrer">npmjs</a> repository, from which all third-party packages, including those from the official <a href="https://github.com/winglang/winglibs" target="_blank" rel="noopener noreferrer">Winglibs</a>, are downloaded.</li>
<li>The AWS CodeArtifact <a href="https://docs.aws.amazon.com/codeartifact/latest/ug/repos.html" target="_blank" rel="noopener noreferrer">Repository</a> contains two types of packages:
<ol>
<li>Those that were developed and published locally.</li>
<li>Those that were cloned from the external <a href="https://www.npmjs.com/" target="_blank" rel="noopener noreferrer">npmjs</a> repository.</li>
</ol>
</li>
<li>Locally developed packages belong to the <code>@winglibs</code> <a href="https://docs.npmjs.com/about-scopes" target="_blank" rel="noopener noreferrer">NPM Namespace</a>. At the moment, this is a requirement determined by how the <a href="https://www.winglang.io/docs/language-reference#41-imports" target="_blank" rel="noopener noreferrer">Winglang import system</a> works.</li>
<li>The remote EC2 desktop instance is configured to use the AWS CodeArtifact <a href="https://docs.aws.amazon.com/codeartifact/latest/ug/repos.html" target="_blank" rel="noopener noreferrer">Repository</a> as its <a href="https://docs.npmjs.com/cli/v8/using-npm/registry" target="_blank" rel="noopener noreferrer">NPM Registry</a> using a temporary session token valid for 12 hours.</li>
<li>As a developer, I communicate with my remote desktop using the <a href="https://code.visualstudio.com/docs/remote/ssh" target="_blank" rel="noopener noreferrer">VS Code Remote</a> feature,  described in the <a href="https://medium.com/aws-in-plain-english/simplifying-remote-cloud-based-development-connections-58a7b7539cc5" target="_blank" rel="noopener noreferrer">previous publication</a>.</li>
</ol>
<p>I found this arrangement suitable for a solo developer and researcher. A real organization, even of a middle size, will require some substantial adjustments — subject to further investigation.</p>
<p>Let’s now look at some technical implementation details.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="cloud-resources-allocation">Cloud Resources Allocation<a class="hash-link" aria-label="Direct link to Cloud Resources Allocation" title="Direct link to Cloud Resources Allocation" href="https://www.winglang.io/blog/2024/05/20/managing-winglang-libraries-with-aws-code-artifact#cloud-resources-allocation">​</a></h2>
<p>Using Cloud Formation templates is always my preferred option. In this case, I created two simple Cloud Formation templates. One for creating an <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codeartifact-domain.html" target="_blank" rel="noopener noreferrer">AWS CodeArtifact Domain</a> resource:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-json codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"AWSTemplateFormatVersion"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2010-09-09"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"Description"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Template to create a CodeArtifact Domain; to be a part of platform template"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"Resources"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"ArtifactDomain"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token property">"Type"</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"AWS::CodeArtifact::Domain"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token property">"Properties"</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token property">"DomainName"</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"o-4e7dgfcrpx-platform"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And another - for creating an <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codeartifact-repository.html" target="_blank" rel="noopener noreferrer">AWS CodeArtifact Repository</a> resource:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-json codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"AWSTemplateFormatVersion"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2010-09-09"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"Description"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Template to create a CodeArtifact repository; to be a part of account template"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"Resources"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"ArtifactRespository"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token property">"Type"</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"AWS::CodeArtifact::Repository"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token property">"Properties"</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token property">"Description"</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"artifact repository for this &lt;winglang&gt; account"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token property">"DomainName"</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"o-4e7dgfcrpx-platform"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token property">"RepositoryName"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"winglang-artifacts"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token property">"ExternalConnections"</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"public:npmjs"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>These templates are mere placeholders for future, more serious, development.</p>
<p>The same could be achieved with <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>, as follows:</p>
<p><a href="https://gist.github.com/eladb/5e1ddd1bd90c53d90b2195d080397381" target="_blank" rel="noopener noreferrer">https://gist.github.com/eladb/5e1ddd1bd90c53d90b2195d080397381</a></p>
<p>Many thanks to <a href="https://www.linkedin.com/in/hackingonstuff/" target="_blank" rel="noopener noreferrer">Elad Ben-Israel</a> for bringing this option to my attention. Currently, the whole <a href="https://medium.com/@asher-sterkin/aws-mapu-65e888009916" target="_blank" rel="noopener noreferrer">MAPU</a> system is implemented in Python and CloudFormation. Re-implementing it completely in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> would be a fascinating case study.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="configuring-npm-with-the-login-command"><strong>Configuring npm with the login command</strong><a class="hash-link" aria-label="Direct link to configuring-npm-with-the-login-command" title="Direct link to configuring-npm-with-the-login-command" href="https://www.winglang.io/blog/2024/05/20/managing-winglang-libraries-with-aws-code-artifact#configuring-npm-with-the-login-command">​</a></h2>
<p>I followed the <a href="https://docs.aws.amazon.com/codeartifact/latest/ug/npm-auth.html#configure-npm-login-command" target="_blank" rel="noopener noreferrer">official guidelines</a> and created the following Bash script:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token builtin class-name" style="color:rgb(189, 147, 249)">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">CODEARTIFACT_AUTH_TOKEN</span><span class="token operator">=</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$(</span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	aws codeartifact get-authorization-token </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	--domain o-4e7dgfcrpx-platform </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	--domain-owner </span><span class="token variable number" style="color:rgb(189, 147, 249);font-style:italic">851725645964</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	--query authorizationToken </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	--output text</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">REPOSITORY_ENDPOINT</span><span class="token operator">=</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$(</span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	aws codeartifact get-repository-endpoint </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	--domain o-4e7dgfcrpx-platform </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	--domain-owner </span><span class="token variable number" style="color:rgb(189, 147, 249);font-style:italic">851725645964</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	--repository winglang-artifacts </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	--format </span><span class="token variable function" style="color:rgb(80, 250, 123);font-style:italic">npm</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	--query repositoryEndpoint </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	--output text</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">REGISTRY</span><span class="token operator">=</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$(</span><span class="token variable builtin class-name" style="color:rgb(189, 147, 249);font-style:italic">echo</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable string" style="color:rgb(255, 121, 198);font-style:italic">"</span><span class="token variable string variable" style="color:rgb(189, 147, 249);font-style:italic">$REPOSITORY_ENDPOINT</span><span class="token variable string" style="color:rgb(255, 121, 198);font-style:italic">"</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable operator" style="color:rgb(189, 147, 249);font-style:italic">|</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable function" style="color:rgb(80, 250, 123);font-style:italic">sed</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable string" style="color:rgb(255, 121, 198);font-style:italic">'s|https:||'</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> config </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">registry</span><span class="token operator">=</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$REPOSITORY_ENDPOINT</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> config </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">set</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$REGISTRY</span><span class="token plain">:_authToken</span><span class="token operator">=</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$CODEARTIFACT_AUTH_TOKEN</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Here is a brief description of the script’s logic:</p>
<ol>
<li>Using the AWS CLI, retrieve an AWS CodeArtifact session token (valid for the next 12 hours).</li>
<li>Using the AWS CLI, the AWS CodeArtifact repository endpoint in a format compatible with NPM.</li>
<li>Use the NPM <code>config</code> command to set the endpoint.</li>
<li>Use the NPM <code>config</code> command to set up session authentication.</li>
</ol>
<p>Placing this script in the <code>[/etc/profile.d](https://www.linuxfromscratch.org/blfs/view/11.0/postlfs/profile.html)</code> ensures that it will be automatically executed at every user login thus making the whole communication with AWS CodeArtifact instead of the official <code>[npmjs](https://docs.npmjs.com/cli/v8/using-npm/registry)</code> repository completely transparent for the end user.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="publishing-custom-libraries">Publishing Custom Libraries<a class="hash-link" aria-label="Direct link to Publishing Custom Libraries" title="Direct link to Publishing Custom Libraries" href="https://www.winglang.io/blog/2024/05/20/managing-winglang-libraries-with-aws-code-artifact#publishing-custom-libraries">​</a></h2>
<p>Implementing this operation while addressing my specific needs required a more sophisticated logic reflected in the following script:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token shebang important">#!/bin/bash</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">set</span><span class="token plain"> -euo pipefail</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Function to clean up tarball and extracted package</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function-name function" style="color:rgb(80, 250, 123)">cleanup</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">rm</span><span class="token plain"> *.tgz</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">rm</span><span class="token plain"> -fR package</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Function to calculate the checksum of a package tarball</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function-name function" style="color:rgb(80, 250, 123)">calculate_checksum</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">local</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">tarball</span><span class="token operator">=</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$(</span><span class="token variable function" style="color:rgb(80, 250, 123);font-style:italic">ls</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> *.tgz </span><span class="token variable operator" style="color:rgb(189, 147, 249);font-style:italic">|</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable function" style="color:rgb(80, 250, 123);font-style:italic">head</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> -n </span><span class="token variable number" style="color:rgb(189, 147, 249);font-style:italic">1</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">tar</span><span class="token plain"> -xzf </span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$tarball</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> package </span><span class="token operator">||</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">exit</span><span class="token plain"> </span><span class="token number">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">local</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">checksum</span><span class="token operator">=</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$(</span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	    </span><span class="token variable function" style="color:rgb(80, 250, 123);font-style:italic">tar</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	    --exclude</span><span class="token variable operator" style="color:rgb(189, 147, 249);font-style:italic">=</span><span class="token variable string" style="color:rgb(255, 121, 198);font-style:italic">'$lib'</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	    --sort</span><span class="token variable operator" style="color:rgb(189, 147, 249);font-style:italic">=</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">name </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	    --mtime</span><span class="token variable operator" style="color:rgb(189, 147, 249);font-style:italic">=</span><span class="token variable string" style="color:rgb(255, 121, 198);font-style:italic">'UTC 1970-01-01'</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	    --owner</span><span class="token variable operator" style="color:rgb(189, 147, 249);font-style:italic">=</span><span class="token variable number" style="color:rgb(189, 147, 249);font-style:italic">0</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	    --group</span><span class="token variable operator" style="color:rgb(189, 147, 249);font-style:italic">=</span><span class="token variable number" style="color:rgb(189, 147, 249);font-style:italic">0</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable punctuation" style="color:rgb(248, 248, 242);font-style:italic">\</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">	    --numeric-owner -cf - </span><span class="token variable builtin class-name" style="color:rgb(189, 147, 249);font-style:italic">.</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable operator" style="color:rgb(189, 147, 249);font-style:italic">|</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> sha256sum </span><span class="token variable operator" style="color:rgb(189, 147, 249);font-style:italic">|</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable function" style="color:rgb(80, 250, 123);font-style:italic">awk</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable string" style="color:rgb(255, 121, 198);font-style:italic">'{print $1}'</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    cleanup</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">echo</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$checksum</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function-name function" style="color:rgb(80, 250, 123)">get_version</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">PACKAGE_VERSION</span><span class="token operator">=</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$(</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">jq -r </span><span class="token variable string" style="color:rgb(255, 121, 198);font-style:italic">'.version'</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> package.json</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function-name function" style="color:rgb(80, 250, 123)">publish</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">echo</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Publishing new version: </span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$PACKAGE_VERSION</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> publish --access public --tag latest *.tgz</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    cleanup</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">exit</span><span class="token plain"> </span><span class="token number">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Step 1: Read the package version from package.json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">get_version</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">PACKAGE_NAME</span><span class="token operator">=</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$(</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">jq -r </span><span class="token variable string" style="color:rgb(255, 121, 198);font-style:italic">'.name'</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> package.json</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Step 2: Check the latest version in the npm registry</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">LATEST_VERSION</span><span class="token operator">=</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$(</span><span class="token variable function" style="color:rgb(80, 250, 123);font-style:italic">npm</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> show </span><span class="token variable string" style="color:rgb(255, 121, 198);font-style:italic">"</span><span class="token variable string variable" style="color:rgb(189, 147, 249);font-style:italic">$PACKAGE_NAME</span><span class="token variable string" style="color:rgb(255, 121, 198);font-style:italic">"</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> version </span><span class="token variable operator file-descriptor important" style="color:rgb(189, 147, 249);font-style:italic">2</span><span class="token variable operator" style="color:rgb(189, 147, 249);font-style:italic">&gt;</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">/dev/null </span><span class="token variable operator" style="color:rgb(189, 147, 249);font-style:italic">||</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable builtin class-name" style="color:rgb(189, 147, 249);font-style:italic">echo</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic"> </span><span class="token variable string" style="color:rgb(255, 121, 198);font-style:italic">""</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Step 3: Prepare wing package</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing pack</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Step 4: If the versions are not equal, publish the new version</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$PACKAGE_VERSION</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"> </span><span class="token operator">!=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$LATEST_VERSION</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">then</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    publish</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">CURRENT_CHECKSUM</span><span class="token operator">=</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$(</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">calculate_checksum</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Download the latest package tarball</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> pack </span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$PACKAGE_NAME</span><span class="token string" style="color:rgb(255, 121, 198)">@</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$LATEST_VERSION</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"> </span><span class="token operator">&gt;</span><span class="token plain"> /dev/null </span><span class="token operator file-descriptor important">2</span><span class="token operator">&gt;</span><span class="token file-descriptor important">&amp;1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">LATEST_CHECKSUM</span><span class="token operator">=</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$(</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">calculate_checksum</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Step 5: Compare the checksums</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$CURRENT_CHECKSUM</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"> </span><span class="token operator">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$LATEST_CHECKSUM</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">then</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">echo</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"No changes detected. Checksum matches the latest published version."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">exit</span><span class="token plain"> </span><span class="token number">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">echo</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$CURRENT_CHECKSUM</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">echo</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$LATEST_CHECKSUM</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">echo</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Checksums do not match. Bumping patch version..."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> version patch</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        wing pack</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        get_version</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        publish</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">fi</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">fi</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Here is a brief explanation of what happens in this script:</p>
<ol>
<li><strong>Step 1:</strong> Using the <code>[jq](https://jqlang.github.io/jq/)</code> command, extract the package name and version from the <code>package.json</code> file.</li>
<li><strong>Step 2:</strong> Using the <code>[npm show](https://docs.npmjs.com/cli/v10/commands/npm-view)</code> command, extract the package version number from the registry.</li>
<li><strong>Step 3:</strong> Using the <code>[wing pack](https://www.winglang.io/docs/libraries)</code> command, prepare the package .tgz file.</li>
<li><strong>Step 4:</strong> If version numbers differ, publish the new version using the <code>[npm publish](https://docs.npmjs.com/cli/v10/commands/npm-publish)</code> command.</li>
<li><strong>Step 5:</strong> If the versions are equal, calculate the checksum for the current and most recently published package. If the checksum values are equal, do nothing. Otherwise, using the <code>[npm version patch](https://docs.npmjs.com/cli/v10/commands/npm-version)</code> command, automatically bump up the <code>[patch](https://symver.org/)</code> version number, rebuild the .tgz file, and publish the new version.</li>
</ol>
<p>Reliable checksum validation was the most challenging part of developing this script. The <code>wing pack</code> command creates a special <code>@lib</code> folder within the resulting <code>.tgz</code> archive. This folder introduces some randomness and can be affected by several factors, including <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> compiler upgrades. Additionally, the <code>.tgz</code> file checksum calculation is sensitive to the order and timestamps of individual files. As a result, comparing the results of direct checksum calculation for the current and published packages was not an option.</p>
<p>To overcome these limitations, new archives are created with the <code>@lib</code> folder excluded and file order and timestamps normalized. The assistance of the <a href="https://openai.com/gpt-4" target="_blank" rel="noopener noreferrer">ChatGPT 4o</a> tool proved instrumental, especially in addressing this challenge.</p>
<p>In the current implementation, I keep this script in my home directory and invoke it from a common <code>[Build.mk](http://Build.mk)</code> Makefile used for all libraries (this might change in the future):</p>
<div class="language-makefile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-makefile codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token builtin-target builtin" style="color:rgb(189, 147, 249)">.PHONY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> all compile-deps build-ts prepare test publish</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">all</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> publish</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">update-deps</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	npm install &amp;&amp; npm update</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">compile-ts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> update-deps</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">ifneq</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">wildcard</span><span class="token plain"> tsconfig.json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">,</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token operator">@</span><span class="token plain">echo </span><span class="token string" style="color:rgb(255, 121, 198)">"tsconfig.json found, running tsc..."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	tsc</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token operator">@</span><span class="token plain">echo </span><span class="token string" style="color:rgb(255, 121, 198)">"tsconfig.json not found, skipping TypeScript compilation."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">endif</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> compile-ts</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	wing test -t sim ./test/*.test.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">publish</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> test</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	~/publish-npm.sh</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="justification">Justification<a class="hash-link" aria-label="Direct link to Justification" title="Direct link to Justification" href="https://www.winglang.io/blog/2024/05/20/managing-winglang-libraries-with-aws-code-artifact#justification">​</a></h2>
<p>To explain why I chose this particular way of publishing logic, I need to explain my overall project structure, illustrated in the diagram below:</p>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:720/format:webp/1*9bmBtM_oV0tZWUVeONgqtw.jpeg" class="img_ev3q">
</div>
<p>The top of the diagram above reflects the NMP packages involved and their dependencies are depicted at the top, while the bottom part reflects my project folder structure.</p>
<p>The <code>endor</code> package is the ultimate goal of this development activity: an exploratory middleware framework for the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> programming language. Its efficacy is validated by a separate <code>todo.endor.w</code> application. Initially, both modules were kept together. However, keeping pure application parts separate from the infrastructure became progressively challenging.</p>
<p>The <code>endor</code> package uses three auxiliary packages <code>logging</code> , <code>exception</code>, and <code>datetimex</code>. These three packages are potential candidates to be contributed to the <a href="https://github.com/winglang/winglibs" target="_blank" rel="noopener noreferrer">Winglibs</a> project. However, they are still under active experimentation and development and are kept within the same Github repository.</p>
<p>Additionally, the <code>endor</code> package depends on other packages published on the public <code>[npmjs](https://docs.npmjs.com/cli/v8/using-npm/registry)</code> registry. Some of these packages, such as <code>dynamodb</code> and <code>jwt</code> belong to the same <code>@winglibs</code> namespace, while others do not.</p>
<p>I face a mixed-case challenge: the system already has a modular structure, but all components are under intensive development, requiring instant propagation of changes. As a solo developer and researcher, I still do not need more sophisticated CI/CD solutions, but rather employ a master Makefile to pull everything together:</p>
<div class="language-makefile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-makefile codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token builtin-target builtin" style="color:rgb(189, 147, 249)">.PHONY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> all \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			  update_npm \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			  update_wing \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			  update_tsc \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			  make_datetimex \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			  make_exception \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			  make_logging \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">			  make_endor</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">all</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">  update_wing make_endor</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">update_npm</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	sudo npm update -g npm</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">update_tsc</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> update_npm</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	sudo npm update -g tsc</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">update_wing</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> update_tsc</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	sudo npm update -g winglang</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">make_datetimex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">MAKE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> -C ./datetimex -f ../Build.mk</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">make_logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> make_datetimex</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">MAKE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> -C ./logging -f ../Build.mk</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">make_exception</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">MAKE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> -C ./exception -f ../Build.mk</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">make_endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> make_exception make_logging</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">MAKE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> -C ./endor -f ../Build.mk</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>todo.endor.w</code> Makefile looks like this:</p>
<div class="language-makefile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-makefile codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token builtin-target builtin" style="color:rgb(189, 147, 249)">.PHONY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> all update_wing install_endor test_local </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">cloud </span><span class="token operator">?=</span><span class="token plain"> aws</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">target </span><span class="token operator">:=</span><span class="token plain"> target/main.tf</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">update_npm</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	sudo npm update -g npm</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">update_wing</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> update_npm</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	sudo npm update -g winglang</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">install_endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	npm install &amp;&amp; npm update</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">build_ts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	tsc</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">test_local</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> update_wing install_endor build_ts test_app</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">test_app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	wing test -t sim ./test/*.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">test_remote</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	wing test -t tf-</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> ./test/service.test.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">run_local</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	wing run -t sim ./dev.main.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">compile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	wing compile ./main.w -t tf-</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">tf-init</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> compile</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"> \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		cd </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">target</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">\</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		terraform init \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">deploy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> tf-init</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"> \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		cd </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">target</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">\</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		terraform apply -auto-approve \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token target symbol" style="color:rgb(248, 248, 242)">destroy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"> \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		cd </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">target</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">\</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		terraform destroy -auto-approve \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This arrangement allows me to keep modules isolated, make changes in several places where appropriate, and perform fully automated build and verification without needing manual version updates within multiple <code>package.json</code> files.</p>
<p>Specifying cross-package dependencies is another point to pay attention to. Here is the <code>endor</code> package specification:</p>
<div class="language-makefile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-makefile codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"name"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@winglibs/endor"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"description"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Wing middleware framework library"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"repository"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"type"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"git"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"url"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://github.com/asterkin/endor.w.git"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"directory"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"endor"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"version"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0.0.19"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"author"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"email"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"asher.sterkin@gmail.com"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"name"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Asher Sterkin"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"license"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MIT"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"peerDependencies"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"@authenio/samlify-node-xmllint"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2.x.x"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"@winglibs/dynamodb"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0.x.x"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"@winglibs/jwt"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0.x.x"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"qs"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"6.x.x"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"samlify"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2.x.x"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"ws"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"8.x.x"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"inflection"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"3.x.x"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"@winglibs/exception"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0.x.x"</span><span class="token plain">,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"@winglibs/logging"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0.x.x"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Notice that, unlike traditional formats, all dependencies are specified using the <code>x</code> placeholder without the leading <code>^</code> symbol. This is because, with the <code>^</code> prefix included, the most up-to-date versions are brought in only for the final <code>todo.endor.w</code> application, whereas I needed them to be used in the dependent modules' unit tests. Using the <code>x</code> placeholder instead does the job.</p>
<p>In summary, while not final, the described solution provides good enough treatment for all essential requirements at the current stage of the system evolution. As the system grows, adequate adjustments will be implemented and reported. Stay tuned.</p>
<h1>Acknowledgments</h1>
<p>Throughout the preparation of this publication, I utilized several key tools to enhance the draft and ensure its quality.</p>
<p>The initial draft was crafted with the organizational capabilities of <a href="https://www.notion.so/" target="_blank" rel="noopener noreferrer">Notion</a>'s free subscription, facilitating the structuring and development of ideas.</p>
<p>For grammar and spelling review, the free version of <a href="https://app.grammarly.com/" target="_blank" rel="noopener noreferrer">Grammarly</a> proved useful for identifying and correcting basic errors, ensuring the readability of the text.</p>
<p>The enhancement of stylistic expression and the narrative coherence checks were performed using the paid version of <a href="https://openai.com/gpt-4" target="_blank" rel="noopener noreferrer">ChatGPT 4o</a>. The <a href="https://openai.com/gpt-4" target="_blank" rel="noopener noreferrer">ChatGPT 4o</a> tool was also used for developing the package publishing script and creation of NMP elements icons.</p>
<p>While these advanced tools and resources significantly contributed to the preparation process, the concepts, solutions, and final decisions presented in this article are entirely my own, for which I bear full responsibility.</p>]]></content:encoded>
            <author>asher.sterkin@gmail.com (Asher Sterkin)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>middleware</category>
            <category>platforms</category>
        </item>
        <item>
            <title><![CDATA[Building your own ChatGPT Graphical Client with NextJS and Wing]]></title>
            <link>https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing</link>
            <guid>https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing</guid>
            <pubDate>Thu, 16 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[A ChatGPT client app built with Winglang and NextJS]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithStickyNavbar_LWe7" id="tldr">TL;DR<a class="hash-link" aria-label="Direct link to TL;DR" title="Direct link to TL;DR" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#tldr">​</a></h2>
<p>By the end of this article, you will build and deploy a ChatGPT Client using Wing and Next.js.</p>
<p>This application can run locally (in a local cloud simulator) or deploy it to your own cloud provider.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1sm2cj4sbcm4skp0ho23.gif" alt="Dance" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="introduction">Introduction<a class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#introduction">​</a></h2>
<p>Building a ChatGPT client and deploying it to your own cloud infrastructure is a good way to ensure control over your data.</p>
<p>Deploying LLMs to your own cloud infrastructure provides you with both privacy and security for your project.</p>
<p>Sometimes, you may have concerns about your data being stored or processed on remote servers when using proprietary LLM platforms like OpenAI’s ChatGPT, either due to the sensitivity of the data being fed into the platform or for other privacy reasons.</p>
<p>In this case, self-hosting an LLM to your cloud infrastructure or running it locally on your machine gives you greater control over the privacy and security of your data.</p>
<blockquote>
<p><a href="https://git.new/wing-repo" target="_blank" rel="noopener noreferrer">Wing</a> is a cloud-oriented programming language that lets you build and deploy cloud-based applications without worrying about the underlying infrastructure.
It simplifies the way you build on the cloud by allowing you to define and manage your cloud infrastructure and your application code within the same language.
Wing is cloud agnostic - applications built with it can be compiled and deployed to various cloud platforms.</p>
</blockquote>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="lets-get-started">Let's get started!<a class="hash-link" aria-label="Direct link to Let's get started!" title="Direct link to Let's get started!" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#lets-get-started">​</a></h2>
<p>To follow along, you need to:</p>
<ul>
<li>Have some understanding of Next.js</li>
<li><a href="https://www.winglang.io/docs/" target="_blank" rel="noopener noreferrer">Install Wing</a> on your machine. Not to worry if you don’t know how to. We’ll go over it together in this project.</li>
<li>Get your OpenAI API key.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="create-your-projects">Create Your Projects<a class="hash-link" aria-label="Direct link to Create Your Projects" title="Direct link to Create Your Projects" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#create-your-projects">​</a></h2>
<p>To get started, you need to install Wing on your machine. Run the following command:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"> -g winglang</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Confirm the installation by checking the version:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing --version</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="create-your-nextjs-and-wing-apps">Create your Next.js and Wing apps.<a class="hash-link" aria-label="Direct link to Create your Next.js and Wing apps." title="Direct link to Create your Next.js and Wing apps." href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#create-your-nextjs-and-wing-apps">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">mkdir</span><span class="token plain"> assistant</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> assistant</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">npx create-next-app@latest frontend</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">mkdir</span><span class="token plain"> backend </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> backend</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing new empty</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>We have successfully created our Wing and Next.js projects inside the assistant directory. The name of our ChatGPT Client is Assistant. Sounds cool, right?</p>
<p>The frontend and backend directories contain our Next and Wing apps, respectively. <code>wing new empty</code> creates three files: <code>package.json</code>, <code>package-lock.json</code>, and <code>main.w</code>. The latter is the app’s entry point.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="run-your-application-locally-in-the-wing-simulator">Run your application locally in the Wing simulator<a class="hash-link" aria-label="Direct link to Run your application locally in the Wing simulator" title="Direct link to Run your application locally in the Wing simulator" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#run-your-application-locally-in-the-wing-simulator">​</a></h3>
<p>The Wing simulator allows you to run your code, write unit tests, and debug your code inside your local machine without needing to deploy to an actual cloud provider, helping you iterate faster.</p>
<p>Use the following command to run your Wing app locally:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing it</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Your Wing app will run on <code>localhost:3000</code>.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n5ytrntrz7lc5225w8w8.png" alt="Console" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="setting-up-your-backend">Setting Up Your Backend<a class="hash-link" aria-label="Direct link to Setting Up Your Backend" title="Direct link to Setting Up Your Backend" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#setting-up-your-backend">​</a></h2>
<ul>
<li>Let’s install Wing’s OpenAI and React Libraries. The OpenAI library provides a standard interface to interact with the LLM. The React library allows you to connect your Wing backend to your Next app.</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> i @winglibs/openai @winglibs/react</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ul>
<li>Import these packages in your <code>main.w</code> file. Let's also import all the other libraries we’ll need.</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring openai</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring react</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring ex</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring http</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><code>bring</code> is the import statement in Wing. Think of it this way, Wing uses <code>bring</code> to achieve the same functionality as <code>import</code> in JavaScript.</p>
<p><code>cloud</code> is Wing’s Cloud library. It exposes a standard interface for Cloud API, Bucket, Counter, Domain, Endpoint, Function and many more cloud resources. <code>ex</code> is a standard library for interfacing with Tables and cloud Redis database, and <code>http</code> is for calling different HTTP methods - sending and retrieving information from remote resources.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-your-openai-api-key">Get Your OpenAI API Key<a class="hash-link" aria-label="Direct link to Get Your OpenAI API Key" title="Direct link to Get Your OpenAI API Key" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#get-your-openai-api-key">​</a></h2>
<p>We will use <code>gpt-4-turbo</code> for our app but you can use any OpenAI model.</p>
<ul>
<li>Create an <a href="https://platform.openai.com/signup" target="_blank" rel="noopener noreferrer">OpenAI</a> account if you don’t have one yet. To create a new API key, Go to <a href="http://platform.openai.com/api-keys" target="_blank" rel="noopener noreferrer">platform.openai.com/api-keys</a> and select <strong>Create new secret key.</strong></li>
</ul>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9645jxsf1fj8902iwnr7.png" alt="OpenAI Key" class="img_ev3q"></p>
<ul>
<li>Set the <strong>Name</strong>, <strong>Project,</strong> and <strong>Permissions,</strong> then click <strong>Create secret key.</strong></li>
</ul>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yng28wns7esezf94t3uq.png" alt="OpenAI Key2" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="initializing-openai">Initializing OpenAI<a class="hash-link" aria-label="Direct link to Initializing OpenAI" title="Direct link to Initializing OpenAI" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#initializing-openai">​</a></h2>
<p>Create a <code>Class</code> to initialize your OpenAI API. We want this to be reusable.</p>
<p>We will add a <code>personality</code> to our <code>Assistant</code> class so that we can dictate the personality of our AI assistant when passing a prompt to it.</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-jsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> apiKeySecret </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Secret</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"OAIAPIKey"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"OpenAI Secret"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Assistant</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">personality</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">openai</span><span class="token operator">:</span><span class="token plain"> openai</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">OpenAI</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">personality</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">openai</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">openai</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">OpenAI</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">apiKeySecret</span><span class="token operator">:</span><span class="token plain"> apiKeySecret</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">personality</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> personality</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">ask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">question</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> prompt </span><span class="token operator">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">you are an assistant with the following personality: </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation property-access">personality</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">. </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">question</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">openai</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">createCompletion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">prompt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token literal-property property">model</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"gpt-4-turbo"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">trim</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Wing unifies infrastructure definition and application logic using the <code>preflight</code> and <code>inflight</code> concepts respectively.</p>
<p><strong>Preflight</strong> code (typically infrastructure definitions) runs once at compile time, while <strong>inflight</strong> code will run at runtime to implement your app’s behavior.</p>
<p>Cloud storage buckets, queues, and API endpoints are some examples of preflight. You don’t need to add the preflight keyword when defining a preflight, Wing knows this by default. But for an inflight block, you need to add the word “inflight” to it.</p>
<blockquote>
<p>We have an inflight block in the code above. Inflight blocks are where you write asynchronous runtime code that can directly interact with resources through their inflight APIs.</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="testing-and-storing-the-cloud-secret">Testing and Storing The Cloud Secret<a class="hash-link" aria-label="Direct link to Testing and Storing The Cloud Secret" title="Direct link to Testing and Storing The Cloud Secret" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#testing-and-storing-the-cloud-secret">​</a></h2>
<p>Let's walk through how we will secure our API keys because we definitely want to take <a href="https://techhq.com/2022/09/hardcoded-api-keys-jeopardize-data-in-the-cloud/" target="_blank" rel="noopener noreferrer">security into account</a>.</p>
<p>Let's create a <code>.env</code> file in our backend’s root and pass in our API Key:</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-jsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token maybe-class-name">OAIAPIKey</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Your_OpenAI_API_key</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>We can test our OpenAI API keys locally referencing our .env file, and then since we are planning to deploy to AWS,  we will walk through setting up the <a href="https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html" target="_blank" rel="noopener noreferrer">AWS Secrets Manager</a>.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e2a1nbh0egmjkckxnaov.png" alt="AWS Console" class="img_ev3q"></p>
<p>First, let's head over to AWS and sign into the Console. If you don't have an account, you can create one for free.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n937801fzs0lajf2knaq.png" alt="AWS Platform" class="img_ev3q"></p>
<p>Navigate to the Secrets Manager and let's store our API key values.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/scbb1snyzjdoip2nvdpl.png" alt="AWS Secrets Manager" class="img_ev3q"></p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lf79xzn6vfhqylao8iuo.png" alt="Image description" class="img_ev3q"></p>
<p>We have stored our API key in a cloud secret named <code>OAIAPIKey</code>. Copy your key and we will jump over to the terminal and connect to our secret that is now stored in the AWS Platform.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing secrets</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now paste in your API Key as the value in the terminal. Your keys are now properly stored and we can start interacting with our app.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="storing-the-ais-responses-in-the-cloud">Storing The AI’s Responses in the Cloud.<a class="hash-link" aria-label="Direct link to Storing The AI’s Responses in the Cloud." title="Direct link to Storing The AI’s Responses in the Cloud." href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#storing-the-ais-responses-in-the-cloud">​</a></h2>
<p>Storing your AI's responses in the cloud gives you control over your data. It resides on your own infrastructure, unlike proprietary platforms like ChatGPT, where your data lives on third-party servers that you don’t have control over. You can also retrieve these responses whenever you need them.</p>
<p>Let’s create another class that uses the Assistant class to pass in our AI’s personality and prompt. We would also store each model’s responses as <code>txt</code> files in a cloud bucket.</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-jsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> counter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">RespondToQuestions</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">id</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">gpt</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Assistant</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">store</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">store</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">gpt</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Assistant</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Respondent"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">id</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"NextID"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">store</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> store</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">sendPrompt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">question</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> reply </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">gpt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">ask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{question}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> n </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">inc</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">store</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">put</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"message-{n}.original.txt"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> reply</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> reply</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<hr>
<p>We gave our Assistant the personality “Respondent.” We want it to respond to questions. You could also let the user on the frontend dictate this personality when sending in their prompts.</p>
<p>Every time it generates a response, the counter increments, and the value of the counter is passed into the <code>n</code> variable used to store the model’s responses in the cloud. However, what we really want is to create a database to store both the user prompts coming from the frontend and our model’s responses.</p>
<p>Let's define our database.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="defining-our-database">Defining Our Database<a class="hash-link" aria-label="Direct link to Defining Our Database" title="Direct link to Defining Our Database" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#defining-our-database">​</a></h2>
<p>Wing has <code>ex.Table</code> built-in - a NoSQL database to store and query data.</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-jsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> db </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ex</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Table</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"assistant"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">primaryKey</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">columns</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">question</span><span class="token operator">:</span><span class="token plain"> ex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ColumnType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">STRING</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">answer</span><span class="token operator">:</span><span class="token plain"> ex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ColumnType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">STRING</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<hr>
<p>We added two columns in our database definition - the first to store user prompts and the second to store the model’s responses.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="creating-api-routes-and-logic">Creating API Routes and Logic<a class="hash-link" aria-label="Direct link to Creating API Routes and Logic" title="Direct link to Creating API Routes and Logic" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#creating-api-routes-and-logic">​</a></h2>
<p>We want to be able to send and receive data in our backend. Let’s create POST and GET routes.</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-jsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> api </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token literal-property property">cors</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">post</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"/assistant"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// POST request logic goes here</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"/assistant"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// GET request logic goes here</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<hr>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-jsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> myAssistant </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">RespondToQuestions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">store</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Helpful Assistant"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">post</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"/assistant"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> prompt </span><span class="token operator">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> myAssistant</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">sendPrompt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token known-class-name class-name">JSON</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">prompt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> id </span><span class="token operator">=</span><span class="token plain"> counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">inc</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// Insert prompt and response in the database</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    db</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">insert</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token literal-property property">question</span><span class="token operator">:</span><span class="token plain"> prompt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token literal-property property">answer</span><span class="token operator">:</span><span class="token plain"> response </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>In the POST route, we want to pass the user prompt received from the frontend into the model and get a response. Both prompt and response will be stored in the database. <code>cloud.ApiResponse</code> allows you to send a response for a user’s request.</p>
<p>Add the logic to retrieve the database items when the frontend makes a GET request.</p>
<hr>
<p>Add the logic to retrieve the database items when the frontend makes a GET request.</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-jsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"/assistant"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> questionsAndAnswers </span><span class="token operator">=</span><span class="token plain"> db</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">list</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">JSON</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">questionsAndAnswers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Our backend is ready. Let's test it out in the local cloud simulator.</p>
<p>Run <code>wing it</code>.</p>
<p>Lets go over to <code>localhost:3000</code> and ask&nbsp; our Assistant a question.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ox67623b9vye7o6quqe.png" alt="Assistant Response" class="img_ev3q"></p>
<p>Both our question and the Assistant’s response has been saved to the database. Take a look.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ajd94ywkhjw04yb21e2.png" alt="Table Data" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="exposing-your-api-url-to-the-frontend">Exposing Your API URL to The Frontend<a class="hash-link" aria-label="Direct link to Exposing Your API URL to The Frontend" title="Direct link to Exposing Your API URL to The Frontend" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#exposing-your-api-url-to-the-frontend">​</a></h2>
<p>We need to expose the API URL of our backend to our Next frontend. This is where the react library installed earlier comes in handy.</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-jsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> website </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">react</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">App</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">projectPath</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"../frontend"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">localPort</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">4000</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">website</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">addEnvironment</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"API_URL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Add the following to the <code>layout.js</code> of your Next app.</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-jsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">Inter</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"next/font/google"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./globals.css"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> inter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:rgb(80, 250, 123)">Inter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token literal-property property">subsets</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"latin"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> metadata </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">title</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Create Next App"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">description</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Generated by create next app"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">default</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:rgb(80, 250, 123)">RootLayout</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token parameter"> children </span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">html</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">lang</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">en</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">	        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">head</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">script</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">src</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">./wing.js</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">defer</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">script</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">           </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">head</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">body</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">inter</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">className</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">children</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">body</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">html</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>We now have access to <code>API_URL</code> in our Next application.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="implementing-the-frontend-logic">Implementing the Frontend Logic<a class="hash-link" aria-label="Direct link to Implementing the Frontend Logic" title="Direct link to Implementing the Frontend Logic" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#implementing-the-frontend-logic">​</a></h2>
<p>Let’s implement the frontend logic to call our backend.</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-jsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> useEffect</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> useState</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> useCallback </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'react'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports">axios</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'axios'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:rgb(80, 250, 123)">App</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">isThinking</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> setIsThinking</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">useState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">input</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> setInput</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">useState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">allInteractions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> setAllInteractions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">useState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> retrieveAllInteractions </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">useCallback</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">api_url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">axios</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		      </span><span class="token literal-property property">method</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"GET"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		      </span><span class="token literal-property property">url</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">api_url</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">/assistant</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">then</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">res</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		      </span><span class="token function" style="color:rgb(80, 250, 123)">setAllInteractions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> handleSubmit </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">useCallback</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">preventDefault</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    </span><span class="token function" style="color:rgb(80, 250, 123)">setIsThinking</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">isThinking</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">input</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">trim</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	      </span><span class="token function" style="color:rgb(80, 250, 123)">alert</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Chat cannot be empty"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	      </span><span class="token function" style="color:rgb(80, 250, 123)">setIsThinking</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	      </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	      </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">axios</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	        </span><span class="token literal-property property">method</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"POST"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	        </span><span class="token literal-property property">url</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation dom variable" style="color:rgb(189, 147, 249);font-style:italic">window</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation property-access">wingEnv</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation constant" style="color:rgb(189, 147, 249)">API_URL</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">/assistant</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	        </span><span class="token literal-property property">headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	          </span><span class="token string-property property">"Content-Type"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"application/json"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	        </span><span class="token literal-property property">data</span><span class="token operator">:</span><span class="token plain"> input</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	      </span><span class="token function" style="color:rgb(80, 250, 123)">setInput</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	      </span><span class="token function" style="color:rgb(80, 250, 123)">setIsThinking</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	      </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">retrieveAllInteractions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token dom variable" style="color:rgb(189, 147, 249);font-style:italic">window</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">wingEnv</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">API_URL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">     </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">useEffect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">typeof</span><span class="token plain"> </span><span class="token dom variable" style="color:rgb(189, 147, 249);font-style:italic">window</span><span class="token plain"> </span><span class="token operator">!==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"undefined"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token function" style="color:rgb(80, 250, 123)">retrieveAllInteractions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token dom variable" style="color:rgb(189, 147, 249);font-style:italic">window</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">wingEnv</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">API_URL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// Here you would return your component's JSX</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token comment" style="color:rgb(98, 114, 164)">// JSX content goes here</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">default</span><span class="token plain"> </span><span class="token maybe-class-name">App</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>retrieveAllInteractions</code> function fetches all the questions and answers in the backend’s database. The <code>handSubmit</code> function sends the user’s prompt to the backend.</p>
<p>Let’s add the JSX implementation.</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-jsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> useEffect</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> useState </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'react'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports">axios</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'axios'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'./App.css'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:rgb(80, 250, 123)">App</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">container</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">header</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">                </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">h1</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text">My Assistant</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">h1</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">                </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">p</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text">Ask anything...</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">p</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">chat-area</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">                </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">chat-area-content</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">                    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">allInteractions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">map</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">chat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">key</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">chat</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">id</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">user-bot-chat</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">                            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">p</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">user-question</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">chat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">question</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">p</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">                            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">p</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">response</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">'</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">chat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">answer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">p</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">                        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">                    </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">p</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">isThinking </span><span class="token tag script language-javascript operator" style="color:rgb(255, 121, 198)">?</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript string" style="color:rgb(255, 121, 198)">"thinking"</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript operator" style="color:rgb(255, 121, 198)">:</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript string" style="color:rgb(255, 121, 198)">"notThinking"</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text">Generating response...</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">p</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">                </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">                </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">type-area</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">                    </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">input</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">                        </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">type</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">text</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">                        </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">placeholder</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">Ask me any question</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">                        </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">value</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">input</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">                        </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">onChange</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript parameter" style="color:rgb(255, 121, 198)">e</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript arrow operator" style="color:rgb(255, 121, 198)">=&gt;</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript function" style="color:rgb(80, 250, 123)">setInput</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">e</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">target</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript property-access" style="color:rgb(255, 121, 198)">value</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">                    </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">                    </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">button</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">onClick</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">handleSubmit</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text">Send</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">button</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">                </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">default</span><span class="token plain"> </span><span class="token maybe-class-name">App</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="running-your-project-locally">Running Your Project Locally<a class="hash-link" aria-label="Direct link to Running Your Project Locally" title="Direct link to Running Your Project Locally" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#running-your-project-locally">​</a></h2>
<p>Navigate to your backend directory and run your Wing app locally using the following command</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-jsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">cd </span><span class="token operator">~</span><span class="token plain">assistant</span><span class="token operator">/</span><span class="token plain">backend</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing it</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Also run your Next.js frontend:</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-jsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">cd </span><span class="token operator">~</span><span class="token plain">assistant</span><span class="token operator">/</span><span class="token plain">frontend</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">npm run dev</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Let’s take a look at our application.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/97g8kikxfwwb7ephfdni.png" alt="Chat App" class="img_ev3q"></p>
<p>Let’s ask our AI Assistant a couple developer questions from our Next App.</p>
<p><img decoding="async" loading="lazy" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5uoz1y9czt0nwwtsesrz.png" alt="Chat App2" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="deploying-your-application-to-aws">Deploying Your Application to AWS<a class="hash-link" aria-label="Direct link to Deploying Your Application to AWS" title="Direct link to Deploying Your Application to AWS" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#deploying-your-application-to-aws">​</a></h2>
<p>We’ve seen how our app can work locally. Wing also allows you to deploy to any cloud provider including AWS. To deploy to AWS, you need <a href="https://terraform.io/downloads" target="_blank" rel="noopener noreferrer">Terraform</a> and <a href="https://docs.aws.amazon.com/cli/" target="_blank" rel="noopener noreferrer">AWS CLI</a> configured with your credentials.</p>
<ul>
<li>Compile to Terraform/AWS using <code>tf-aws</code>. The command instructs the compiler to use Terraform as the provisioning engine to bind all our resources to the default set of AWS resources.</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> ~/assistant/backend</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing compile --platform tf-aws main.w</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<hr>
<ul>
<li>Run Terraform Init and Apply</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> ./target/main.tfaws</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">terraform init</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">terraform apply</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<hr>
<p>Note: <code>terraform apply</code> takes some time to complete.</p>
<p>You can find the complete code for this tutorial <a href="https://github.com/NathanTarbert/chatgpt-client-wing-nextjs" target="_blank" rel="noopener noreferrer">here</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="wrapping-it-up">Wrapping It Up<a class="hash-link" aria-label="Direct link to Wrapping It Up" title="Direct link to Wrapping It Up" href="https://www.winglang.io/blog/2024/05/16/chatgpt-client-with-nextjs-and-wing#wrapping-it-up">​</a></h2>
<p>As I mentioned earlier, we should all be concerned with our apps security, building your own ChatGPT client and deploying it to your cloud infrastructure gives your app some very good <a href="https://docs.aws.amazon.com/whitepapers/latest/aws-overview/security-and-compliance.html#:~:text=Keep%20Your%20data%20safe%20%E2%80%94%20The,compliance%20programs%20in%20its%20infrastructure." target="_blank" rel="noopener noreferrer">safeguards</a>.</p>
<p>We have demonstrated in this tutorial how <a href="https://git.new/wing-repo" target="_blank" rel="noopener noreferrer">Wing</a> provides a straightforward approach to building scalable cloud applications without worrying about the underlying infrastructure.</p>
<p>If you are interested in building more cool stuff, Wing has an active community of developers, partnering in building a vision for the cloud. We'd love to see you there.</p>
<p>Just head over to our <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">Discord</a> and say hi!</p>]]></content:encoded>
            <author>nathant@wing.cloud (Nathan Tarbert)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>winglang</category>
            <category>platforms</category>
        </item>
        <item>
            <title><![CDATA[In Search for Winglang Middleware]]></title>
            <link>https://www.winglang.io/blog/2024/05/07/in-search-for-winglang-middleware-part-two</link>
            <guid>https://www.winglang.io/blog/2024/05/07/in-search-for-winglang-middleware-part-two</guid>
            <pubDate>Tue, 07 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Winglang middleware]]></description>
            <content:encoded><![CDATA[<div fontsize:="">Part Two: Pipeline Formation with Template Method </div>
<p><img decoding="async" loading="lazy" alt="Asher&amp;#39;s blog cover art" src="https://www.winglang.io/assets/images/ashers-blog-middleware-pt-two-9b977b4f4e39d31d62d9b5fd7fc902e4.jpg" width="1792" height="1024" class="img_ev3q"></p>
<p><a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang's</a> unique capability to uniformly handle both <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">preflight</a> (cloud resource configuration) and <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">inflight</a> (cloud events processing) logic opens up meta-programming possibilities akin to <a href="https://lispcookbook.github.io/cl-cookbook/macros.html" target="_blank" rel="noopener noreferrer">Lisp macros</a>. This allows for the dynamic adjustment of service configurations to various deployment targets—such as DEV, TEST, STAGE, and PROD—at the build stage. By doing so, it optimizes cost, security, and performance without compromising the integrity of the core service logic, which remains largely insulated from middleware framework details. This level of flexibility is unmatched by more traditional cloud middleware libraries, such as <a href="https://github.com/aws-powertools" target="_blank" rel="noopener noreferrer">PowerTools for AWS Lambda</a>, which I explored in the <a href="https://medium.com/itnext/in-search-for-winglang-middleware-9d1be0782108" target="_blank" rel="noopener noreferrer">first part</a> of this series.</p>
<p>In this part, I will explore how a middleware framework can leverage the <a href="https://en.wikipedia.org/wiki/Template_method_pattern" target="_blank" rel="noopener noreferrer">Template Method Design Pattern</a>. This design pattern has proven instrumental in defining the common elements of the <a href="https://en.wikipedia.org/wiki/REST" target="_blank" rel="noopener noreferrer">REST API</a> Create/Retrieve/Update/Delete (CRUD) request handling flow, while still allowing enough flexibility to accommodate the specifics of each request.</p>
<p>Specifically, the application of the <a href="https://en.wikipedia.org/wiki/Template_method_pattern" target="_blank" rel="noopener noreferrer">Template Method Design Pattern</a> to define a common request-handling workflow has demonstrated the following benefits:</p>
<ul>
<li>Unlike <a href="https://en.wikipedia.org/wiki/Decorator_pattern" target="_blank" rel="noopener noreferrer">Decorator</a>, it organically presents post-processing steps of request handling in their natural sequence.</li>
<li>It facilitates the reuse of a common request-handling definition across all functions related to a resource, service, or even across all services developed by the same team or organization.</li>
<li>It enables the specification of multiple configurations optimized for various deployment targets (DEV, TEST, STAGE, PROD), addressing variability at the build stage to eliminate unnecessary overhead and security risks.</li>
</ul>
<p>Nevertheless, this approach has limitations. A high number of deployment targets, services, resources, and function permutations may necessitate maintaining a large number of templates—a common challenge in any <a href="https://platformengineering.org/blog/what-is-platform-engineering" target="_blank" rel="noopener noreferrer">Engineering Platform</a> based on blueprints.</p>
<p>Exploring whether these limitations can be surmounted using <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang's</a> unique capabilities will be the focus of future research.</p>
<p>As clarified in the <a href="https://medium.com/itnext/in-search-for-winglang-middleware-9d1be0782108" target="_blank" rel="noopener noreferrer">previous publication</a>,</p>
<blockquote>
<p><strong>Common middleware services</strong> augment distribution middleware by defining higher-level domain-independent reusable services that allow application developers to concentrate on
programming business logic, without the need to write the “plumbing” code required to develop distributed applications via lower-level middleware directly.</p>
</blockquote>
<p>In our pursuit, we specifically aim to define common service configurations that are adaptable to various development targets. Such configurations are not only reusable across multiple services and resources within the same team or organization but are also distinct enough not to be overgeneralized in the form of a framework but rather to merit integration into a tailored <a href="https://platformengineering.org/blog/what-is-platform-engineering" target="_blank" rel="noopener noreferrer">Engineering Platform</a>. This balance ensures that while the configurations maintain a high level of generality, they remain sufficiently detailed to support the unique needs of different projects within the organization.</p>
<p>Here is an example of how common service configurations can be implemented using <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>.
Typically, this or a similar code snippet will be a part of a larger solution integrated into an organization's or team's <a href="https://platformengineering.org/blog/what-is-platform-engineering" target="_blank" rel="noopener noreferrer">engineering platform</a>:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">//Could be a part of an organization or team engineering platform</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">ServiceFactory</span><span class="token plain"> impl endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IRestApiHandlerTemplate</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _tools</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiTools</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _mode</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub logger</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub api</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">_getLoggingLevel</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mode</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> mode </span><span class="token operator">==</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">PROD</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">INFO</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> elif mode </span><span class="token operator">==</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEV</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TRACE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEBUG</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">_getToolsOptions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        mode</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        logger</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Logger</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiToolsOptions</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> mode </span><span class="token operator">==</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEV</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiToolsOptions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                logger</span><span class="token operator">:</span><span class="token plain"> logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                statusMessage</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// leave original error messages intact</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiToolsOptions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            logger</span><span class="token operator">:</span><span class="token plain"> logger</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// use defaults</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">serviceName</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> mode</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_mode</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">logger</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getLoggingLevel</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            serviceName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tools</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">ApiTools</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getToolsOptions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">api</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">_getProdApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        resource</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        responseFormats</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        getHomePage</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">RestApiBuilder</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> tokenFactory </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">FixedSecretTokenFiltersFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> cookieFactory </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">CookieAuthFiltersFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">tokenFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> apiBuilder </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">RestApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            cookieFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            responseFormats</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> getHomePage </span><span class="token operator">!=</span><span class="token plain"> nil </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">samlLogin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cookieFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> getHomePage</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">_getDevApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        resource</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        responseFormats</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        getHomePage</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">RestApiBuilder</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> session </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            userID</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"test-user"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            fullName</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Test User"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> stubAuth </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">ApiStubAuthFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">session</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> apiBuilder </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">RestApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            stubAuth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            responseFormats</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> getHomePage </span><span class="token operator">!=</span><span class="token plain"> nil </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stubLogin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">session</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> getHomePage</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">_getDefaultApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        resource</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        responseFormats</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        password</span><span class="token operator">:</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">RestApiBuilder</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> basicAuth </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">ApiBasicAuthFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">password</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> apiBuilder </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">RestApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            basicAuth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            responseFormats</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">getApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        resource</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        responseFormats</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        getHomePage</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        password</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token operator">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">RestApiBuilder</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_mode</span><span class="token plain"> </span><span class="token operator">==</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">PROD</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getProdApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                responseFormats</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                getHomePage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> elif </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_mode</span><span class="token plain"> </span><span class="token operator">==</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEV</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getDevApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                responseFormats</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                getHomePage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getDefaultApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                responseFormats</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                password</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">makeRequestHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        functionName</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        proc</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">var</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tools</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">logRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">functionName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                response </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">proc</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> err </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                response </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tools</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">errorResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tools</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">logResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">functionName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            response </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tools</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">responseMessage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This example is quite detailed, so we will break it down section by section to fully understand its structure and functionality.</p>
<p>This module, by convention named <code>middleware.w</code>, features a <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">Winglang preflight</a> class called <code>ServiceFactory</code>. This class encapsulates the following public resources and methods, which are crucial for the middleware's operation:</p>
<ul>
<li><code>api: [cloud.Api](https://www.winglang.io/docs/standard-library/cloud/api)</code>: resource from the <a href="https://www.winglang.io/docs/api/category/cloud" target="_blank" rel="noopener noreferrer">Winglang Standard Library</a></li>
<li><code>logger: logging.Logger</code>: resource, extending the <a href="https://www.winglang.io/docs/libraries" target="_blank" rel="noopener noreferrer">Winglang libraries</a>, which was discussed previously in terms of its utility and possible implementation implementation <a href="https://medium.com/itnext/implementing-production-grade-crud-rest-api-in-winglang-7b8f6917efc2" target="_blank" rel="noopener noreferrer">here</a></li>
<li><code>makeRequestHandler()</code>: <a href="https://en.wikipedia.org/wiki/Factory_method_pattern" target="_blank" rel="noopener noreferrer">Factory Method</a> that applies the <a href="https://en.wikipedia.org/wiki/Template_method_pattern" target="_blank" rel="noopener noreferrer">Template Method Design Pattern</a> tailored to each request handler</li>
<li><code>getApiBuilder()</code>: another <a href="https://en.wikipedia.org/wiki/Factory_method_pattern" target="_blank" rel="noopener noreferrer">Factory Method</a> this time applying the <a href="https://en.wikipedia.org/wiki/Builder_pattern" target="_blank" rel="noopener noreferrer">Builder Design Pattern</a> to configure specific resource API calls</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="makerequesthandler-factory-method">makeRequestHandler() Factory Method<a class="hash-link" aria-label="Direct link to makeRequestHandler() Factory Method" title="Direct link to makeRequestHandler() Factory Method" href="https://www.winglang.io/blog/2024/05/07/in-search-for-winglang-middleware-part-two#makerequesthandler-factory-method">​</a></h2>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">makeRequestHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        functionName</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        proc</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">var</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tools</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">logRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">functionName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                response </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">proc</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> err </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                response </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tools</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">errorResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tools</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">logResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">functionName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            response </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tools</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">responseMessage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This <a href="https://en.wikipedia.org/wiki/Factory_method_pattern" target="_blank" rel="noopener noreferrer">Factory Method</a> plays a central role in implementing the Common Service Middleware. It is a <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">Winglang preflight</a> method that obtains two parameters:</p>
<ul>
<li><code>functionName</code>: The name of the function handling the API request, used for logging purposes.</li>
<li><code>proc</code>: a <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">Winglang inflight</a> function that transforms <code>cloud.ApiRequest</code> into a <code>cloud.ApiResponse</code></li>
</ul>
<p>Internally, it defines a <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">Winglang inflight</a> function, called <code>handler</code> that encapsulates a typical API request processing workflow:</p>
<ol>
<li><strong>Logging the Request</strong>: Initially logs the incoming <code>cloud.ApiRequest</code>.</li>
<li><strong>Processing the Request</strong>: Executes the <code>proc</code> function to obtain a <code>cloud.ApiResponse</code>.</li>
<li><strong>Error Handling</strong>: In the case of an error, it transforms the error into an appropriate <code>cloud.ApiResponse</code>.</li>
<li><strong>Response Logging</strong>: Logs the outgoing <code>cloud.ApiResponse</code>.</li>
<li><strong>Error Message Management</strong>: Modifies the error message in the response based on the configuration to prevent leakage of sensitive information to potential attackers.</li>
</ol>
<p>Operations for logging and error handling are managed using the auxiliary <code>endor.ApiTools</code> class, which we will explore in further detail later.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="getapibuilder-factory-method">getApiBuilder() Factory Method<a class="hash-link" aria-label="Direct link to getApiBuilder() Factory Method" title="Direct link to getApiBuilder() Factory Method" href="https://www.winglang.io/blog/2024/05/07/in-search-for-winglang-middleware-part-two#getapibuilder-factory-method">​</a></h2>
<p>The <code>getApiBuilder()</code> method, another key component implemented as a <a href="https://en.wikipedia.org/wiki/Factory_method_pattern" target="_blank" rel="noopener noreferrer">Factory Method</a>, dynamically creates a properly configured API <a href="https://en.wikipedia.org/wiki/Builder_pattern" target="_blank" rel="noopener noreferrer">Builder</a> for a specific resource, depending on the deployment mode:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token function" style="color:rgb(80, 250, 123)">getApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        resource</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        responseFormats</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        getHomePage</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        password</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token operator">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">RestApiBuilder</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_mode</span><span class="token plain"> </span><span class="token operator">==</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">PROD</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getProdApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                responseFormats</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                getHomePage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> elif </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_mode</span><span class="token plain"> </span><span class="token operator">==</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEV</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getDevApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                responseFormats</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                getHomePage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getDefaultApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                responseFormats</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                password</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">Winglang preflight</a> method accepts four parameters:</p>
<ul>
<li><code>resource</code>: A <a href="https://www.winglang.io/docs/language-reference#31-structs" target="_blank" rel="noopener noreferrer">Winglang Struct</a> defining the API resource, including its names and HTTP paths for singular and plural operations.</li>
<li><code>responseFormats</code>: A <a href="https://www.winglang.io/docs/language-reference#37-arrays" target="_blank" rel="noopener noreferrer">Winglang Array</a> specifying supported response formats, such as <code>application/json</code>, <code>text/html</code>, or <code>text/plain</code>.</li>
<li><code>getHomePage</code>: An optional <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">Winglang inflight</a> function to fetch the home page content using session data and the required format.</li>
<li><code>password</code>: An optional string for temporary use in <a href="https://en.wikipedia.org/wiki/Basic_access_authentication" target="_blank" rel="noopener noreferrer">HTTP Basic Authentication</a>.</li>
</ul>
<p>Based on the <code>_mode</code> field, the method directs the construction of the appropriate builder:</p>
<ul>
<li>It calls <code>_getProdApiBuilder</code> for the <code>PROD</code> mode.</li>
<li>It invokes <code>_getDevApiBuilder</code> for the <code>DEV</code> mode.</li>
<li>It defaults to <code>_getDefaultApiBuilder</code> in other cases.</li>
</ul>
<p>The main variability point that distinguishes these three options is the authentication <a href="https://en.wikipedia.org/wiki/Strategy_pattern" target="_blank" rel="noopener noreferrer">strategy</a> applied to each API request. Let's examine the specifics of each builder's implementation.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="_getprodapibuilder-factory-method">_getProdApiBuilder() Factory Method<a class="hash-link" aria-label="Direct link to _getProdApiBuilder() Factory Method" title="Direct link to _getProdApiBuilder() Factory Method" href="https://www.winglang.io/blog/2024/05/07/in-search-for-winglang-middleware-part-two#_getprodapibuilder-factory-method">​</a></h2>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">_getProdApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        resource</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        responseFormats</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        getHomePage</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">RestApiBuilder</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> tokenFactory </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">FixedSecretTokenFiltersFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> cookieFactory </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">CookieAuthFiltersFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">tokenFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> apiBuilder </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">RestApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            cookieFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            responseFormats</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> getHomePage </span><span class="token operator">!=</span><span class="token plain"> nil </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">samlLogin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cookieFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> getHomePage</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>For production environments, the security of API requests is paramount. This method implements stringent authentication protocols using <a href="https://en.wikipedia.org/wiki/JSON_Web_Token" target="_blank" rel="noopener noreferrer">JSON Web Tokens (JWT)</a> embedded within <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cookie" target="_blank" rel="noopener noreferrer">Cookie HTTP Headers</a>. The JWTs are signed with a fixed random key, a cost-effective measure that maintains robust security for services at this level.</p>
<p>This <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">Winglang preflight</a> method sets up the described security configuration. Additionally, if the <code>getHomePage</code> parameter is not <code>nil</code>, the method configures an extra HTTP request handler for SAML-based authentication, offering another layer of security and user verification (further details on this process can be found <a href="https://medium.com/itnext/implementing-production-grade-crud-rest-api-in-winglang-7b8f6917efc2" target="_blank" rel="noopener noreferrer">here</a>).</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="_getdevapibuilder-factory-method">_getDevApiBuilder() Factory Method<a class="hash-link" aria-label="Direct link to _getDevApiBuilder() Factory Method" title="Direct link to _getDevApiBuilder() Factory Method" href="https://www.winglang.io/blog/2024/05/07/in-search-for-winglang-middleware-part-two#_getdevapibuilder-factory-method">​</a></h2>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">_getDevApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        resource</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        responseFormats</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        getHomePage</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">RestApiBuilder</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> session </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            userID</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"test-user"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            fullName</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Test User"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> stubAuth </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">ApiStubAuthFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">session</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> apiBuilder </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">RestApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            stubAuth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            responseFormats</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> getHomePage </span><span class="token operator">!=</span><span class="token plain"> nil </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stubLogin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">session</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> getHomePage</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>For development purposes, especially when using the <a href="https://www.winglang.io/docs/category/sim" target="_blank" rel="noopener noreferrer">Winglang Simulator</a> in <a href="https://www.winglang.io/docs/tools/wing-console#interact-with-your-wing-application" target="_blank" rel="noopener noreferrer">interactive mode</a>, security requirements can be relaxed. In this mode, authentic security is not required, allowing developers to focus on functionality and flow without the overhead of complex security protocols.</p>
<p>This <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">Winglang preflight</a> method implements such a setup. It uses a stub authentication system based on predefined user session data. Furthermore, if the <code>getHomePage</code> parameter is supplied and not <code>nil</code>, the method adds an HTTP request handler that simulates the login process, maintaining the integrity of the user experience even in a simulated environment.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="_getdefaultapibuilder-factory-method">_getDefaultApiBuilder() Factory Method<a class="hash-link" aria-label="Direct link to _getDefaultApiBuilder() Factory Method" title="Direct link to _getDefaultApiBuilder() Factory Method" href="https://www.winglang.io/blog/2024/05/07/in-search-for-winglang-middleware-part-two#_getdefaultapibuilder-factory-method">​</a></h2>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">_getDefaultApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        resource</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        responseFormats</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        password</span><span class="token operator">:</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">RestApiBuilder</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> basicAuth </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">ApiBasicAuthFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">password</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> apiBuilder </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">RestApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            basicAuth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            responseFormats</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>For test and stage modes, where end-to-end testing is routinely performed, a balance between security, cost-efficiency, and performance is essential. Unlike local simulations that utilize stub authentication similar to the development environment, end-to-end tests in real cloud platforms like AWS require more robust security.</p>
<p>This <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">Winglang preflight</a> method achieves this by implementing <a href="https://en.wikipedia.org/wiki/Basic_access_authentication" target="_blank" rel="noopener noreferrer">HTTP Basic Authentication</a>. It utilizes a dynamically generated password to ensure security while maintaining cost efficiency. The use of <a href="https://en.wikipedia.org/wiki/Basic_access_authentication" target="_blank" rel="noopener noreferrer">HTTP Basic Authentication</a>, where credentials are passed directly in the header, eliminates the need for separate login request handling, streamlining the testing process.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="servicefactory-object-initialization">ServiceFactory Object Initialization<a class="hash-link" aria-label="Direct link to ServiceFactory Object Initialization" title="Direct link to ServiceFactory Object Initialization" href="https://www.winglang.io/blog/2024/05/07/in-search-for-winglang-middleware-part-two#servicefactory-object-initialization">​</a></h2>
<p>Proper initialization of the <code>ServiceFactory</code> object is crucial for the functionality of its public methods and fields. Below is a detailed look into its initialization process:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">//Could be a part of organization or team engineering platform</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">ServiceFactory</span><span class="token plain"> impl endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IRestApiHandlerTemplate</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _tools</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiTools</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _mode</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub logger</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub api</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">_getLoggingLevel</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mode</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> mode </span><span class="token operator">==</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">PROD</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">INFO</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> elif mode </span><span class="token operator">==</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEV</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TRACE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEBUG</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">_getToolsOptions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        mode</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        logger</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Logger</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiToolsOptions</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> mode </span><span class="token operator">==</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEV</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiToolsOptions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                logger</span><span class="token operator">:</span><span class="token plain"> logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                statusMessage</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// leave original error messages intact</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiToolsOptions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            logger</span><span class="token operator">:</span><span class="token plain"> logger</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// use defaults</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">serviceName</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> mode</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_mode</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">logger</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getLoggingLevel</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            serviceName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tools</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">ApiTools</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getToolsOptions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">api</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>new()</code> constructor method is designed to take two parameters:</p>
<ul>
<li><code>serviceName</code>: Utilized in all log messages to identify service-specific operations.</li>
<li><code>mode</code>: Determines the appropriate configuration settings for different operational environments.</li>
</ul>
<p>The initialization sequence performs the following steps:</p>
<ol>
<li><strong>Mode Configuration</strong>: Stores the <code>mode</code> to dictate the behavior of the <code>getApiBuilder()</code> method.</li>
<li><strong>Logger Initialization</strong>: Creates a <code>Logger</code> object with a logging level based on <code>mode</code>:
<ul>
<li><strong>INFO</strong> for PROD for streamlined logging.</li>
<li><strong>TRACE</strong> for DEV to enable detailed debugging.</li>
<li><strong>DEBUG</strong> for other environments to balance detail and performance.</li>
</ul>
</li>
<li><strong>ApiTools Configuration</strong>: Establishes an <code>endor.ApiTools</code> object with settings influenced by <code>mode</code>:
<ul>
<li>Retains original error messages in DEV mode to aid in debugging.</li>
<li>Replaces error messages with standard HTTP response text in other modes to safeguard against potential security risks.</li>
</ul>
</li>
</ol>
<p>This <code>ServiceFactory</code> class, by implementing the <code>endor.IRestApiHandlerTemplate</code> interface, seamlessly integrates with the <code>endor.RestApiBuilder</code>. This allows the latter to utilize the <code>makeRequestHandler()</code> method of <code>ServiceFactory</code>, thus ensuring consistent handling of all API requests.</p>
<h1>TodoService</h1>
<p>The common middleware service configuration described previously hides a substantial portion of the system infrastructure complexity, allowing specific service configurations to be defined with ease and precision. A practical implementation of this approach can be seen in the <code>TodoService</code>, first introduced in the <a href="https://medium.com/itnext/implementing-production-grade-crud-rest-api-in-winglang-7b8f6917efc2" target="_blank" rel="noopener noreferrer">previous publication</a>:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./core"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./adapters"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> adapters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./middleware.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> middleware</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">TodoService</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _api</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">//TODO: true content negotiation; unit test?; move to adapters??</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">_getResponseFormatters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		    mode</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		    resource</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResource</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ITodoFormatter</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> mode </span><span class="token operator">==</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TEST</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ITodoFormatter</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"application/json"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">adapters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">TodoJsonFormatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ITodoFormatter</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"text/html"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">adapters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">TodoHtmlFormatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">htmlPath</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"text/plain"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">adapters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">TodoTextFormatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mode</span><span class="token operator">:</span><span class="token plain"> endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> password</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> serviceName </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Todo Service"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> factory </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">middleware</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">ServiceFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">serviceName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> resource </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">endor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">ApiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Task"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> responseFormatters </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_getResponseFormatters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> repository </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">adapters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">TaskTableRepository</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">factory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">TodoHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            repository</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            responseFormatters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            factory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">logger</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> apiBuilder </span><span class="token operator">=</span><span class="token plain"> factory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getApiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            mode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            responseFormatters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">keys</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getHomePage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            password</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">retrieveResources</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getAllTasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">createResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">createTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">replaceResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">replaceTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        apiBuilder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">deleteResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">deleteTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_api</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> factory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">getUrl</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>TodoService</code> class serves as a <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">Winglang preflight</a> entity that orchestrates the integration of the service core, its adapters, and middleware. It includes a public <code>getUrl()</code> method for testing purposes.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="service-initialization">Service Initialization<a class="hash-link" aria-label="Direct link to Service Initialization" title="Direct link to Service Initialization" href="https://www.winglang.io/blog/2024/05/07/in-search-for-winglang-middleware-part-two#service-initialization">​</a></h2>
<p>The <code>new()</code> constructor method takes two parameters:</p>
<ul>
<li><code>mode</code>: Determines the output format selection and middleware configuration.</li>
<li><code>password</code>: An optional string for <a href="https://en.wikipedia.org/wiki/Basic_access_authentication" target="_blank" rel="noopener noreferrer">HTTP Basic Authentication</a> in scenarios requiring secure access.</li>
</ul>
<p>The service is initialized through the following steps:</p>
<ol>
<li><strong>Middleware Configuration</strong>: Initializes a <code>ServiceFactory</code> with <code>serviceName</code> and <code>mode</code>.</li>
<li><strong>Resource Descriptor</strong>: Sets up a <code>Task</code> resource descriptor that translates to the <code>/tasks</code> HTTP path.</li>
<li><strong>Response Formatter Configuration</strong>: Depending on the <code>mode</code>, it configures response formatters:
<ul>
<li><code>application/json</code> for TEST mode.</li>
<li><code>text/html</code> and <code>text/plain</code> for PROD and DEV modes.</li>
</ul>
</li>
<li><strong>Repository Creation</strong>: Establishes a Tasks repository using a DynamoDB backend.</li>
<li><strong>Handler Setup</strong>: Configures a <code>core.TodoHandler</code> with necessary dependencies, including a logger from <code>ServiceFactory</code>.</li>
<li><strong>API Builder Setup</strong>: Uses <code>ServiceFactory.getApiBuilder()</code> to link <code>TodoHandler</code> methods to respective REST API endpoints.</li>
<li><strong>REST API Wiring:</strong> Connects <code>TodoHandler</code> methods to the corresponding <a href="https://en.wikipedia.org/wiki/REST" target="_blank" rel="noopener noreferrer">REST API</a> calls.</li>
<li><strong>API Object Storage</strong>: Retains the <code>cloud.Api</code> object to handle URL retrieval via <code>getUrl()</code>.</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="configurations">Configurations<a class="hash-link" aria-label="Direct link to Configurations" title="Direct link to Configurations" href="https://www.winglang.io/blog/2024/05/07/in-search-for-winglang-middleware-part-two#configurations">​</a></h2>
<p>This <code>TodoService</code> can be instantiated with different target modes and optionally a random password, resulting in three primary configurations for various environments:</p>
<ol>
<li><strong>Production</strong>: <code>let _service = new service.TodoService(endor.Mode.PROD);</code></li>
<li><strong>Development</strong>: <code>let _service = new service.TodoService(endor.Mode.DEV);</code></li>
<li><strong>Testing</strong>: <code>let _service = new service.TodoService(endor.Mode.TEST, _password);</code></li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="design-diagram">Design Diagram<a class="hash-link" aria-label="Direct link to Design Diagram" title="Direct link to Design Diagram" href="https://www.winglang.io/blog/2024/05/07/in-search-for-winglang-middleware-part-two#design-diagram">​</a></h2>
<p>While detailed code snippets and textual descriptions provide precise insight into design decisions, they often fall short of conveying a holistic view. For a broader perspective, visual representations are invaluable, especially when dealing with concepts as abstract as <a href="https://en.wikipedia.org/wiki/Higher-order_programming" target="_blank" rel="noopener noreferrer">higher-order programming</a> utilized by <a href="https://www.winglang.io/docs/concepts/inflights" target="_blank" rel="noopener noreferrer">Winglang's preflight/inflight</a> mechanisms. This section aims to bridge this understanding gap through graphical illustrations.</p>
<p>To visualize core system components and their relationships a <a href="https://en.wikipedia.org/wiki/Class_diagram" target="_blank" rel="noopener noreferrer">UML Class diagram</a> is a suitable tool:</p>
<p><img decoding="async" loading="lazy" alt="Design Pattern 1" src="https://www.winglang.io/assets/images/ServiceFactory-dce763f3b5ad85e05f83a34ddd8eee48.jpg" width="960" height="540" class="img_ev3q"></p>
<p>In this diagram, solid arrows indicate permanent references, dashed arrows depict temporal interactions, and diamond-ended lines show component aggregations. This static representation helps delineate how components are interconnected during the <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">preflight</a> phase.</p>
<p>However, to visualize what happens dynamically at the <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">inflight</a> stage, a more specialized notation is necessary. Traditional UML <a href="https://en.wikipedia.org/wiki/Communication_diagram" target="_blank" rel="noopener noreferrer">communication</a> and <a href="https://en.wikipedia.org/wiki/Sequence_diagram" target="_blank" rel="noopener noreferrer">sequence</a> diagrams were found inadequate, prompting the creation of a custom notation specifically designed for this purpose.</p>
<p>Illustrated below is the <code>createTask</code> with <a href="https://en.wikipedia.org/wiki/Basic_access_authentication" target="_blank" rel="noopener noreferrer">HTTP Basic Authentication</a> scenario:</p>
<p><img decoding="async" loading="lazy" alt="Design Pattern 2" src="https://www.winglang.io/assets/images/Inflight_API%20Request_Handling_Call_Tree-b17304fb313662e2743b0adae9c57290.jpg" width="960" height="540" class="img_ev3q">
In this diagram:</p>
<ul>
<li>Circles with transparent backgrounds represent individual functional steps.</li>
<li>Circles with grey backgrounds denote <a href="https://en.wikipedia.org/wiki/Template_method_pattern" target="_blank" rel="noopener noreferrer">template method</a> plug-in function sockets.</li>
<li>Rounded rectangles indicate top-level functions.</li>
<li>Dashed arrows symbolize standard function calls, while solid arrows indicate indirect function calls via function references.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="interpretation-of-the-diagram">Interpretation of the Diagram<a class="hash-link" aria-label="Direct link to Interpretation of the Diagram" title="Direct link to Interpretation of the Diagram" href="https://www.winglang.io/blog/2024/05/07/in-search-for-winglang-middleware-part-two#interpretation-of-the-diagram">​</a></h2>
<ol>
<li>An incoming HTTP POST request is received by the cloud resource (e.g., <a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html" target="_blank" rel="noopener noreferrer">AWS API Gateway</a>), which uses the <a href="https://www.winglang.io/docs/standard-library/cloud/api" target="_blank" rel="noopener noreferrer">Winglang <code>cloud.Api</code></a> to convert it into a <code>cloud.ApiRequest</code> and invokes the appropriate <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">inflight</a> function, typically specified within the <code>RestApiHandlerTemplate</code> (here, implemented by <code>ServiceFactory</code>).</li>
<li>The api request handling process begins within a <code>try</code> block, where the <code>logRequest</code> function from <code>ApiTools</code> logs the request, and the plugged-in function (<code>createResource</code> from <code>RestApiBuilder</code>) processes the request. Upon error, <code>errorResponse</code> from <code>ApiTools</code> converts exceptions into <code>cloud.ApiResponse</code>. Regardless of the outcome, <code>logResponse</code> and <code>responseMessage</code> from <code>ApiTools</code> are invoked to finalize the processing.</li>
<li>The <code>createResource</code> function within <code>RestApiBuilder</code> initiates authentication via a plugged-in <code>auth</code> function (provided by <code>BasicAuthFactory</code>), which extracts user data and passes control to <code>createResource</code> of <code>RestApiFactory</code>.</li>
<li>Finally, <code>createResource</code> in <code>RestApiFactory</code> parses HTTP headers and body data and calls the <code>createTask</code> function provided by <code>TodoHandler</code>, which handles the core business logic.</li>
</ol>
<p>This dynamic interaction is indeed complex, highlighting the intricate and interconnected nature of the system. The proposed middleware design aims to shield users from this complexity in daily operations. However, when issues arise, creating a precise graphical representation of the underlying system dynamics becomes essential. Future research will likely focus on developing tools to maintain cognitive control over such complex systems, ensuring that developers can effectively manage and troubleshoot without being overwhelmed.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="todo-service-core">Todo Service Core<a class="hash-link" aria-label="Direct link to Todo Service Core" title="Direct link to Todo Service Core" href="https://www.winglang.io/blog/2024/05/07/in-search-for-winglang-middleware-part-two#todo-service-core">​</a></h2>
<p>The architecture adopted allows the service core to remain independent of any middleware framework, focusing on core functionality without being tangled in middleware specifics. An example of this is the <code>core.TodoHandler</code> class:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./task.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> task</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./parser.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./formatter.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Experimental implementation of</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// "Preflight Object Oriented, Inflight Functional"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Design Pattern</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">TodoHandler</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _tasks</span><span class="token operator">:</span><span class="token plain"> task</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ITaskDataRepository</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _parser</span><span class="token operator">:</span><span class="token plain"> parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">TodoParser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _formatter</span><span class="token operator">:</span><span class="token plain"> formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">TodoFormattingRouter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _logger</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        tasks_</span><span class="token operator">:</span><span class="token plain"> task</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ITaskDataRepository</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        formatters</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ITodoFormatter</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        logger</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Logger</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tasks</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> tasks_</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_parser</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">TodoParser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_formatter</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">TodoFormattingRouter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">formatters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_logger</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">getHomePage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> outFormat</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> userData </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parseUserData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">formatHomePage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">outFormat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> userData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">getAllTasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            user</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            query</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            outFormat</span><span class="token operator">:</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> userData </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parseUserData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token comment" style="color:rgb(98, 114, 164)">//TBD: should it get userData instead?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> tasks </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getTasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">userData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">userID</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">formatTasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">outFormat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">createTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            user</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            taskAttributes</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            outFormat</span><span class="token operator">:</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> taskData </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parsePartialTaskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                taskAttributes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">addTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">taskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token comment" style="color:rgb(98, 114, 164)">//TBD: cloud events?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">info</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"createTask"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">userID</span><span class="token operator">:</span><span class="token plain"> taskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">userID</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> taskID</span><span class="token operator">:</span><span class="token plain">taskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">taskID</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">formatTasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">outFormat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">taskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">replaceTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            user</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            id</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            taskAttributes</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            outFormat</span><span class="token operator">:</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> taskData </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parseFullTaskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                taskAttributes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">replaceTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">taskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token comment" style="color:rgb(98, 114, 164)">//TBD: cloud events?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">info</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"replaceTask"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">userID</span><span class="token operator">:</span><span class="token plain"> taskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">userID</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> taskID</span><span class="token operator">:</span><span class="token plain">taskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">taskID</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">formatTasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">outFormat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">taskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">deleteTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> id</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> userData </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parseUserData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> taskID </span><span class="token operator">=</span><span class="token plain"> num</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token comment" style="color:rgb(98, 114, 164)">//TBD: taskKey? userData?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">deleteTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">userData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">userID</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> taskID</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token comment" style="color:rgb(98, 114, 164)">//TBD: cloud events?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">info</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"deleteTask"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">userID</span><span class="token operator">:</span><span class="token plain"> userData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">userID</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> taskID</span><span class="token operator">:</span><span class="token plain">taskID</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">//TBD: formatter?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>core.TodoHandler</code> is designed as a <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">Winglang preflight</a> class that encapsulates key functionalities for Todo Service operations. Each method in this class exemplifies a <a href="https://en.wikipedia.org/wiki/Factory_method_pattern" target="_blank" rel="noopener noreferrer">Factory Method</a>, returning specialized <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">inflight</a> functions that handle specific aspects of Todo management.</p>
<p>The only implicit coupling between the core of the Todo Service and its middleware lies in the parameters passed to each function. This level of coupling, referred to as <a href="https://www.amazon.com/Balancing-Coupling-Software-Design-Addison-Wesley-ebook/dp/B09RV3Z3TP" target="_blank" rel="noopener noreferrer">Knowledge Sharing</a>, is a trade-off typically considered acceptable in such architectural designs, facilitating seamless integration while maintaining a clear separation of concerns.</p>
<p>Interestingly enough, introducing <a href="https://www.typescriptlang.org/docs/handbook/2/generics.html" target="_blank" rel="noopener noreferrer">Generics</a> support in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> could potentially increase rather than decrease system coupling. With Generics, the coordination between the core and middleware layers would extend beyond just the order and types of parameters. It would also necessitate sharing the names of functions and their parameters, thereby tightening the interdependence within the system.</p>
<p>The following <a href="https://en.wikipedia.org/wiki/Class_diagram" target="_blank" rel="noopener noreferrer">UML class diagram</a> summarizes the Todo Service logic design in visual form:</p>
<p><img decoding="async" loading="lazy" alt="ToDo Service" src="https://www.winglang.io/assets/images/TodoService-e00c5718ced935e678fb20f799bdadfb.jpg" width="960" height="540" class="img_ev3q"></p>
<p>A detailed description of this design is presented in <a href="https://medium.com/itnext/implementing-production-grade-crud-rest-api-in-winglang-7b8f6917efc2" target="_blank" rel="noopener noreferrer">a previous publication</a>.</p>
<h1>Endor Middleware Framework</h1>
<p>The <code>ServiceFactory</code> class, detailed earlier, relies on the <code>Endor</code> middleware framework—an experimental library designed to push the boundaries of what is possible with <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>, a new cloud-oriented programming language.</p>
<p>The name "<a href="https://www.elfdict.com/w/endor" target="_blank" rel="noopener noreferrer">Endor</a>", derived from <a href="https://en.wikipedia.org/wiki/Quenya" target="_blank" rel="noopener noreferrer">Quenya</a>—a functional language <a href="https://en.wikipedia.org/wiki/Languages_constructed_by_J._R._R._Tolkien" target="_blank" rel="noopener noreferrer">created by J.R.R. Tolkien</a> for the Elves in his <a href="https://en.wikipedia.org/wiki/Middle-earth" target="_blank" rel="noopener noreferrer">Middle-earth fiction</a>—translates to "Middle-earth." This nomenclature not only signifies 'middle' but also metaphorically represents our exploration into <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang's</a> unleashed yet potential, positioning it as a pioneering language at the crossroads of established practices and innovative paradigms.</p>
<p>In its current iteration, the <code>Endor</code> middleware framework encapsulates an initial set of functionalities for HTTP request handling, including various authentication methods. While a comprehensive review of the entire framework is outside the scope of this publication, we will briefly explore the <code>Endor.ApiBuilder</code> class implementation, which plays a crucial role in integrating application-specific handlers into a common request processing infrastructure:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./apiStubAuth.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> apiStubAuth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./apiResource.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> apiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./apiAuthFactory.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> authFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./restApiFactory.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> restApiFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./cookieAuthFilters.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> cookieFilters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">interface</span><span class="token plain"> </span><span class="token class-name">IRestApiHandlerTemplate</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">makeRequestHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        functionName</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        proc</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">RestApiBuilder</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _resource</span><span class="token operator">:</span><span class="token plain"> apiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _template</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">IRestApiHandlerTemplate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _factory</span><span class="token operator">:</span><span class="token plain"> restApiFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">RestApiFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _auth</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _api</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        api</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        resource</span><span class="token operator">:</span><span class="token plain"> apiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        template</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">IRestApiHandlerTemplate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        authFactory</span><span class="token operator">:</span><span class="token plain"> authFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IApiAuthFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        responseFormats</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_resource</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_template</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> template</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_factory</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">restApiFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">RestApiFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">responseFormats</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_auth</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> authFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getAuth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_api</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">_makeAuthRequestHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        functionName</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        proc</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> userData </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_auth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">proc</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">userData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_template</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">makeRequestHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">functionName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">samlLogin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        cookieFactory</span><span class="token operator">:</span><span class="token plain"> cookieFilters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">CookieAuthFiltersFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        getHomePage</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">post</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"/sp/acs"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_template</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">makeRequestHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"login"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_factory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">samlLogin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cookieFactory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> getHomePage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">stubLogin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        session</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        getHomePage</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"/"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_template</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">makeRequestHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"login"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_factory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stubLogin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">session</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> getHomePage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">retrieveResources</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        handler</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_makeAuthRequestHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"get{this._resource.plural}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_factory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">retrieveResources</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    handler</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">createResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        handler</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">post</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_makeAuthRequestHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"create{this._resource.singular}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_factory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">createResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    handler</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">replaceResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        handler</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">put</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">idPath</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_makeAuthRequestHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"replace{this._resource.singular}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_factory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">replaceResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    handler</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">deleteResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        handler</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">delete</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_resource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">idPath</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">_makeAuthRequestHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"delete{this._resource.singular}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_factory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">deleteResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    handler</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">//TODO: other operations: partial update (patch), has (head), delete all, update all</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>RestApiBuilder</code> class is designed to wrap application-specific handlers, such as <code>createTask()</code>, within a standardized cloud API request-response conversion process, seamlessly incorporating specified authentication methods. The conversion from <code>cloud.ApiRequest</code> to <code>cloud.ApiResponse</code> is further handled by the <code>endor.RestApiFactory</code>, whose details are not covered in this publication.</p>
<p>The <code>endor.ApiTools</code> class, another significant component of the framework, provides a suite of middleware operations:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring exception</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub struct </span><span class="token maybe-class-name">ApiToolsOptions</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    logger</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    logLevel</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    statusMessage</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    statusLogging</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token operator">&gt;</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">//TODO: unit test</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">ApiTools</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _logger</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _logLevel</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _errorStatus</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">num</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _statusMessage</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _statusLogging</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        options</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">ApiToolsOptions</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_logger</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> options</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_logLevel</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> options</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">logLevel</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEBUG</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_errorStatus</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">num</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"ValueError"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token number">400</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"AuthenticationError"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token number">401</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"AuthorizationError"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token number">403</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"KeyError"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token number">404</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"InternalError"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token number">500</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"NotImplementedError"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token number">501</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_statusMessage</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> options</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">statusMessage</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"400"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Bad Request"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"401"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Unauthorized"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"403"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Forbidden"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"404"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Not Found"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"500"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Internal Server Error"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"501"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Not Implemented"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_statusLogging</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> options</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">statusLogging</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"200"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEBUG</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"400"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">WARNING</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"401"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">WARNING</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"403"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">WARNING</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"404"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">WARNING</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"500"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">ERROR</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"501"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">ERROR</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">logRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">functionName</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_logLevel</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            functionName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                request</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">logResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">functionName</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> logLevel </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_statusLogging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryGet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{response.status!}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                logLevel</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                functionName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    response</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">errorResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> error </span><span class="token operator">=</span><span class="token plain"> exception</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryParse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> status </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_errorStatus</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryGet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">tag</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    status</span><span class="token operator">:</span><span class="token plain"> status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                        </span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"text/plain"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    body</span><span class="token operator">:</span><span class="token plain"> error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">message</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">500</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"text/plain"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            body</span><span class="token operator">:</span><span class="token plain"> err</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">responseMessage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">response</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> message </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_statusMessage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryGet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{response.status!}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                status</span><span class="token operator">:</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                headers</span><span class="token operator">:</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">headers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                body</span><span class="token operator">:</span><span class="token plain"> message</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This class offers essential functionalities for logging requests and responses, handling errors, and modifying response messages based on the status codes, thereby standardizing the error handling and logging processes across all middleware services.</p>
<p>The following <a href="https://en.wikipedia.org/wiki/Class_diagram" target="_blank" rel="noopener noreferrer">UML class diagram</a> summarizes the <code>endor</code> middleware framework design in visual form:</p>
<p><img decoding="async" loading="lazy" alt="Service Factory" src="https://www.winglang.io/assets/images/ServiceFactory-dce763f3b5ad85e05f83a34ddd8eee48.jpg" width="960" height="540" class="img_ev3q"></p>
<h1>Middleware Service Layers</h1>
<p>Finally, let us synthesize the components discussed throughout this series and identify some common patterns that have emerged. Below, we visualize how these elements interact:</p>
<p><img decoding="async" loading="lazy" alt="Middleware Layer Revised" src="https://www.winglang.io/assets/images/Winglang%20Middleware%20Layer%20Revised-f0d6fcd3efe2345da947f12acb1934ae.jpg" width="960" height="540" class="img_ev3q"></p>
<p>At the top of this structure is located the <code>TodoService</code> which pulls together three critical elements:</p>
<ol>
<li><strong>The Service Core</strong> - Defines the fundamental service logic independent of specific communication and storage implementations:
<ul>
<li><strong>Domain Entities</strong> like Task and User.</li>
<li><strong>Domain Entity Factory</strong> - Constructs domain-specific data, such as assigning unique IDs to tasks.</li>
<li><strong>Parser</strong> - Transforms JSON into domain-specific data structures.</li>
<li><strong>Formatter</strong> - An abstract interface for converting domain data into required formats (e.g., HTML).</li>
<li><strong>Repository</strong> - An abstract interface for domain data storage.</li>
<li><strong>Handler</strong> - Integrates core components to manage specific API requests.</li>
</ul>
</li>
<li><strong>The Service Adapters</strong> - Implements specific interfaces for the Formatter and Repository. Examples include:
<ul>
<li><strong>HTML Formatter</strong></li>
<li><strong>JSON Formatter</strong></li>
<li><strong>Plain Text Formatter</strong></li>
<li><strong>Task Repository</strong> using DynamoDB.</li>
</ul>
</li>
<li><strong>The Platform Middleware</strong> - Contains the <code>ServiceFactory</code> class, crucial for implementing a standardized request-handling workflow.</li>
</ol>
<p>The <code>endor</code> Middleware Framework provides foundational building blocks for composing request handling workflows, utilizing core <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> libraries like <code>logging</code> and <code>exception</code> for enhanced functionality.</p>
<h1>Conclusions</h1>
<p>The application of the <a href="https://en.wikipedia.org/wiki/Template_method_pattern" target="_blank" rel="noopener noreferrer">Template Method Design Pattern</a> to define a common request-handling workflow has demonstrated significant flexibility and utility, surpassing mainstream solutions such as <a href="https://github.com/aws-powertools" target="_blank" rel="noopener noreferrer">PowerTools for AWS Lambda</a>:</p>
<ul>
<li>It organically presents post-processing steps of request handling in their natural sequence.</li>
<li>It facilitates the reuse of a common request-handling definition across all functions related to a resource, service, or even across all services developed by the same team or organization.</li>
<li>It enables the specification of multiple configurations optimized for various deployment targets (DEV, TEST, STAGE, PROD), addressing variability at the build stage to eliminate unnecessary overhead and security risks.</li>
</ul>
<p>Nevertheless, this approach has limitations. A high number of deployment targets, services, resources, and function permutations may necessitate maintaining a large number of templates—a common challenge in any <a href="https://platformengineering.org/blog/what-is-platform-engineering" target="_blank" rel="noopener noreferrer">Engineering Platform</a> based on blueprints.</p>
<p>Exploring whether these limitations can be surmounted using <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang's</a> unique capabilities will be the focus of future research. Stay tuned for further developments.</p>
<h1>Acknowledgments</h1>
<p>Throughout the preparation of this publication, I utilized several key tools to enhance the draft and ensure its quality.</p>
<p>The initial draft was crafted with the organizational capabilities of <a href="https://www.notion.so/" target="_blank" rel="noopener noreferrer">Notion</a>'s free subscription, facilitating the structuring and development of ideas.</p>
<p>For grammar and spelling review, the free version of <a href="https://app.grammarly.com/" target="_blank" rel="noopener noreferrer">Grammarly</a> proved useful for identifying and correcting basic errors, ensuring the readability of the text.</p>
<p>The enhancement of stylistic expression and the narrative coherence checks were performed using the paid version of <a href="https://openai.com/gpt-4" target="_blank" rel="noopener noreferrer">ChatGPT 4.0</a>.</p>
<p>While these advanced tools and resources significantly contributed to the preparation process, the concepts, solutions, and final decisions presented in this article are entirely my own, for which I bear full responsibility.</p>]]></content:encoded>
            <author>asher.sterkin@gmail.com (Asher Sterkin)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>middleware</category>
            <category>platforms</category>
        </item>
        <item>
            <title><![CDATA[Inflight Magazine no. 9]]></title>
            <link>https://www.winglang.io/blog/2024/04/19/magazine-009</link>
            <guid>https://www.winglang.io/blog/2024/04/19/magazine-009</guid>
            <pubDate>Fri, 19 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Updates from the Wing project]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>The 9th issue of the Wing Inflight Magazine.</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="Cover Art" src="https://www.winglang.io/assets/images/inflight-9-banner-f35bb9883d6d9f61cbbec16a5f99f6c1.png" width="1792" height="1024" class="img_ev3q"></p>
<p>Howdy Wingnuts!</p>
<p>I am pleased to share another issue of the <em>Wing Inflight Magazine</em> with recent updates and news
from the <a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">Winglang</a> project.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="so-what-is-wing-again">So what is Wing again?<a class="hash-link" aria-label="Direct link to So what is Wing again?" title="Direct link to So what is Wing again?" href="https://www.winglang.io/blog/2024/04/19/magazine-009#so-what-is-wing-again">​</a></h3>
<p>Wing is a new programming environment for the cloud. It makes it easy for developers to build and
test distributed systems that leverage a variety of powerful cloud primitives such as queues,
topics, API endpoints, buckets, websites, topics and a growing ecosystem of
<a href="https://github.com/winglang/winglibs" target="_blank" rel="noopener noreferrer">winglibs</a>.</p>
<p>Wing comes with a <em>visual cloud simulator</em> which can be used to interact and test complete cloud
applications on your local machine, with fast hot reloading and without having to deploy a single
resource to the cloud.</p>
<p>One of the unique capabilities of Wing is that it supports what we call <strong>pluggable platform
providers</strong>. This means that applications can be <em>cloud- and provisioning-engine agnostic</em>, so they
can be deployed to multiple cloud providers using multiple provisioning engines.</p>
<p>There is already support for Terraform/OpenTofu, CloudFormation, AWS, GCP and Azure, and discussions
about <a href="https://github.com/winglang/wing/issues/4298" target="_blank" rel="noopener noreferrer">Cloudflare</a>,
<a href="https://github.com/winglang/wing/issues/6268" target="_blank" rel="noopener noreferrer">Crossplane</a>,
<a href="https://github.com/winglang/wing/issues/6272" target="_blank" rel="noopener noreferrer">Pulumi</a>,
<a href="https://github.com/winglang/wing/issues/6273" target="_blank" rel="noopener noreferrer">OpenShift</a>, <a href="https://github.com/winglang/wing/issues/6271" target="_blank" rel="noopener noreferrer">Azure
Bicep</a>. Check out the <a href="https://www.winglang.io/docs/api/standard-library/compatibility-matrix" target="_blank" rel="noopener noreferrer">compatibility
matrix</a>, add your 👍 to the
relevant issue, and share your use case to help us prioritize!</p>
<p>Platform teams can also create their own custom platforms using CDK constructs. This offers central
control over best practices, compliance policies, security, deployment strategies and any other
aspect of how Wing applications are implemented in an organization's cloud environment.</p>
<p><strong>Wing is still in active development</strong>, but we are starting to see some really cool stuff being
built with it. If you are up for a really fun (yet possibly bumpy) ride, we encourage you to <a href="https://www.winglang.io/docs" target="_blank" rel="noopener noreferrer">take
Wing for a spin on your local machine</a> or in the Wing
Playground and <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">let us know</a> what you
think.</p>
<p>We are designing Wing to be <strong>familiar and friendly</strong> for developers who come from modern
object-oriented background such as TypeScript, Swift, C# and Java, so it will take you <a href="https://github.com/winglang/workshop-react/blob/main/cheatsheet.md" target="_blank" rel="noopener noreferrer">5
minutes</a> to learn.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="in-todays-issue">In today's issue<a class="hash-link" aria-label="Direct link to In today's issue" title="Direct link to In today's issue" href="https://www.winglang.io/blog/2024/04/19/magazine-009#in-todays-issue">​</a></h3>
<ul>
<li>🐛 <a href="https://www.winglang.io/blog/2024/04/19/magazine-009#debugging-with-breakpoints">Debugging with breakpoints</a></li>
<li>📊 <a href="https://www.winglang.io/blog/2024/04/19/magazine-009#local-simulation-of-serverless-function-concurrency">Local simulation of serverless function concurrency</a></li>
<li>💁 <a href="https://www.winglang.io/blog/2024/04/19/magazine-009#a-new-project-template-for-react-with-vite">A new project template for React with Vite</a></li>
<li>🔘 <a href="https://www.winglang.io/blog/2024/04/19/magazine-009#adding-ui-to-wing-classes-through-bring-ui">Adding UI to Wing classes through <code>bring ui</code></a></li>
<li>🪝 <a href="https://www.winglang.io/blog/2024/04/19/magazine-009#exposing-cloud-endpoints-for-webhook-development">Exposing cloud endpoints for webhook development</a></li>
<li>🏋️‍♀️ <a href="https://www.winglang.io/blog/2024/04/19/magazine-009#explicit-lifting-of-preflight-objects">Explicit lifting of preflight objects</a></li>
<li>🤞 <a href="https://www.winglang.io/blog/2024/04/19/magazine-009#changes-to-default-object-identifiers">Changes to default object identifiers</a></li>
<li>💼 <a href="https://www.winglang.io/blog/2024/04/19/magazine-009#implicitly-loaded-platform-extensions">Implicitly loaded platform extensions</a></li>
<li>🕑 <a href="https://www.winglang.io/blog/2024/04/19/magazine-009#standardize-cron-expressions">Standardize cron expressions</a></li>
<li>🎥 <a href="https://www.winglang.io/blog/2024/04/19/magazine-009#goodies-from-the-wingly-update">Goodies from the Wingly Update</a></li>
<li>🦁 <a href="https://www.winglang.io/blog/2024/04/19/magazine-009#wing-in-the-wild">Wing in the Wild</a></li>
<li>👯‍♂️ <a href="https://www.winglang.io/blog/2024/04/19/magazine-009#community-events">Community Events</a></li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="debugging-with-breakpoints">Debugging with breakpoints<a class="hash-link" aria-label="Direct link to Debugging with breakpoints" title="Direct link to Debugging with breakpoints" href="https://www.winglang.io/blog/2024/04/19/magazine-009#debugging-with-breakpoints">​</a></h3>
<p>It is now possible to set breakpoints and fully debug your Wing applications!</p>
<p>The Wing VS Code extension, breakpoints can be added to <code>.w</code> files, both for preflight and inflight
code and simply hit F5 to debug. The built-in debugger can now be used to inspect and step through
the code.</p>
<p><img decoding="async" loading="lazy" alt="debugging" src="https://www.winglang.io/assets/images/mag-009-debugging-db73c72c9693cd30cf961a22e67a998a.png" width="721" height="407" class="img_ev3q"></p>
<blockquote>
<p><a href="https://github.com/winglang/wing/pull/5981" target="_blank" rel="noopener noreferrer">See PR by Mark</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="local-simulation-of-serverless-function-concurrency">Local simulation of serverless function concurrency<a class="hash-link" aria-label="Direct link to Local simulation of serverless function concurrency" title="Direct link to Local simulation of serverless function concurrency" href="https://www.winglang.io/blog/2024/04/19/magazine-009#local-simulation-of-serverless-function-concurrency">​</a></h3>
<p>We've made improvements to how <code>cloud.Function</code>s are executed in the Wing Simulator so they
functionally behave like FaaS providers. We are now running each function within an isolated child
process and manage it's concurrency limits.</p>
<p><img decoding="async" loading="lazy" src="https://www.winglang.io/assets/images/mag-009-concurrency-18561acc887e1f217c669f90042d7daf.png" width="1352" height="512" class="img_ev3q"></p>
<p>The <code>concurrency</code> option that can be passed to <code>cloud.Function</code> or any resource that takes an
inflight closure can be used to control these limits.</p>
<p>For example:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring util</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> queue </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Queue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">x</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"only one at a time: {x}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">queue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">setConsumer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token literal-property property">concurrency</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">//                         ^^^^^^^^^^^^^^</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"push 10"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> i </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> </span><span class="token number">0.</span><span class="token number">.10</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> queue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">push</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{i}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  util</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">waitUntil</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> queue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">approxSize</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">==</span><span class="token plain"> </span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ul>
<li>When running this with <code>concurrency: 1</code>, the code finishes after ~1.5s</li>
<li>When running with <code>concurrency: 10</code>, the code finishes after 0.5s</li>
</ul>
<blockquote>
<p><a href="https://github.com/winglang/wing/pull/5867" target="_blank" rel="noopener noreferrer">See PR by Chris</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="a-new-project-template-for-react-with-vite">A new project template for React with Vite<a class="hash-link" aria-label="Direct link to A new project template for React with Vite" title="Direct link to A new project template for React with Vite" href="https://www.winglang.io/blog/2024/04/19/magazine-009#a-new-project-template-for-react-with-vite">​</a></h3>
<p>We are continuing to add new project templates for various types of projects, and we've recently
created one for the infamous combination of <a href="https://react.dev/" target="_blank" rel="noopener noreferrer">React</a> with
<a href="https://vitejs.dev/" target="_blank" rel="noopener noreferrer">Vite</a> tooling.</p>
<p>Check out <a href="https://www.winglang.io/docs/guides/react-vite-websockets" target="_blank" rel="noopener noreferrer">this guide</a>
for a detailed tutorial or just get started with:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-sh codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">mkdir my-project &amp;&amp; cd my-project</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing new react-vite</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="adding-ui-to-wing-classes-through-bring-ui">Adding UI to Wing classes through <code>bring ui</code><a class="hash-link" aria-label="Direct link to adding-ui-to-wing-classes-through-bring-ui" title="Direct link to adding-ui-to-wing-classes-through-bring-ui" href="https://www.winglang.io/blog/2024/04/19/magazine-009#adding-ui-to-wing-classes-through-bring-ui">​</a></h3>
<p>It is now possible to associate simple user interface elements with Wing preflight classes through
the <code>ui</code> module. These elements can dynamically interact with your system via simple implementations
of inflight closures:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring ui</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">MyResource</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">counter</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">counter</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ui</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Button</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Cool Button"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">inc</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ui</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Field</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Counter"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"{this.counter.peek()}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now, when a <code>MyResource</code> node is selected in the Wing Console, you'll see this in the inspector
pane:</p>
<p><img decoding="async" loading="lazy" alt="bring-ui" src="https://www.winglang.io/assets/images/mag-009-bring-ui-25f637a7558d6de300a5d20fcf4b9b91.png" width="379" height="342" class="img_ev3q"></p>
<p>We are adding more UI elements and can't wait to see what people will build with this!</p>
<blockquote>
<p><a href="https://github.com/winglang/wing/pull/5841" target="_blank" rel="noopener noreferrer">See PR by Cristian</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="exposing-cloud-endpoints-for-webhook-development">Exposing cloud endpoints for webhook development<a class="hash-link" aria-label="Direct link to Exposing cloud endpoints for webhook development" title="Direct link to Exposing cloud endpoints for webhook development" href="https://www.winglang.io/blog/2024/04/19/magazine-009#exposing-cloud-endpoints-for-webhook-development">​</a></h3>
<p>When developing applications that react to requests from other services via web hooks such as bots
and extensions, it is often very valuable to be able to accept requests from these external systems
during development.</p>
<p>So now, every <code>cloud.Endpoint</code> in your application (either explicitly or implicitly defined via a
<code>cloud.Api</code>, <code>cloud.Website</code>, etc) can be exposed and requests will be tunneled into the local
simulator:</p>
<p><img decoding="async" loading="lazy" src="https://www.winglang.io/assets/images/mag-009-endpoints-cd5aa0c6a2062334b014f6c5def76d96.png" width="456" height="107" class="img_ev3q"></p>
<blockquote>
<p>This is an experimental feature and still needs some ironing out, and we would love to hear what
you think about it.</p>
</blockquote>
<blockquote>
<p><a href="https://github.com/winglang/wing/pull/5792" target="_blank" rel="noopener noreferrer">See PR by Elad</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="explicit-lifting-of-preflight-objects">Explicit lifting of preflight objects<a class="hash-link" aria-label="Direct link to Explicit lifting of preflight objects" title="Direct link to Explicit lifting of preflight objects" href="https://www.winglang.io/blog/2024/04/19/magazine-009#explicit-lifting-of-preflight-objects">​</a></h3>
<p>When inflight code is referencing a preflight object, the object is <em>lifted</em> and the operation
performed on the object is <em>qualified</em> in order to be able to determine things like IAM permissions.</p>
<p>In many cases, the Wing compiler can automatically qualify the lift. For example, in the code below,
it is clear that the inflight closure performs a <code>push</code> operation on the lifted queue object:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> myQueue </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Queue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  myQueue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">push</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"hello"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>But since the Wing compiler currently does not perform symbolic execution, there are cases where
it's currently impossible for the compiler to qualify the lift. For example, if I assign <code>myQueue</code>
to a new variable called (<code>yourQueue</code>), we will get the following error:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> myQueue </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Queue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> yourQueue </span><span class="token operator">=</span><span class="token plain"> myQueue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  yourQueue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">push</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"hello"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">//^^^^^^^^^ Expression of type "Queue" references an unknown preflight object, can't qualify its capabilities.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To overcome this limitation, a new builtin <code>lift()</code> can be used to explicitly qualify the lifts:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> myQueue </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Queue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">lift</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">myQueue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"push"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> yourQueue </span><span class="token operator">=</span><span class="token plain"> myQueue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  yourQueue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">push</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"hello"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>New builtin <code>lift</code> function allows you to lift preflight objects for the current inflight closure.</p>
<blockquote>
<p>This syntax is still under discussion, but we wanted to make sure this is not blocking users.
Check out the <a href="https://github.com/winglang/wing/pull/5951" target="_blank" rel="noopener noreferrer">RFC</a> and join the conversation.</p>
</blockquote>
<p><a href="https://github.com/winglang/wing/pull/5935" target="_blank" rel="noopener noreferrer">See PR by Yoav</a></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="changes-to-default-object-identifiers">Changes to default object identifiers<a class="hash-link" aria-label="Direct link to Changes to default object identifiers" title="Direct link to Changes to default object identifiers" href="https://www.winglang.io/blog/2024/04/19/magazine-009#changes-to-default-object-identifiers">​</a></h3>
<p>When creating <a href="https://www.winglang.io/docs/language-reference#33-preflight-classes" target="_blank" rel="noopener noreferrer">preflight
objects</a> in Wing, each object
gets an identifier which is unique to its scope of definition. These identifiers are essential for
producing deterministic unique addresses for cloud resources when they are provisioned.</p>
<p>The default identifier for objects in Wing is the name of the class. In the following example, the
identifier of the bucket is simply <code>"Bucket"</code>:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Previously, the default identifier included the namespace of the class, so in the above example the
identifier was <code>"cloud.Bucket"</code>, but since namespaces can now be aliased (<code>bring cloud as my_cloud</code>), this resulted in unstable defaults, which can have dire implications on infrastructure.</p>
<p>By the way, Wing also has dedicated syntax (<code>as ID</code>) to determine the identity of an object in case
there are multiple instances of the same type or you want to be more explicit:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"my_bucket"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>We are discussing potentially <a href="https://github.com/winglang/wing/issues/4604" target="_blank" rel="noopener noreferrer">changing this
syntax</a>, so let us know what you think.</p>
</blockquote>
<p><a href="https://github.com/winglang/wing/pull/5658" target="_blank" rel="noopener noreferrer">See PR by Elad</a></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="implicitly-loaded-platform-extensions">Implicitly loaded platform extensions<a class="hash-link" aria-label="Direct link to Implicitly loaded platform extensions" title="Direct link to Implicitly loaded platform extensions" href="https://www.winglang.io/blog/2024/04/19/magazine-009#implicitly-loaded-platform-extensions">​</a></h3>
<p><a href="https://www.winglang.io/docs/concepts/platforms" target="_blank" rel="noopener noreferrer">Platform extensions</a> are one of the most powerful
capabilities of Wing. They can determine how cloud resources are implemented in your cloud
environment, validate that your application adheres to an organizational policy or inject best
practices and common patterns "under the hood".</p>
<p>So far, it was possible to configure Wing to use a platform provider using an explicit <code>--platform</code>
switch passed to the Wing CLI, but we've seen a need for modules or libraries to be able to provide
platform extensions without having to require explicit configuration.</p>
<p>To that end, as Wing compiles your code, any <code>wplatform.js</code> files found will be loaded automatically
as a platform. This occurs after explicit ones like <code>-t tf-aws</code> and also applies to any winglibs
used by your applications.</p>
<p>One of the currently explored use cases is the ability for libraries to expose their own platform
parameters.</p>
<p>For example, the <a href="https://github.com/winglang/winglibs/tree/main/eventbridge" target="_blank" rel="noopener noreferrer"><code>eventbridge</code></a> winglib
exposes a platform parameter called <code>eventBridgeName</code> to allow developers to connect to an existing
EventBridge bus:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-shell codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing compile -t @winglang/platform-awscdk -v </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">eventBridgeName</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"my-bus"</span><span class="token plain"> main.w</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Here's a sneak peak on how this platform extension is implemented:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">module</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">exports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Platform</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  parameters </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">type</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"object"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	  </span><span class="token literal-property property">properties</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    </span><span class="token literal-property property">eventBridgeName</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    </span><span class="token literal-property property">type</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"string"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p><a href="https://github.com/winglang/wing/pull/5886" target="_blank" rel="noopener noreferrer">See PR by Hasan</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="standardize-cron-expressions">Standardize cron expressions<a class="hash-link" aria-label="Direct link to Standardize cron expressions" title="Direct link to Standardize cron expressions" href="https://www.winglang.io/blog/2024/04/19/magazine-009#standardize-cron-expressions">​</a></h3>
<p>A cron expression like <code>* * * * *</code> is valid in a unix-based crontab, but not in AWS. On the other
hand, <code>* * * * ?</code> is valid in AWS, but not elsewhere.</p>
<p>Now, Wing will expect cron expression to match the standard syntax, and will automatically convert
it to the AWS syntax when deploying to AWS:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Schedule</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cron</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"* * * * *"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p><a href="https://github.com/winglang/wing/pull/5956" target="_blank" rel="noopener noreferrer">See PR by Marcio</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="goodies-from-the-wingly-update">Goodies from the Wingly Update<a class="hash-link" aria-label="Direct link to Goodies from the Wingly Update" title="Direct link to Goodies from the Wingly Update" href="https://www.winglang.io/blog/2024/04/19/magazine-009#goodies-from-the-wingly-update">​</a></h3>
<p><a href="https://www.twitch.tv/winglangio" target="_blank" rel="noopener noreferrer">The Wingly Update</a> is our corky bi-weekly stream where we share
the latest developments of the project, chat with folks from the cloud industry, geek out and
celebrate the beauty of the cloud.</p>
<p>If you haven't been able to catch our show, you can find the complete stack of <a href="https://youtube.com/playlist?list=PL-P8v-FRassZBWsNoSafL_ReO0JO0xJVm&amp;si=trffVrtGGMUZ-SKb" target="_blank" rel="noopener noreferrer">all our episodes
here</a>.</p>
<p>Here are a few goodies we curated from recent shows:</p>
<ul>
<li>The recent <a href="https://www.youtube.com/watch?v=jfUiAdcjlO4" target="_blank" rel="noopener noreferrer">CHANGELOG</a> with <a href="https://github.com/MarkMcCulloh" target="_blank" rel="noopener noreferrer">@MarkMcCulloh</a></li>
<li>An overview of where we are in our journey towards <a href="https://www.youtube.com/watch?v=eorc-Z25jGM" target="_blank" rel="noopener noreferrer">Wing for TypeScript</a>.</li>
<li>A <a href="https://www.youtube.com/watch?v=bi67oqJBNU0" target="_blank" rel="noopener noreferrer">chat with Allen Helton</a> about Texas, life, conferences, cowboys and his love for serverless.</li>
<li>A fun <a href="https://www.youtube.com/watch?v=G_8n5AIzmFA" target="_blank" rel="noopener noreferrer">chat with Michael Antonio</a> from AWS about his journey at Microsoft and Amazon, IAC, CDK and computing nostalgia.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="wing-in-the-wild">Wing in the Wild<a class="hash-link" aria-label="Direct link to Wing in the Wild" title="Direct link to Wing in the Wild" href="https://www.winglang.io/blog/2024/04/19/magazine-009#wing-in-the-wild">​</a></h3>
<p>This is a new section in our magazine where we curate content about Wing from the world wide and
wonderful web:</p>
<ul>
<li>An awesome <a href="https://www.youtube.com/watch?v=aNGM_RF66_U" target="_blank" rel="noopener noreferrer">overview video of Wing</a> by Amichai
Mantinband.</li>
<li>Ayush Thakur
<a href="https://www.linkedin.com/posts/ayush2390_nextjs-wing-activity-7176582275357184001-sIUe?utm_source=share&amp;utm_medium=member_desktop" target="_blank" rel="noopener noreferrer">wrote</a>
about his experience building a NextS app with a Wing backend.</li>
<li>Asher Sterkin's explored an implementation of <a href="https://itnext.io/implementing-production-grade-crud-rest-api-in-winglang-7b8f6917efc2" target="_blank" rel="noopener noreferrer">production-grade REST
APIs</a> in
Wing as well as used Wing to manage multiple AWS environments.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="community-events">Community Events<a class="hash-link" aria-label="Direct link to Community Events" title="Direct link to Community Events" href="https://www.winglang.io/blog/2024/04/19/magazine-009#community-events">​</a></h3>
<p>You can find details for all our events in the <a href="https://calendar.google.com/calendar/u/0?cid=Y18wZTljMGRkZjRiM2IyNzdmMmFlZTMzZjI2NDljYzNlMDAzMGE2OTI1NmRiNjQyNTk0YTc3YmFkZDhjNjc4YzQ4QGdyb3VwLmNhbGVuZGFyLmdvb2dsZS5jb20" target="_blank" rel="noopener noreferrer">Wingnuts
Calendar</a>,
amongst them:</p>
<ul>
<li><a href="https://calendar.google.com/calendar/event?action=TEMPLATE&amp;tmeid=NDN1dWpoNTQ4dGhhNDNvNzUwcW9yYW12dDBfMjAyNDAzMTJUMTQzMDAwWiBjXzBlOWMwZGRmNGIzYjI3N2YyYWVlMzNmMjY0OWNjM2UwMDMwYTY5MjU2ZGI2NDI1OTRhNzdiYWRkOGM2NzhjNDhAZw&amp;tmsrc=c_0e9c0ddf4b3b277f2aee33f2649cc3e0030a69256db642594a77badd8c678c48%40group.calendar.google.com&amp;scp=ALL" target="_blank" rel="noopener noreferrer">Winglang Community
Meeting</a>
is our bi-weekly gathering where members of our community showcase cool apps, demos, and other
projects.</li>
<li><a href="https://calendar.google.com/calendar/event?action=TEMPLATE&amp;tmeid=ZnFtM3NrbHM0NGZqdTNjZGdyMDg2bHVidXBfMjAyMzEyMThUMTIwMDAwWiBjXzBlOWMwZGRmNGIzYjI3N2YyYWVlMzNmMjY0OWNjM2UwMDMwYTY5MjU2ZGI2NDI1OTRhNzdiYWRkOGM2NzhjNDhAZw&amp;tmsrc=c_0e9c0ddf4b3b277f2aee33f2649cc3e0030a69256db642594a77badd8c678c48%40group.calendar.google.com&amp;scp=ALL" target="_blank" rel="noopener noreferrer">Monday Office
Hours</a>
is our bi-weekly opportunity for you to share your feedback, thoughts, concerns, or simply drop by
to say hi.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" href="https://www.winglang.io/blog/2024/04/19/magazine-009#summary">​</a></h3>
<p>That's it for this edition!</p>
<p>You are invited to join the <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">Wing Discord</a>! Come say hello and hang out
with fellow Wingnuts! Give <a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">winglang.io</a> a visit and take Wing out for a spin.
If you're not already, stay updated on the latest changes in our
<a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">repo</a>.</p>
<p>Looking forward to entertaining you in your next flight!</p>
<p><em>- The Wing Team</em></p>]]></content:encoded>
            <author>eladb@wing.cloud (Elad Ben-Israel)</author>
            <author>markm@wing.cloud (Mark McCulloh)</author>
            <author>revitalb@wing.cloud (Revital Barletz)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>winglang</category>
            <category>changelog</category>
            <category>newsletter</category>
        </item>
        <item>
            <title><![CDATA[In Search for Winglang Middleware Part One]]></title>
            <link>https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware</link>
            <guid>https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware</guid>
            <pubDate>Wed, 10 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Winglang middleware]]></description>
            <content:encoded><![CDATA[<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:640/format:webp/1*CrYbo6MTHhudUgazL2h9Vw.png" class="img_ev3q">
</div>
<p>Introducing a new programming language that creates an opportunity and an obligation to reevaluate existing methodologies, solutions, and the entire ecosystem—from language syntax and toolchain to the standard library through the lens of <strong>first principles</strong>.</p>
<p>Simply lifting and shifting existing applications to the cloud has been broadly recognized as risky and sub-optimal. Such a transition tends to render applications less secure, inefficient, and costly without proper adaptation. This principle holds for programming languages and their ecosystems.</p>
<p>Currently, most cloud platform vendors accommodate mainstream programming languages like Python or TypeScript with minimal adjustments. While leveraging existing languages and their vast ecosystems has certain advantages—given it takes about a decade for a new programming language to gain significant traction—it's constrained by the limitations of third-party libraries and tools designed primarily for desktop or server environments, with perhaps a nod towards containerization.</p>
<p><a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> is a new programming language pioneering a <em>cloud-oriented</em> paradigm that seeks to rethink the cloud software development stack from the ground up. My initial evaluations of
<a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang's</a> syntax, standard library, and toolchain were presented in two prior Medium publications:</p>
<ol>
<li><a href="https://medium.com/itnext/hello-winglang-hexagon-6f2bdb550f37" target="_blank" rel="noopener noreferrer">Hello, Winglang Hexagon!: Exploring Cloud Hexagonal Design with Winglang, TypeScript, and Ports &amp; Adapters</a></li>
<li><a href="https://medium.com/itnext/implementing-production-grade-crud-rest-api-in-winglang-7b8f6917efc2" target="_blank" rel="noopener noreferrer">Implementing Production-grade CRUD REST API in Winglang: The First Steps</a></li>
</ol>
<p>Capitalizing on this exploration, I will focus now on the higher-level infrastructure frameworks, often called 'Middleware'. Given its breadth and complexity, Middleware development cannot be comprehensively covered in a single publication. Thus, this publication is probably the beginning of a series where each part will be published as new materials are gathered, insights derived, or solutions uncovered.</p>
<p>Part One of the series, the current publication, will provide an overview of Middleware origins and discuss the current state of affairs, and possible directions for <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> Middleware. The next publications will look at more specific aspects.</p>
<p>With <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> being a rapidly evolving language, distinguishing the core language features from the third-party Middleware built atop this series will remain an unfolding narrative. Stay tuned.</p>
<p>Throughout the preparation of this publication, I utilized several key tools to enhance the draft and ensure its quality.</p>
<p>The initial draft was crafted with the organizational capabilities of <a href="https://www.notion.so/" target="_blank" rel="noopener noreferrer">Notion</a>'s free subscription, facilitating the structuring and development of ideas.</p>
<p>For grammar and spelling review, the free version of <a href="https://app.grammarly.com/" target="_blank" rel="noopener noreferrer">Grammarly</a> proved useful for identifying and correcting basic errors, ensuring the readability of the text.</p>
<p>The enhancement of stylistic expression and the narrative coherence checks were performed using the paid version of <a href="https://openai.com/gpt-4" target="_blank" rel="noopener noreferrer">ChatGPT 4.0</a>.</p>
<p>I owe a special mention to <a href="https://profile.typepad.com/ironick" target="_blank" rel="noopener noreferrer">Nick Gal’s</a> informative <a href="https://ironick.typepad.com/ironick/2005/07/update_on_the_o.html" target="_blank" rel="noopener noreferrer">blog post</a> for illuminating the origins of the term "Middleware," helping to set the correct historical context of the whole discussion.</p>
<p>While these advanced tools and resources significantly contributed to the preparation process, the concepts, solutions, and final decisions presented in this article are entirely my own, for which I bear full responsibility.</p>
<h1>What is Middleware?</h1>
<p>The term "Middleware" passed a long way from its inception and formal definitions to its usage in day-to-day software development practices, particularly within web development.</p>
<p>Covering every nuance and variation of Middleware would be long a journey worthy of a comprehensive volume entitled “The History of Middleware”—a volume awaiting its author.</p>
<p>In this exploration, we aim to chart the principal course, distilling the essence of Middleware and its crucial role in filling the gap between basic-level infrastructure and the practical needs of cloud-based applications development.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="origins-of-middleware">Origins of Middleware<a class="hash-link" aria-label="Direct link to Origins of Middleware" title="Direct link to Origins of Middleware" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#origins-of-middleware">​</a></h2>
<blockquote>
<p><img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:78/1*wwcUBzKuagPLLBCuuiw9ig.png" alt="Brian Ranell" class="img_ev3q">The concept of <em>Middleware</em> ||traces its roots back to an intriguing figure: the Russian-born British cartographer and cryptographer, Alexander d’Agapeyeff, at the "<a href="http://homepages.cs.ncl.ac.uk/brian.randell/NATO/nato1968.PDF" target="_blank" rel="noopener noreferrer">1968 NATO Software Engineering Conference</a>."</p>
</blockquote>
<p>Despite the scarcity of official information about d’Agapeyeff, his legacy extends beyond the enigmatic <a href="https://en.wikipedia.org/wiki/D%27Agapeyeff_cipher" target="_blank" rel="noopener noreferrer">d’Agapeyeff Cipher</a>, as he also played a pivotal role in the software industry as the founder and chairman of the "<a href="https://en.wikipedia.org/wiki/CAP_Group" target="_blank" rel="noopener noreferrer">CAP Group</a>." Insights into the early days of Middleware are illuminated by <a href="https://en.wikipedia.org/wiki/Brian_Randell" target="_blank" rel="noopener noreferrer">Brian Randell</a>, a distinguished British computer scientist, in his recounting of "<a href="https://web.archive.org/web/20131231001745/http://icse08.upb.de/downloads/ICSE08-40yRandellMiddleware.pdf" target="_blank" rel="noopener noreferrer">Some Middleware Beginnings</a>."</p>
<p>At the <a href="http://homepages.cs.ncl.ac.uk/brian.randell/NATO/nato1968.PDF" target="_blank" rel="noopener noreferrer">NATO Conference</a> d’Agapeyeff introduced his Inverted Pyramid—a conceptual framework positioning Middleware as the critical layer bridging the gap between low-level infrastructure (such as Control Programs and Service Routines) and Application Programs:</p>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:640/format:webp/1*CrYbo6MTHhudUgazL2h9Vw.png" class="img_ev3q">
</div>
<p textalign:="">Fig 1: Alexander d'Agapeyeff's Pyramid</p>
<p>Here is how A. d’Agapeyeff explains it:</p>
<blockquote>
<p><em>An example of the kind of software system I am talking about is putting all the applications in a hospital on a computer, whereby you get a whole set of people to use the machine. This kind of system is very sensitive to weaknesses in the software, particular as regards the inability to maintain the system and to extend it freely.</em></p>
</blockquote>
<blockquote>
<p><em>This sensitivity of software can be understood if we liken it to what I will call the inverted pyramid... The buttresses are assemblers and compilers. They don’t help to maintain the thing, but if they fail you have a skew. At the bottom are the control programs, then the various service routines. Further up we have what I call middleware.</em></p>
</blockquote>
<blockquote>
<p><em>This is because no matter how good the manufacturer’s software for items like file handling it is just not suitable; it’s either inefficient or inappropriate. We usually have to rewrite the file handling processes, the initial message analysis and above all the real-time schedulers, because in this type of situation the application programs interact and the manufacturers, software tends to throw them off at the drop of a hat, which is somewhat embarrassing. On the top you have a whole chain of application programs.</em></p>
</blockquote>
<blockquote>
<p><em>The point about this pyramid is that it is terribly sensitive to change in the underlying software such that the new version does not contain the old as a subset. It becomes very expensive to maintain these systems and to extend them while keeping them live.</em></p>
</blockquote>
<p>A. d'Agapeyeff emphasized the delicate balance within this pyramid, noting how sensitive it is to changes in the underlying software that do not preserve backward compatibility. He also warned against danger of over-generalized software too often unsuitable to any practical need:</p>
<blockquote>
<p><em>In aiming at too many objectives the higher-level languages have, perhaps, proved to be useless to the layman, too complex for the novice and too restricted for the expert.</em></p>
</blockquote>
<p>Despite improvements in general-purpose file handling and other advancements since d’Agapeyeff's time, the essence of his observations remains relevant.</p>
<p>There is still a big gap between low-level infrastructure, today encapsulated in an Operating System, like Linux, and the needs of final applications. The Operating System layer reflects and simplifies access to hardware capabilities, which are common for almost all applications.</p>
<p>Higher-level infrastructure needs, however, vary between different groups of applications: some prioritize minimizing the operational cost, some others - speed of development, and others - highly tightened security.</p>
<p>Different implementations of the Middleware layer are intended to fill up this gap and to provide domain-neutral services that are better tailored to the non-functional requirements of various groups of applications.</p>
<p>This consideration also explains why it’s always preferable to keep the core language, aka <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>, and its standard library relatively small and stable, leaving more <a href="https://www.dre.vanderbilt.edu/~schmidt/PDF/Commonality_Variability.pdf" target="_blank" rel="noopener noreferrer">variability</a> to be addressed by these intermediate Middleware layers.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="patterns-frameworks-and-middleware">Patterns, Frameworks, and Middleware<a class="hash-link" aria-label="Direct link to Patterns, Frameworks, and Middleware" title="Direct link to Patterns, Frameworks, and Middleware" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#patterns-frameworks-and-middleware">​</a></h2>
<p>The middleware definition was refined in the “<a href="https://www.dre.vanderbilt.edu/~schmidt/PDF/ICSE-03.pdf" target="_blank" rel="noopener noreferrer">Patterns, Frameworks, and Middleware:
Their Synergistic Relationships</a>” paper, published in 2003 by <a href="https://en.wikipedia.org/wiki/Douglas_C._Schmidt" target="_blank" rel="noopener noreferrer">Douglas C. Schmidt</a> and <a href="https://en.wikipedia.org/wiki/Pattern-Oriented_Software_Architecture" target="_blank" rel="noopener noreferrer">Frank Buschmann</a>. Here, they define middleware as:</p>
<blockquote>
<p><em>software that can significantly increase reuse by providing readily usable, standard solutions
to common programming tasks, such as persistent storage, (de)marshaling, message buffering and queueing, request demultiplexing, and concurrency control. Developers who use
middleware can therefore focus primarily on application-oriented topics, such as business logic, rather than wrestling with tedious and error-prone details associated with programming infrastructure software using lower-level OS APIs and mechanisms.</em></p>
</blockquote>
<p>To understand the interplay between Design Patterns, Frameworks and Middleware, let’s start with formal definitions derived from the “<a href="https://www.dre.vanderbilt.edu/~schmidt/PDF/ICSE-03.pdf" target="_blank" rel="noopener noreferrer">Patterns, Frameworks, and Middleware: Their Synergistic Relationships</a>” paper Abstract:</p>
<blockquote>
<p><em>Patterns codify reusable design expertise that provides time-proven solutions to commonly occurring software problems that arise in particular contexts and domains.</em></p>
</blockquote>
<blockquote>
<p><em>Frameworks provide both a reusable <a href="https://www.amazon.com/Software-Product-Lines-Practices-Patterns/dp/0201703327" target="_blank" rel="noopener noreferrer">product-line architecture</a> – guided by patterns – for a family of related applications and an integrated set of collaborating components that implement concrete realizations of the architecture.</em></p>
</blockquote>
<blockquote>
<p><em>Middleware is reusable software that leverages patterns and frameworks to bridge the gap between the functional requirements of applications and the underlying operating systems, network protocol stacks, and databases.</em></p>
</blockquote>
<p>In other words, Middleware is implemented in the form of one or more Frameworks, which in turn apply several Design Patterns to achieve their goals including future extensibility. Exactly this combination, when implemented correctly, ensures Middleware's ability to flexibly address the infrastructure needs of large yet distinct groups of applications.</p>
<p>Let’s take a closer look at the definitions of each element presented above.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="design-patterns">Design Patterns<a class="hash-link" aria-label="Direct link to Design Patterns" title="Direct link to Design Patterns" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#design-patterns">​</a></h2>
<p>In the realm of software engineering, a <strong>Software Design Pattern</strong> is understood as a generalized, reusable blueprint for addressing frequent challenges encountered in software design. As defined by <a href="https://en.wikipedia.org/wiki/Software_design_pattern" target="_blank" rel="noopener noreferrer">Wikipedia</a>:</p>
<blockquote>
<p>In <a href="https://en.wikipedia.org/wiki/Software_engineering" target="_blank" rel="noopener noreferrer">software engineering</a>, a <strong>software design pattern</strong> is a general, <a href="https://en.wikipedia.org/wiki/Reusability" target="_blank" rel="noopener noreferrer">reusable</a> solution to a commonly occurring problem within a given context in <a href="https://en.wikipedia.org/wiki/Software_design" target="_blank" rel="noopener noreferrer">software design</a>. It is not a finished design that can be transformed directly into <a href="https://en.wikipedia.org/wiki/Source_code" target="_blank" rel="noopener noreferrer">source</a> or <a href="https://en.wikipedia.org/wiki/Machine_code" target="_blank" rel="noopener noreferrer">machine code</a>. Rather, it is a description or template for how to solve a problem that can be used in many different situations. Design patterns are formalized <a href="https://en.wikipedia.org/wiki/Best_practice" target="_blank" rel="noopener noreferrer">best practices</a> that the programmer can use to solve common problems when designing an application or system.</p>
</blockquote>
<p>Sometimes, the term <strong>Architectural Pattern</strong> is used to distinguish high-level software architecture decisions from lower-level, implementation-oriented <a href="https://en.wikipedia.org/wiki/Software_design_pattern" target="_blank" rel="noopener noreferrer">Design Patterns</a>, as defined in <a href="https://en.wikipedia.org/wiki/Architectural_pattern" target="_blank" rel="noopener noreferrer">Wikipedia</a>:</p>
<blockquote>
<p>An <strong>architectural pattern</strong> is a general, reusable resolution to a commonly occurring problem in <a href="https://en.wikipedia.org/wiki/Software_architecture" target="_blank" rel="noopener noreferrer">software architecture</a> within a given context. The architectural patterns address various issues in <a href="https://en.wikipedia.org/wiki/Software_engineering" target="_blank" rel="noopener noreferrer">software engineering</a>, such as <a href="https://en.wikipedia.org/wiki/Computer_hardware" target="_blank" rel="noopener noreferrer">computer hardware</a> performance limitations, <a href="https://en.wikipedia.org/wiki/High_availability" target="_blank" rel="noopener noreferrer">high availability</a> and minimization of a <a href="https://en.wikipedia.org/wiki/Business_risk" target="_blank" rel="noopener noreferrer">business risk</a>. Some architectural patterns have been implemented within <a href="https://en.wikipedia.org/wiki/Software_framework" target="_blank" rel="noopener noreferrer">software frameworks</a>.</p>
</blockquote>
<p>It is essential to differentiate <a href="https://en.wikipedia.org/wiki/Architectural_pattern" target="_blank" rel="noopener noreferrer">Architectural</a> and <a href="https://en.wikipedia.org/wiki/Software_design_pattern" target="_blank" rel="noopener noreferrer">Design Patterns</a> from their implementations in specific software projects. While an <a href="https://en.wikipedia.org/wiki/Architectural_pattern" target="_blank" rel="noopener noreferrer">Architectural</a> or <a href="https://en.wikipedia.org/wiki/Software_design_pattern" target="_blank" rel="noopener noreferrer">Design Pattern</a> provides an initial idea for solution, its implementation may involve a combination of several patterns, tailored to the unique requirements and nuances of the project at hand.</p>
<p><a href="https://en.wikipedia.org/wiki/Architectural_pattern" target="_blank" rel="noopener noreferrer">Architectural Patterns</a>, such as <a href="https://patterns.eecs.berkeley.edu/?page_id=19" target="_blank" rel="noopener noreferrer">Pipe-and-Filters</a>, and <a href="https://en.wikipedia.org/wiki/Software_design_pattern" target="_blank" rel="noopener noreferrer">Design Patterns</a>, such as the <a href="https://en.wikipedia.org/wiki/Decorator_pattern" target="_blank" rel="noopener noreferrer">Decorator</a>, are not only about solving problems in code. They also serve as a common language among architects and developers, facilitating more straightforward communication about software structure and design choices. They are also invaluable tools for analyzing existing solutions, as we will see later.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="software-frameworks">Software Frameworks<a class="hash-link" aria-label="Direct link to Software Frameworks" title="Direct link to Software Frameworks" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#software-frameworks">​</a></h2>
<p>In the domain of computer programming, a <strong>Software Framework</strong> represents a sophisticated form of abstraction, designed to standardize the development process by offering a reusable set of libraries or tools. As defined by <a href="https://en.wikipedia.org/wiki/Software_framework" target="_blank" rel="noopener noreferrer">Wikipedia</a>:</p>
<blockquote>
<p>In <a href="https://en.wikipedia.org/wiki/Computer_programming" target="_blank" rel="noopener noreferrer">computer programming</a>, a <strong>software framework</strong> is an <a href="https://en.wikipedia.org/wiki/Abstraction_(computer*science)" target="_blank" rel="noopener noreferrer">abstraction</a> in which <a href="https://en.wikipedia.org/wiki/Software" target="_blank" rel="noopener noreferrer">software</a>, providing generic functionality, can be selectively changed by additional user-written code, thus providing application-specific software.</p>
</blockquote>
<blockquote>
<p>It provides a standard way to build and deploy applications and is a universal, reusable <a href="https://en.wikipedia.org/wiki/Software_environment_(disambiguation)" target="_blank" rel="noopener noreferrer">software environment</a> that provides particular functionality as part of a larger <a href="https://en.wikipedia.org/wiki/Software_platform" target="_blank" rel="noopener noreferrer">software platform</a> to facilitate the development of <a href="https://en.wikipedia.org/wiki/Software_application" target="_blank" rel="noopener noreferrer">software applications</a>, products and solutions.</p>
</blockquote>
<p>In other words, a <a href="https://en.wikipedia.org/wiki/Software_framework" target="_blank" rel="noopener noreferrer">Software Framework</a> is an evolved <a href="https://en.wikipedia.org/wiki/Library_(computing)" target="_blank" rel="noopener noreferrer">Software Library</a> that employs the principle of <a href="https://en.wikipedia.org/wiki/Inversion_of_control" target="_blank" rel="noopener noreferrer">inversion of control</a>. This means the framework, rather than the user's application, takes charge of the control flow. The application-specific code is then integrated through <a href="https://en.wikipedia.org/wiki/Callback_(computer_programming)" target="_blank" rel="noopener noreferrer">callbacks</a> or <a href="https://en.wikipedia.org/wiki/Plug-in_(computing)" target="_blank" rel="noopener noreferrer">plugins</a>, which the framework's core logic invokes as needed.</p>
<p>Utilizing a <a href="https://en.wikipedia.org/wiki/Software_framework" target="_blank" rel="noopener noreferrer">Software Framework</a> as the foundational layer for integrating domain-specific code with the underlying infrastructure allows developers to significantly decrease the development time and effort for complex software applications. Frameworks facilitate adherence to established coding standards and patterns, resulting in more maintainable, scalable, and secure code.</p>
<p>Nonetheless, it's crucial to follow the <a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" target="_blank" rel="noopener noreferrer">Clean Architecture</a> guidelines, which mandate that domain-specific code remains decoupled and independent from any framework to preserve its ability to evolve independently of any infrastructure. Therefore, an ideal <a href="https://en.wikipedia.org/wiki/Software_framework" target="_blank" rel="noopener noreferrer">Software Framework</a> should support plugging into it a pure domain code without any modification.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="middleware">Middleware<a class="hash-link" aria-label="Direct link to Middleware" title="Direct link to Middleware" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#middleware">​</a></h2>
<p>The Middleware is defined by <a href="https://en.wikipedia.org/wiki/Middleware" target="_blank" rel="noopener noreferrer">Wikipedia</a> as follows:</p>
<blockquote>
<p><em><strong>Middleware</strong> is a type of <a href="https://en.wikipedia.org/wiki/Computer_software" target="_blank" rel="noopener noreferrer">computer software</a> program that provides services to software applications beyond those available from the <a href="https://en.wikipedia.org/wiki/Operating_system" target="_blank" rel="noopener noreferrer">operating system</a>. It can be described as "software glue".</em></p>
</blockquote>
<blockquote>
<p><em><strong>Middleware</strong> in the context of <a href="https://en.wikipedia.org/wiki/Distributed_application" target="_blank" rel="noopener noreferrer">distributed applications</a> is <a href="https://en.wikipedia.org/wiki/Software" target="_blank" rel="noopener noreferrer">software</a> that provides services beyond those provided by the <a href="https://en.wikipedia.org/wiki/Operating_system" target="_blank" rel="noopener noreferrer">operating system</a> to enable the various components of a distributed system to communicate and manage data. Middleware supports and simplifies complex <a href="https://en.wikipedia.org/wiki/Distributed_application" target="_blank" rel="noopener noreferrer">distributed applications</a>. It includes <a href="https://en.wikipedia.org/wiki/Web_server" target="_blank" rel="noopener noreferrer">web servers</a>, <a href="https://en.wikipedia.org/wiki/Application_server" target="_blank" rel="noopener noreferrer">application servers</a>, messaging and similar tools that support application development and delivery. Middleware is especially integral to modern information technology based on <a href="https://en.wikipedia.org/wiki/XML" target="_blank" rel="noopener noreferrer">XML</a>, <a href="https://en.wikipedia.org/wiki/SOAP" target="_blank" rel="noopener noreferrer">SOAP</a>, <a href="https://en.wikipedia.org/wiki/Web_service" target="_blank" rel="noopener noreferrer">Web services</a>, and <a href="https://en.wikipedia.org/wiki/Service-oriented_architecture" target="_blank" rel="noopener noreferrer">service-oriented architecture</a>.</em></p>
</blockquote>
<p>Middleware, however, is not a monolithic entity but is rather composed of several distinct layers as we shall see in the next section.</p>
<h1>Middleware Layers</h1>
<p>Below is an illustrative diagram portraying Middleware as a stack of such layers, each with its specialized function, as suggested in the <a href="https://www.dre.vanderbilt.edu/~schmidt/PDF/ICSE-03.pdf" target="_blank" rel="noopener noreferrer">Schmidt and Buchman paper</a>:</p>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:640/format:webp/1*OrkhM6vKHGKMxdXdqdIbLA.png" class="img_ev3q">
</div>
<p textalign:="">Fig 2: Middleware Layers</p>
<p>Fig 2: Middleware Layers in Context</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="layered-architecture-clarified">Layered Architecture Clarified<a class="hash-link" aria-label="Direct link to Layered Architecture Clarified" title="Direct link to Layered Architecture Clarified" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#layered-architecture-clarified">​</a></h2>
<p>To appreciate the significance of this layered structure, a good understanding of the very concept of Layered Architecture is essential—a concept too often misunderstood completely and confused with the <a href="https://en.wikipedia.org/wiki/Multitier_architecture" target="_blank" rel="noopener noreferrer">Multitier Architecture</a>, deviating significantly from the original principles laid out by <a href="https://en.wikipedia.org/wiki/Edsger_W._Dijkstra" target="_blank" rel="noopener noreferrer">E.W. Dijkstra</a>.</p>
<p>At the “<a href="http://homepages.cs.ncl.ac.uk/brian.randell/NATO/nato1968.PDF" target="_blank" rel="noopener noreferrer">1968 NATO Software Engineering Conference</a>,” <a href="https://en.wikipedia.org/wiki/Edsger_W._Dijkstra" target="_blank" rel="noopener noreferrer">E.W. Dijkstra</a> presented a paper titled “Complexity Controlled by Hierarchical Ordering of Function and Variability” where he stated:</p>
<blockquote>
<p><em>We conceive an ordered sequence of machines: A[0], A[1], ... A[n], where A[0] is the given hardware machine and where the software of layer i transforms machine A[i] into A[i+1]. The software of layer i is defined in terms of machine A[i], it is to be executed by machine A[i], the software of layer i uses machine A[i] to make machine A[i+1].</em></p>
</blockquote>
<p>In other words, in a correctly organized Layered Architecture, the higher-level virtual machine is implemented <em>in terms of</em> the lower-level virtual machine. Within this series, we will come back to this powerful technique over and over again.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="back-to-the-middleware-layers">Back to the Middleware Layers<a class="hash-link" aria-label="Direct link to Back to the Middleware Layers" title="Direct link to Back to the Middleware Layers" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#back-to-the-middleware-layers">​</a></h2>
<p>Right beneath the Applications layer resides the Domain-Specific Middleware Services layer, a notion deserving a separate discussion within the broader framework of <a href="https://en.wikipedia.org/wiki/Domain-driven_design" target="_blank" rel="noopener noreferrer">Domain-Driven Design</a>.</p>
<p>Within this context, however, we are more interested in the Distribution Middleware layer, which serves as the intermediary between Host Infrastructure Middleware within a single "box" and the Common Middleware Services layer which operates across a distributed system's architecture.</p>
<p>As stated in the <a href="https://www.dre.vanderbilt.edu/~schmidt/PDF/ICSE-03.pdf" target="_blank" rel="noopener noreferrer">paper</a>:</p>
<blockquote>
<p><em>Common middleware services augment distribution middleware by defining higher-level domain-independent reusable services that allow application developers to concentrate on programming business logic.</em></p>
</blockquote>
<p>With this understanding, we can now place <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> Middleware within the Middleware Services layer enabling the implementation of Domain-Specific Middleware Services <em>in terms of</em> its primitives.</p>
<p>To complete the picture, we need more quotes from the “<a href="https://www.dre.vanderbilt.edu/~schmidt/PDF/ICSE-03.pdf" target="_blank" rel="noopener noreferrer">Patterns, Frameworks, and Middleware: Their Synergistic Relationships</a>” article mapped onto the modern cloud infrastructure elements.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="host-infrastructure-middleware">Host Infrastructure Middleware<a class="hash-link" aria-label="Direct link to Host Infrastructure Middleware" title="Direct link to Host Infrastructure Middleware" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#host-infrastructure-middleware">​</a></h2>
<p>Here is how it’s defined in the <a href="https://www.dre.vanderbilt.edu/~schmidt/PDF/ICSE-03.pdf" target="_blank" rel="noopener noreferrer">paper</a>:</p>
<blockquote>
<p><strong>Host infrastructure middleware</strong> encapsulates and enhances native OS mechanisms to create reusable event demultiplexing, interprocess communication, concurrency, and synchronization objects, such as reactors; acceptors, connectors, and service handlers; monitor objects; active objects; and service configurators. By encapsulating the peculiarities of particular operating systems, these reusable objects help eliminate many tedious, error-prone, and non-portable aspects of developing and maintaining application software via low-level OS programming APIs, such as Sockets or POSIX pthreads.</p>
</blockquote>
<p>In the AWS environment, general-purpose virtualization services such as <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html" target="_blank" rel="noopener noreferrer">AWS EC2</a> (computer), <a href="https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html" target="_blank" rel="noopener noreferrer">AWS VPC</a> (network), and <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ebs-volumes.html" target="_blank" rel="noopener noreferrer">AWS EBS</a> (storage) play this role.</p>
<p>On the other hand, when speaking about the <a href="https://docs.aws.amazon.com/lambda/latest/dg/welcome.html" target="_blank" rel="noopener noreferrer">AWS Lambda</a> <a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html" target="_blank" rel="noopener noreferrer">execution environment</a>, we may identify <a href="https://aws.amazon.com/blogs/aws/firecracker-lightweight-virtualization-for-serverless-computing/" target="_blank" rel="noopener noreferrer">AWS Firecracker</a>, AWS Lambda standard and custom <a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html" target="_blank" rel="noopener noreferrer">Runtimes</a>, <a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-extensions.html" target="_blank" rel="noopener noreferrer">AWS Lambda Extensions</a>, and <a href="https://docs.aws.amazon.com/lambda/latest/dg/chapter-layers.html" target="_blank" rel="noopener noreferrer">AWS Lambda Layers</a> as also belonging to this category.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="distribution-middleware">Distribution Middleware<a class="hash-link" aria-label="Direct link to Distribution Middleware" title="Direct link to Distribution Middleware" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#distribution-middleware">​</a></h2>
<p>Here is how it’s defined in the <a href="https://www.dre.vanderbilt.edu/~schmidt/PDF/ICSE-03.pdf" target="_blank" rel="noopener noreferrer">paper</a>:</p>
<blockquote>
<p><em><strong>Distribution middleware</strong> defines higher-level distributed programming models whose reusable APIs and objects automate and extend the native OS mechanisms encapsulated by host infrastructure middleware.</em></p>
</blockquote>
<blockquote>
<p><em><strong>Distribution middleware</strong> enables clients to program applications by invoking operations on target objects without hard-coding dependencies on their location, programming language, OS platform, communication protocols and interconnects, and hardware.</em></p>
</blockquote>
<p>Within the AWS environment, fully managed API, Storage, and Messaging services such as <a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html" target="_blank" rel="noopener noreferrer">AWS API Gateway</a>, <a href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html" target="_blank" rel="noopener noreferrer">AWS SQS</a>, <a href="https://docs.aws.amazon.com/sns/latest/dg/welcome.html" target="_blank" rel="noopener noreferrer">AWS SNS</a>, <a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html" target="_blank" rel="noopener noreferrer">AWS S3</a>, and <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html" target="_blank" rel="noopener noreferrer">DynamoDB</a> would fit naturally into this category.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="common-middleware-services">Common Middleware Services<a class="hash-link" aria-label="Direct link to Common Middleware Services" title="Direct link to Common Middleware Services" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#common-middleware-services">​</a></h2>
<p>Here is how it’s defined in the <a href="https://www.dre.vanderbilt.edu/~schmidt/PDF/ICSE-03.pdf" target="_blank" rel="noopener noreferrer">paper</a>:</p>
<blockquote>
<p><em><strong>Common middleware services</strong> augment distribution middleware by defining higher-level domain-independent reusable services that allow application developers to concentrate on programming business logic, without the need to write the “plumbing” code required to develop distributed applications via lower-level middleware directly.</em></p>
</blockquote>
<blockquote>
<p><em>For example, common middleware service providers bundle transactional behavior, security, and database connection pooling and threading into reusable components, so that application developers no longer need to write code that handles these tasks.</em></p>
</blockquote>
<blockquote>
<p><em>Whereas distribution middleware focuses largely on managing end-system resources in support of an object-oriented distributed programming model, common middleware services focus on allocating, scheduling, and coordinating various resources throughout a distributed system using a component programming and scripting model.</em></p>
</blockquote>
<blockquote>
<p><em>Developers can reuse these component services to manage global resources and perform common distribution tasks that would otherwise be implemented in an ad hoc manner within each application. The form and content of these services will continue to evolve as the requirements on the applications being constructed expand.</em></p>
</blockquote>
<p>Formally speaking, <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>, its <a href="https://www.winglang.io/docs/category/standard-library" target="_blank" rel="noopener noreferrer">Standard Library</a>, and its <a href="https://github.com/winglang/winglibs" target="_blank" rel="noopener noreferrer">Extended Libraries</a> collectively constitute <strong>Common middleware services</strong> built on the top of the cloud platform <strong>Distribution Middleware</strong> and its corresponding lower-level <strong>Common middleware services</strong> represented by the cloud platform <a href="https://aws.amazon.com/sdk-for-javascript/" target="_blank" rel="noopener noreferrer">SDK for JavaScript</a> and various <a href="https://en.wikipedia.org/wiki/Infrastructure_as_code" target="_blank" rel="noopener noreferrer">Infrastructure as Code</a> tools, such as <a href="https://docs.aws.amazon.com/cdk/v2/guide/home.html" target="_blank" rel="noopener noreferrer">AWS CDK</a> or <a href="https://www.terraform.io/" target="_blank" rel="noopener noreferrer">Terraform</a>.</p>
<p>With <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> Middleware we are looking for a higher level of abstraction built <em>in terms of</em> the core language and its library and facilitating the development of <a href="https://medium.com/itnext/implementing-production-grade-crud-rest-api-in-winglang-7b8f6917efc2" target="_blank" rel="noopener noreferrer">production-grade</a> <strong>Domain-specific middleware services</strong> and applications on top of it.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="domain-specific-middleware-services">Domain-Specific Middleware Services<a class="hash-link" aria-label="Direct link to Domain-Specific Middleware Services" title="Direct link to Domain-Specific Middleware Services" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#domain-specific-middleware-services">​</a></h2>
<p>Here is how it’s defined in the <a href="https://www.dre.vanderbilt.edu/~schmidt/PDF/ICSE-03.pdf" target="_blank" rel="noopener noreferrer">paper</a>:</p>
<blockquote>
<p><strong>Domain-specific middleware services</strong> are tailored to the requirements of particular domains, such as telecom, e-commerce, health care, process automation, or aerospace. Unlike the other three middleware layers discussed above that provide broadly reusable “horizontal” mechanisms and services, domain-specific middleware services are targeted at “vertical” markets and product-line architectures. Since they embody knowledge of a domain, moreover, reusable domain-specific middleware services have the most potential to increase the quality and decrease the cycle-time and effort required to develop particular types of application software.</p>
</blockquote>
<p>To sum up, the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> Middleware objective is to continue the trend of the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> compiler and its standard library to make developing <strong>Domain-specific middleware services</strong> <em><a href="https://medium.com/@hackingonstuff/cloud-why-so-difficult-%EF%B8%8F-4e9ef1446a64" target="_blank" rel="noopener noreferrer">less difficult</a>.</em></p>
<h1>Cloud Middleware State of Affairs</h1>
<p>Applying the terminology introduced above, the current state of affairs with AWS cloud Middleware could be visualized as follows:</p>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:720/format:webp/1*uLzuyjbLRD_w77NVGCt0Bg.jpeg" class="img_ev3q">
</div>
<p textalign:="">Fig 3: Cloud Middleware State of Affairs</p>
<p>We will look at three leading Middleware Frameworks for AWS:</p>
<ol>
<li><a href="https://middy.js.org/" target="_blank" rel="noopener noreferrer">Middy</a> (TypeScript)</li>
<li><a href="https://github.com/aws-powertools" target="_blank" rel="noopener noreferrer">Power Tools for AWS Lambda</a> (<a href="https://docs.powertools.aws.dev/lambda/python/latest/" target="_blank" rel="noopener noreferrer">Python</a>, <a href="https://docs.powertools.aws.dev/lambda/typescript/latest/" target="_blank" rel="noopener noreferrer">TypeScript</a>, <a href="https://docs.powertools.aws.dev/lambda/java/" target="_blank" rel="noopener noreferrer">Java</a>, and <a href="https://docs.powertools.aws.dev/lambda/dotnet/" target="_blank" rel="noopener noreferrer">.NET</a>)</li>
<li><a href="https://dbartholomae.github.io/lambda-middleware/" target="_blank" rel="noopener noreferrer">Lambda Middleware</a></li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="middy">Middy<a class="hash-link" aria-label="Direct link to Middy" title="Direct link to Middy" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#middy">​</a></h2>
<p>If we dive into the <a href="https://middy.js.org/docs" target="_blank" rel="noopener noreferrer">Middy Documentation</a> we will find that it positions itself as a <strong>middleware engine</strong>, which is correct if we recall that very often <a href="https://en.wikipedia.org/wiki/Software_framework" target="_blank" rel="noopener noreferrer">Frameworks</a>, which <a href="https://middy.js.org/" target="_blank" rel="noopener noreferrer">Middy</a> is, are called Engines. However, it later claims that “… like generic web frameworks (<a href="http://fastify.io/" target="_blank" rel="noopener noreferrer">fastify</a>, <a href="https://hapijs.com/" target="_blank" rel="noopener noreferrer">hapi</a>, <a href="http://expressjs.com/" target="_blank" rel="noopener noreferrer">express</a>, etc.), this problem has been solved using the <a href="https://www.packtpub.com/mapt/book/web_development/9781783287314/4/ch04lvl1sec33/middleware" target="_blank" rel="noopener noreferrer">middleware pattern</a>.” This is, as we understand now, complete nonsense. If we dive into the <a href="https://middy.js.org/docs" target="_blank" rel="noopener noreferrer">Middy Documentation</a> <a href="https://middy.js.org/docs/intro/how-it-works" target="_blank" rel="noopener noreferrer">further</a>, we will find the following picture:</p>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:720/format:webp/1*4bwNcnUdQiKO9o48bRs_5A.png" class="img_ev3q">
</div>
<p textalign:="">Fig 4: Middy</p>
<p>Now, we realize that what <a href="https://middy.js.org/" target="_blank" rel="noopener noreferrer">Middy</a> calls “middleware” is a particular implementation of the <a href="https://patterns.eecs.berkeley.edu/?page_id=19" target="_blank" rel="noopener noreferrer">Pipe-and-Filters Architecture Pattern</a> via the <a href="https://en.wikipedia.org/wiki/Decorator_pattern" target="_blank" rel="noopener noreferrer">Decorator Design Pattern</a>. The latter should not be confused with <a href="https://www.typescriptlang.org/docs/handbook/decorators.html" target="_blank" rel="noopener noreferrer">TypeScript Decorators</a>. In other words, <a href="https://middy.js.org/" target="_blank" rel="noopener noreferrer">Middy</a> decorators are assembled into a pipeline each one performing certain operations <em>before</em> and/or <em>after</em> an HTTP request handling.</p>
<p>Perhaps, the main culprit of this confusion is the <a href="http://expressjs.com/en/guide/writing-middleware.html" target="_blank" rel="noopener noreferrer">expressjs Framework Guide</a> usage of titles like “Writing Middleware” and “Using Middleware” even though it internally uses the term <strong>middleware function</strong>, which is correct.</p>
<p><a href="https://middy.js.org/" target="_blank" rel="noopener noreferrer">Middy</a> comes with an impressive list of <a href="https://middy.js.org/docs/middlewares/intro" target="_blank" rel="noopener noreferrer">official middleware decorator plugins</a> plus a long list of <a href="https://middy.js.org/docs/middlewares/third-party" target="_blank" rel="noopener noreferrer">3rd party middleware decorator plugins</a><strong>.</strong></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="power-tools-for-aws-lambda">Power Tools for AWS Lambda<a class="hash-link" aria-label="Direct link to Power Tools for AWS Lambda" title="Direct link to Power Tools for AWS Lambda" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#power-tools-for-aws-lambda">​</a></h2>
<p>Here, the basic building blocks are called <a href="https://docs.powertools.aws.dev/lambda/python/latest/#features" target="_blank" rel="noopener noreferrer">Features</a>, which in many cases are <a href="https://en.wikipedia.org/wiki/Adapter_pattern" target="_blank" rel="noopener noreferrer">Adapters</a> of lower-level <a href="https://aws.amazon.com/sdk-for-javascript/" target="_blank" rel="noopener noreferrer">SDK</a> functions. The list of features for different languages varies with the <a href="https://docs.powertools.aws.dev/lambda/python/latest/" target="_blank" rel="noopener noreferrer">Python version</a> to have the most comprehensive one. Features could be attached to Lambda Handlers using language decorators, used manually, or, in the case of <a href="https://docs.powertools.aws.dev/lambda/typescript/latest/" target="_blank" rel="noopener noreferrer">TypeScript</a>, using <a href="https://middy.js.org/" target="_blank" rel="noopener noreferrer">Middy</a>. The term <strong>middleware</strong> pops up <a href="https://docs.powertools.aws.dev/lambda/python/latest/utilities/middleware_factory/" target="_blank" rel="noopener noreferrer">here</a> and <a href="https://middy.js.org/docs/integrations/lambda-powertools/#best-practices" target="_blank" rel="noopener noreferrer">there</a> and always means some <a href="https://en.wikipedia.org/wiki/Decorator_pattern" target="_blank" rel="noopener noreferrer">decorator</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="lambda-middleware">Lambda Middleware<a class="hash-link" aria-label="Direct link to Lambda Middleware" title="Direct link to Lambda Middleware" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#lambda-middleware">​</a></h2>
<p>This one is also an implementation of the <a href="https://patterns.eecs.berkeley.edu/?page_id=19" target="_blank" rel="noopener noreferrer">Pipe-and-Filters Architecture Pattern</a> via the <a href="https://en.wikipedia.org/wiki/Decorator_pattern" target="_blank" rel="noopener noreferrer">Decorator Design Pattern</a>. Unlike <a href="https://middy.js.org/" target="_blank" rel="noopener noreferrer">Middy</a>, individual decorators are combined in a pipeline using a special <a href="https://dbartholomae.github.io/lambda-middleware/packages/compose/" target="_blank" rel="noopener noreferrer">Compose decorator</a> effectively applying the <a href="https://en.wikipedia.org/wiki/Composite_pattern" target="_blank" rel="noopener noreferrer">Composite Design Pattern</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="limitations-of-existing-solutions">Limitations of existing solutions<a class="hash-link" aria-label="Direct link to Limitations of existing solutions" title="Direct link to Limitations of existing solutions" href="https://www.winglang.io/blog/2024/04/10/in-search-for-winglang-middleware#limitations-of-existing-solutions">​</a></h2>
<p>Apart from using the incorrect terminology, all three frameworks have certain limitations in common, as follows:</p>
<ol>
<li>
<p><strong>The confusing sequence of operation of multiple <a href="https://en.wikipedia.org/wiki/Decorator_pattern" target="_blank" rel="noopener noreferrer">Decorators</a>.</strong> When more than one decorator is defined, the sequence of <em>before</em> operations is in the order of decorators, but the the sequence of <em>after</em> operations is in <strong>reverse order</strong>. With a long list of decorators that might be a source of serious confusion or even a conflict.</p>
</li>
<li>
<p><strong>Reliance of environment variables.</strong> Control over the operation of particular <a href="https://en.wikipedia.org/wiki/Adapter_pattern" target="_blank" rel="noopener noreferrer">adapters</a> (e.g. <a href="https://docs.powertools.aws.dev/lambda/typescript/latest/core/logger/" target="_blank" rel="noopener noreferrer">Logger</a>) solely relies on environment variables. To make a change, one will need to redeploy the Lambda Function.</p>
</li>
<li>
<p><strong>A single list of decorators with some limited control in runtime.</strong> There is only one list of decorators per Lambda Function and, if some decorators need to be excluded and replaced depending on the deployment target or run-time environment, a run-time check needs to be performed (look, for example, at how <a href="https://docs.powertools.aws.dev/lambda/typescript/latest/core/tracer/" target="_blank" rel="noopener noreferrer">Tracer behavior is controlled</a> in <a href="https://docs.powertools.aws.dev/lambda/typescript/latest/" target="_blank" rel="noopener noreferrer">Power Tools for AWS Lambda</a>). This introduces unnecessary run-time overhead and enlarges the potential security attack surface.</p>
</li>
<li>
<p><strong>Lack of support for higher-level crosscut specifications.</strong> All middleware decorators are specified for individual Lambda functions. Common specifications at the organization, organization unit, account, or service levels will require some handmade custom solutions.</p>
</li>
<li>
<p><strong>Too narrow interpretation of Middleware as a linear implementation of <a href="https://patterns.eecs.berkeley.edu/?page_id=19" target="_blank" rel="noopener noreferrer">Pipe-and-Filers</a> and <a href="https://en.wikipedia.org/wiki/Decorator_pattern" target="_blank" rel="noopener noreferrer">Decorator</a> design patterns.</strong> <a href="https://docs.powertools.aws.dev/lambda/typescript/latest/" target="_blank" rel="noopener noreferrer">Power Tools for AWS Lambda</a> makes it slightly better by introducing its <a href="https://docs.powertools.aws.dev/lambda/python/latest/#features" target="_blank" rel="noopener noreferrer">Features</a>, also called Utilities, such as <a href="https://docs.powertools.aws.dev/lambda/typescript/latest/core/logger/" target="_blank" rel="noopener noreferrer">Logger</a>, first and corresponding decorators second. <a href="https://middy.js.org/" target="_blank" rel="noopener noreferrer">Middy</a>, on the other hand, treats everything as a decorator. In both cases, the decorators are stacked in one linear sequence, such that retrieving two parameters, one from the <a href="https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/#secretsprovider" target="_blank" rel="noopener noreferrer">Secrets Manager</a> and another from the <a href="https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/#appconfigprovider" target="_blank" rel="noopener noreferrer">AppConfig</a>, cannot be performed in parallel while state-of-the-art pipeline builders, such as <a href="https://docs.marblejs.com/" target="_blank" rel="noopener noreferrer">Marble.js</a> and <a href="http://caolan.github.io/async/v3/" target="_blank" rel="noopener noreferrer">Async.js</a>, support significantly more advanced control forms.</p>
</li>
</ol>
<p>For <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> Common Services Middleware Framework (we can now use the correct full name) this list of limitations will serve as a call for action to look for pragmatic ways to overcome these limitations.</p>
<h1>Winglang Middleware Direction</h1>
<p>Following the “<a href="https://www.dre.vanderbilt.edu/~schmidt/PDF/ICSE-03.pdf" target="_blank" rel="noopener noreferrer">Patterns, Frameworks, and Middleware: Their Synergistic Relationships</a>” article middleware layers taxonomy, the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> Common Middleware Services Framework is positioned as follows:</p>
<div textalign:="">
<img decoding="async" loading="lazy" src="https://miro.medium.com/v2/resize:fit:720/format:webp/1*Kl4UWhR5yvrEdMy32mIlWw.jpeg" class="img_ev3q">
</div>
<p textalign:="">Fig 5: Winglang Middlware Layer</p>
<p>In the diagram above, the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> Middleware Layer, code name <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> MW, is positioned as an upper sub-layer of Common Middleware Services, built on the top of the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> as a representative of the <a href="https://medium.com/@asher-sterkin/ifc-2023-technology-landscape-6953ff9ab9e5" target="_blank" rel="noopener noreferrer">Infrastructure-from-Code</a> solution, which in turn is built on the top of the cloud-specific <a href="https://medium.com/@asher-sterkin/ifc-2023-technology-landscape-6953ff9ab9e5" target="_blank" rel="noopener noreferrer">SDK</a> and <a href="https://medium.com/@asher-sterkin/ifc-2023-technology-landscape-6953ff9ab9e5" target="_blank" rel="noopener noreferrer">IaC</a> solutions providing convenient access to the cloud Distribution Middleware.</p>
<p>From the feature set perspective, the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> MW is expected</p>
<ol>
<li>To be on par with leading middleware frameworks such
<ol>
<li><a href="https://middy.js.org/" target="_blank" rel="noopener noreferrer">Middy</a> (TypeScript)</li>
<li><a href="https://github.com/aws-powertools" target="_blank" rel="noopener noreferrer">Power Tools for AWS Lambda</a> (<a href="https://docs.powertools.aws.dev/lambda/python/latest/" target="_blank" rel="noopener noreferrer">Python</a>, <a href="https://docs.powertools.aws.dev/lambda/typescript/latest/" target="_blank" rel="noopener noreferrer">TypeScript</a>, <a href="https://docs.powertools.aws.dev/lambda/java/" target="_blank" rel="noopener noreferrer">Java</a>, and <a href="https://docs.powertools.aws.dev/lambda/dotnet/" target="_blank" rel="noopener noreferrer">.NET</a>)</li>
<li><a href="https://dbartholomae.github.io/lambda-middleware/" target="_blank" rel="noopener noreferrer">Lambda Middleware</a></li>
</ol>
</li>
<li>In addition, to provide support for leading open standards such as
<ol>
<li><a href="https://openid.net/" target="_blank" rel="noopener noreferrer">OpenID</a></li>
<li><a href="https://opentelemetry.io/docs/what-is-opentelemetry/" target="_blank" rel="noopener noreferrer">Open Telemetry</a></li>
<li><a href="https://oauth.net/2/" target="_blank" rel="noopener noreferrer">OAuth 2.0</a></li>
<li><a href="https://www.asyncapi.com/en" target="_blank" rel="noopener noreferrer">Async API</a></li>
<li><a href="https://cloudevents.io/" target="_blank" rel="noopener noreferrer">Cloud Events</a></li>
</ol>
</li>
<li>To provide built-in support for cross-cut middleware specifications at different levels above individual cloud functions</li>
<li>To support run-time fine-tuning of individual feature parameters (e.g. logging level) without corresponding cloud resources redeployment</li>
</ol>
<p>Different implementations of <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> MW will vary in efficiency, ease of use (e.g. middleware pipeline configuration), flexibility, and supplementary tooling such as automatic code generation.</p>
<p>At the current stage, any premature conversion towards a single solution will be detrimental to the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> ecosystem evolution, and running multiple experiments in parallel would be more beneficial. Once certain middleware features prove themselves, they might be incorporated into the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> core, but it’s advisable not to rush too fast.</p>
<p>For the same reason, I intentionally called this section <em>Directions</em> rather than <em>Requirements</em> or <em>Problem Statement</em>. I have only a general sense of the desirable direction to proceed. Making things too specific could lead to some serendipitous alternatives being missed. I can, however, specify some constraints, as follows:</p>
<ol>
<li><strong>Do not count on advanced <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> features</strong>, such as <a href="https://www.typescriptlang.org/docs/handbook/2/generics.html" target="_blank" rel="noopener noreferrer">Generics</a>, to come. Generics may significantly complicate the language syntax and too often are introduced before a clear understanding of how much sophistication is required. Also, at the early stages of exploration, the lack of Generics support could be compensated by switching to a general-purpose data type, such as <a href="https://www.winglang.io/docs/language-reference#114-json-type" target="_blank" rel="noopener noreferrer">Json</a>, or code generators, including the <a href="https://gcc.gnu.org/onlinedocs/cpp/Macros.html" target="_blank" rel="noopener noreferrer">“C” macros</a>.</li>
<li><strong>Stick with <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a></strong> and switch to <a href="https://www.winglang.io/docs/language-reference#521-typescript" target="_blank" rel="noopener noreferrer">TypeScript</a> for implementing low-level extensions only. As a new language, <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> lacks features taken for granted in mainstream languages and therefore requires some faith to get a fair chance to write as much code as possible, even if it is slightly less convenient. This is the only way for a new programming language to evolve.</li>
<li><strong>If the development of CLI tools is required, prefer TypeScript over other languages such as Python.</strong> I already have the TypeScript toolchain installed on my desktop with all dependencies resolved. It’s always better to limit the number of moving parts in the system to the absolute minimum.</li>
<li><strong>Limit <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> middleware implementation to</strong> a <strong>single process</strong> of a Cloud Function. Out-of-proc capabilities, such as <a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-extensions.html" target="_blank" rel="noopener noreferrer">AWS Lambda Extensions</a>, can improve overall system performance, security, and reuse (see, for example, this <a href="https://aws.amazon.com/blogs/compute/enhancing-runtime-security-and-governance-with-the-aws-lambda-runtime-api-proxy-extension/?advocacy_source=everyonesocial&amp;trk=global_employee_advocacy&amp;sc_channel=sm&amp;es_id=70adde6d15" target="_blank" rel="noopener noreferrer">blog post</a>). However, they are not currently supported by <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> out of the box. Also, utilizing such advanced capabilities will increase the system's complexity while contributing little, if any, at the semantic level. Exploring this direction can be postponed to later stages.</li>
</ol>
<h1>What’s Next?</h1>
<p>This publication was completely devoted to clarifying the concept of <a href="https://en.wikipedia.org/wiki/Middleware" target="_blank" rel="noopener noreferrer">Middleware</a>, its position within the cloud software system stack, and defining a general direction for developing one or more <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> Middleware <a href="https://en.wikipedia.org/wiki/Software_framework" target="_blank" rel="noopener noreferrer">Frameworks</a>.</p>
<p>I plan to devote the next Part Two of this series to exploring different options for implementing the <a href="https://patterns.eecs.berkeley.edu/?page_id=19" target="_blank" rel="noopener noreferrer">Pipe-and-Filters Pattern</a> in <a href="https://en.wikipedia.org/wiki/Middleware" target="_blank" rel="noopener noreferrer">Middleware</a> and after that to start building individual utilities and corresponding filters one by one.</p>
<p>It’s a rare opportunity that one does not encounter every day to revise the generic software infrastructure elements from the first principles and to explore the most suitable ways of realizing these principles on the leading modern cloud platforms. If you are interested in taking part in this journey, drop me a line.</p>]]></content:encoded>
            <author>asher.sterkin@gmail.com (Asher Sterkin)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>middleware</category>
            <category>platforms</category>
        </item>
        <item>
            <title><![CDATA[Inflight Magazine no. 8]]></title>
            <link>https://www.winglang.io/blog/2024/03/13/magazine-008</link>
            <guid>https://www.winglang.io/blog/2024/03/13/magazine-008</guid>
            <pubDate>Wed, 13 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Updates from the winglang project]]></description>
            <content:encoded><![CDATA[<p>import ReactPlayer from "react-player";
import console_new_look from "./assets/2024-03-13-magazine-008/console-new-look.mp4";</p>
<blockquote>
<p>The 8th issue of the Wing Inflight Magazine.</p>
</blockquote>
<p>Hello Wingnuts!</p>
<p>We are back with another issue of the <strong>Wing Inflight Magazine</strong> and excited to share some updates about <a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">Winglang</a>, <strong>an open source-programming language for the cloud</strong>.</p>
<p>Wing is shipped with a <strong>powerful cloud simulator</strong> which allows developers to write and test complete cloud application without having to deploy anything to the cloud.</p>
<p>The language combines cloud infrastructure <em><strong>and</strong></em> runtime into a single programming model and <strong>compiles to Terraform/CloudFormation and JavaScript</strong> that are ready to deploy to AWS, GCP and Azure (see <a href="https://www.winglang.io/docs/api/standard-library/compatibility-matrix" target="_blank" rel="noopener noreferrer">support matrix</a>).</p>
<p>We are designing Wing to be <strong>familiar and friendly</strong> for developers who come from modern object-oriented background, so it will take you <a href="https://github.com/winglang/workshop-react/blob/main/cheatsheet.md" target="_blank" rel="noopener noreferrer">5 minutes</a> to learn.</p>
<p>Check out our <a href="https://www.winglang.io/docs/" target="_blank" rel="noopener noreferrer">getting started tutorial</a> or hit the Wing Playground for an online experience.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="in-todays-issue">In today's issue<a class="hash-link" aria-label="Direct link to In today's issue" title="Direct link to In today's issue" href="https://www.winglang.io/blog/2024/03/13/magazine-008#in-todays-issue">​</a></h3>
<ul>
<li>🚀 <a href="https://www.winglang.io/blog/2024/03/13/magazine-008#deploying-aws-resources-and-apis-inside-a-private-vpcs">Deploying AWS resources and APIs inside a private VPCs</a></li>
<li>🎨 <a href="https://www.winglang.io/blog/2024/03/13/magazine-008#a-fresh-look-for-the-wing-console-map-view">A fresh look for the Wing Console map view</a></li>
<li>🤩 <a href="https://www.winglang.io/blog/2024/03/13/magazine-008#new-syntax-for-creating-sets">New syntax for creating sets</a></li>
<li>🔥 <a href="https://www.winglang.io/blog/2024/03/13/magazine-008#mutually-referential-type-declarations">Mutually referential type declarations</a></li>
<li>🛟 <a href="https://www.winglang.io/blog/2024/03/13/magazine-008#the-bang--operator">The bang <code>!</code> operator</a></li>
<li>🏋️ <a href="https://www.winglang.io/blog/2024/03/13/magazine-008#ability-to-lift-collection-of-inflight-closures">Ability to lift collection of inflight closures</a></li>
<li>🗄️ <a href="https://www.winglang.io/blog/2024/03/13/magazine-008#fsappendfile"><code>fs.appendFile()</code></a></li>
<li>⚙ <a href="https://www.winglang.io/blog/2024/03/13/magazine-008#platform-parameters-and-aws-vpc-configuration">Platform Parameters and AWS VPC configuration</a></li>
<li>🛌 <a href="https://www.winglang.io/blog/2024/03/13/magazine-008#ergonomic-improvements-for-cloudfunction-and-cloudapi">Ergonomic improvements for <code>cloud.Function</code> and <code>cloud.Api</code></a></li>
<li>🎥 <a href="https://www.winglang.io/blog/2024/03/13/magazine-008#goodies-from-the-wingly-update">Goodies from the Wingly Update</a></li>
<li>👯‍♀️ <a href="https://www.winglang.io/blog/2024/03/13/magazine-008#community-events">Community Events</a></li>
</ul>
<blockquote>
<p>NOTE: I spent like two hours trying to figure out the right emojis here so please take a minute to appreciate them :-)</p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="deploying-aws-resources-and-apis-inside-a-private-vpcs">Deploying AWS resources and APIs inside a private VPCs<a class="hash-link" aria-label="Direct link to Deploying AWS resources and APIs inside a private VPCs" title="Direct link to Deploying AWS resources and APIs inside a private VPCs" href="https://www.winglang.io/blog/2024/03/13/magazine-008#deploying-aws-resources-and-apis-inside-a-private-vpcs">​</a></h3>
<p><img decoding="async" loading="lazy" src="https://www.winglang.io/assets/images/private-api-e3af851e05013c677508e02c2f3dff37.png" width="1000" height="569" class="img_ev3q"></p>
<p>Users tell us they are looking for ways to deploy API-based services inside their VPCs. We've spent some time learning about <a href="https://www.winglang.io/blog/2024/02/15/private-api-gateways" target="_blank" rel="noopener noreferrer">the challenges people have</a> and figured we can offer a awesome experience in Wing for this use case.</p>
<p>We published a <a href="https://www.winglang.io/blog/2024/02/09/private-api-gateway-aws" target="_blank" rel="noopener noreferrer">guide</a> which describes how to configure the <code>tf-aws</code> platform to deploy your application's AWS resources and APIs inside a VPC, with support for creating a whole new VPC or deploying into a VPC that's already setup in your environment.</p>
<p>Check out a recording of this <a href="https://youtu.be/1o5dk4S82_o?si=mvHGaYBJtGTj2Fi8" target="_blank" rel="noopener noreferrer">online workshop</a> by <a href="https://github.com/hasanaburayyan" target="_blank" rel="noopener noreferrer">Hasan Abu-Rayyan</a> from the Wing core team, where he talks about this use case and walks through an example.</p>
<p><a href="https://github.com/rkazakov" target="_blank" rel="noopener noreferrer">Ruslan Kazakov</a> from Sydney, Australia wrote about his experience in <a href="https://medium.com/bear-plus/secure-your-vpc-endpoint-for-api-gateway-with-winglang-235a5f8af072" target="_blank" rel="noopener noreferrer">a blog post</a> :</p>
<blockquote>
<p>”Wing made all the difference! After struggling for days with the CDK, I turned to Wing and had a fully functional Private API Gateway up and running within hours. Its simplicity and power are unparalleled. Thank you, Wing, for saving me time and headaches!”</p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="a-fresh-look-for-the-wing-console-map-view">A fresh look for the Wing Console map view<a class="hash-link" aria-label="Direct link to A fresh look for the Wing Console map view" title="Direct link to A fresh look for the Wing Console map view" href="https://www.winglang.io/blog/2024/03/13/magazine-008#a-fresh-look-for-the-wing-console-map-view">​</a></h3>
<p>We gave the map view in Wing Console some love, improved colors, cleaned up the UI and polished the interactions:</p>
<reactplayer width="50%" height="50%" playing="" loop="" muted="" url="{console_new_look}/">
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="new-syntax-for-creating-sets">New syntax for creating sets<a class="hash-link" aria-label="Direct link to New syntax for creating sets" title="Direct link to New syntax for creating sets" href="https://www.winglang.io/blog/2024/03/13/magazine-008#new-syntax-for-creating-sets">​</a></h3>
<p>Wing has a built-in <code>Set</code> type to represent a collection of unique values. This type used to have its own literal syntax which used curly braces <code>{}</code>:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> mySet </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// before</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>While this syntax was cute, it caused some confusion with the object literal syntax that also uses curly braces (<code>{ foo: 123 }</code>). Given how infrequently sets are created (and how frequently object literals are used), the syntactic complexity seemed unwarranted. Sets can now be created with the existing square brackets <code>[]</code> alongside a type annotation:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> mySet </span><span class="token operator">=</span><span class="token plain"> </span><span class="token known-class-name class-name">Set</span><span class="token operator">&lt;</span><span class="token plain">num</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p><a href="https://github.com/winglang/wing/pull/5729" target="_blank" rel="noopener noreferrer">PR #5729</a> by <a href="https://github.com/Warkanlock" target="_blank" rel="noopener noreferrer">@Warkanlock</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="mutually-referential-type-declarations">Mutually referential type declarations<a class="hash-link" aria-label="Direct link to Mutually referential type declarations" title="Direct link to Mutually referential type declarations" href="https://www.winglang.io/blog/2024/03/13/magazine-008#mutually-referential-type-declarations">​</a></h3>
<p>It is now possible for two type declarations such as <code>struct</code>s, <code>interface</code>s, or <code>class</code>es to refer to each other:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">interface</span><span class="token plain"> </span><span class="token class-name">IThing1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">m2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">IThing2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">interface</span><span class="token plain"> </span><span class="token class-name">IThing2</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">m1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">IThing1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">struct </span><span class="token constant" style="color:rgb(189, 147, 249)">M1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token literal-property property">m2</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">M2</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">struct </span><span class="token constant" style="color:rgb(189, 147, 249)">M2</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token literal-property property">m1</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">M1</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This implies that declarations can be used anywhere within the scope, regardless of where they are located in the file. Declarations are basically type system information and they are not executed, so there is no meaning to their order.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// this works even though M1 is declared later!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> </span><span class="token literal-property property">x</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">M1</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">struct </span><span class="token constant" style="color:rgb(189, 147, 249)">M1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token literal-property property">m2</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">M2</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">struct </span><span class="token constant" style="color:rgb(189, 147, 249)">M2</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token literal-property property">m1</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">M1</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p><a href="https://github.com/winglang/wing/pull/5683" target="_blank" rel="noopener noreferrer">PR #5683</a> by <a href="https://github.com/Chriscbr" target="_blank" rel="noopener noreferrer">@Chriscbr</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-bang--operator">The bang <code>!</code> operator<a class="hash-link" aria-label="Direct link to the-bang--operator" title="Direct link to the-bang--operator" href="https://www.winglang.io/blog/2024/03/13/magazine-008#the-bang--operator">​</a></h3>
<p>We are continuing to add language tools for safely dealing with nullity.</p>
<p>The bang operator (<code>!</code>) performs a <em>runtime assertion</em> that a value is not <code>nil</code>, and returns the value.</p>
<p>An error will be thrown if the value is <code>nil</code>. Unlike TypeScript, where <code>!</code> is only a type-checking hint, in Wing the bang operator will actually throw an error if there is no value. This means that nullity will not propagate further and avoids the common horrors of <code>"Cannot read properties of undefined"</code> errors, cascading through your program.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">struct </span><span class="token maybe-class-name">User</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">email</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"https://api.mysystem.com/users/127364"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> user </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">User</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parseJson</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// since "body" is `str?` we need to unwrap it</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"name: {user.name}, email: {user.email}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This is roughly equivalent to:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> body </span><span class="token operator">=</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> user </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">User</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parseJson</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Unexpected nil"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p><a href="https://github.com/winglang/wing/pull/5556" target="_blank" rel="noopener noreferrer">PR #5556</a> by <a href="https://github.com/meirdev" target="_blank" rel="noopener noreferrer">@meirdev</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="ability-to-lift-collection-of-inflight-closures">Ability to lift collection of inflight closures<a class="hash-link" aria-label="Direct link to Ability to lift collection of inflight closures" title="Direct link to Ability to lift collection of inflight closures" href="https://www.winglang.io/blog/2024/03/13/magazine-008#ability-to-lift-collection-of-inflight-closures">​</a></h3>
<p>This is a very powerful addition to the Wing lifting system that opens up many interesting use cases.</p>
<p>It is now possible to lift collections of inflight closures (arrays, maps, etc) from preflight to inflight. This allows you to collect them during preflight and execute later. For example, a common use case is event handlers.</p>
<p>The example below implements a simple pub/sub mechanism using a collection of inflight closure. The <code>Users</code> class which allows consumers to subscribe to a "sign up" event by providing an inflight closure as the handler. When a new user signs up, all the handlers are called:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Users</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">signupHandlers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">MutArray</span><span class="token operator">&lt;</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">signupHandlers</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">MutArray</span><span class="token operator">&lt;</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub </span><span class="token function" style="color:rgb(80, 250, 123)">onSignup</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">handler</span><span class="token parameter operator">:</span><span class="token parameter"> </span><span class="token parameter function" style="color:rgb(80, 250, 123)">inflight</span><span class="token parameter"> </span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">str</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token parameter operator">:</span><span class="token parameter"> </span><span class="token parameter keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">signupHandlers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">push</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">nodeof</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">addConnection</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"onSignup"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token literal-property property">source</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">unsafeCast</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token literal-property property">target</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">signup</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">user</span><span class="token parameter operator">:</span><span class="token parameter"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> h </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">signupHandlers</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token function" style="color:rgb(80, 250, 123)">h</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">UserCounter</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">counter</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">users</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Users</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">counter</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    users</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">onSignup</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">inc</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">count</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> num </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">peek</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">WelcomeEmail</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">users</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Users</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    users</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">onSignup</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">email</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token comment" style="color:rgb(98, 114, 164)">// send an email to user</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> users </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Users</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">UserCounter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">users</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">WelcomeEmail</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">users</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Notice the cool usage of <code>nodeof(x).addConnection()</code> which results in this beautiful view:</p>
<p><img decoding="async" loading="lazy" src="https://www.winglang.io/assets/images/collection-b80085927f60f8b01e74c89be8e5aa34.png" width="463" height="302" class="img_ev3q"></p>
<blockquote>
<p><a href="https://github.com/winglang/wing/pull/5757" target="_blank" rel="noopener noreferrer">PR #5757</a> by <a href="https://github.com/yoav-steinberg" target="_blank" rel="noopener noreferrer">@yoav-steinberg</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="fsappendfile"><code>fs.appendFile()</code><a class="hash-link" aria-label="Direct link to fsappendfile" title="Direct link to fsappendfile" href="https://www.winglang.io/blog/2024/03/13/magazine-008#fsappendfile">​</a></h3>
<p>A new function on the filesystem (<code>fs</code>) builtin module. <code>fs.appendFile()</code> writes data to the <em>end</em> of a file.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring fs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> file </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"/dummy.txt"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">fs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">writeFile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">file</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hello "</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">fs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">appendFile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">file</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"World!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// file now contains "Hello World!"</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p><a href="https://github.com/winglang/wing/pull/5800" target="_blank" rel="noopener noreferrer">PR #5800</a> by <a href="https://github.com/CJLA" target="_blank" rel="noopener noreferrer">@CJLA</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="platform-parameters-and-aws-vpc-configuration">Platform Parameters and AWS VPC configuration<a class="hash-link" aria-label="Direct link to Platform Parameters and AWS VPC configuration" title="Direct link to Platform Parameters and AWS VPC configuration" href="https://www.winglang.io/blog/2024/03/13/magazine-008#platform-parameters-and-aws-vpc-configuration">​</a></h3>
<p><a href="https://www.winglang.io/docs/concepts/platforms" target="_blank" rel="noopener noreferrer">Platforms</a> are the "backend" of the Wing compiler. They hook into the compilation and synthesis process and determine everything about how an app will eventually be deployed to the cloud. Wing is shipped with a set of built-in platforms such as <code>tf-aws</code>, <code>tf-azure</code>, but users can create their own platform extensions, and we are starting to see some very creative and powerful capabilities enabled by this feature.</p>
<p>It is now possible for platforms to read parameters from a configuration file (<code>wing.toml</code>) or from the <code>-v</code> CLI switch.</p>
<p>As one example of this, the <code>tf-aws</code> platform now supports a few parameters related to handling VPCs. The parameters provide an easy mechanism to control this cross-cutting concern across all your resources:</p>
<p><code>wing.toml</code>:</p>
<div class="language-toml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-toml codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">[tf-aws]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">vpc = "existing"</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">vpc_id = "vpc-088c31249bb80726a"</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">vpc_lambda = true</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>With the above configuration, when compiling the following program to <code>tf-aws</code>, the AWS Lambda function below will be placed inside an existing VPC:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"hi"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p><a href="https://github.com/winglang/wing/pull/5557" target="_blank" rel="noopener noreferrer">PR #5557</a> by <a href="https://github.com/hasanaburayyan" target="_blank" rel="noopener noreferrer">@hasanaburayyan</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="ergonomic-improvements-for-cloudfunction-and-cloudapi">Ergonomic improvements for <code>cloud.Function</code> and <code>cloud.Api</code><a class="hash-link" aria-label="Direct link to ergonomic-improvements-for-cloudfunction-and-cloudapi" title="Direct link to ergonomic-improvements-for-cloudfunction-and-cloudapi" href="https://www.winglang.io/blog/2024/03/13/magazine-008#ergonomic-improvements-for-cloudfunction-and-cloudapi">​</a></h3>
<p><code>cloud.Function</code> and <code>cloud.Api</code> are fundamental building blocks of Wing's SDK. They both make use of inflight handlers for their runtime.
These handlers had a required return type, which was often not actually needed. Now this return type is optional and defaults to a sensible value:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// no need to return anything!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">post</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"/"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hi"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// can also return a partial response with no body, like:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// return { status: 200 };</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Invoking <code>cloud.Function</code> also now has an optional argument instead of a required one:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> func </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hi"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"invoke function"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  func</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p><a href="https://github.com/winglang/wing/pull/5644" target="_blank" rel="noopener noreferrer">PR #5644</a> by <a href="https://github.com/eladb" target="_blank" rel="noopener noreferrer">@eladb</a></p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="goodies-from-the-wingly-update">Goodies from the Wingly Update<a class="hash-link" aria-label="Direct link to Goodies from the Wingly Update" title="Direct link to Goodies from the Wingly Update" href="https://www.winglang.io/blog/2024/03/13/magazine-008#goodies-from-the-wingly-update">​</a></h3>
<p><a href="https://www.twitch.tv/winglangio" target="_blank" rel="noopener noreferrer">The Wingly Update</a> is our corky bi-weekly stream where we share the latest developments of the project, chat with folks from the cloud industry, geek out and celebrate the beauty of the cloud.</p>
<p>If you haven't been able to catch our show, you can find the complete stack of <a href="https://youtube.com/playlist?list=PL-P8v-FRassZBWsNoSafL_ReO0JO0xJVm&amp;si=trffVrtGGMUZ-SKb" target="_blank" rel="noopener noreferrer">all our episodes here</a>.</p>
<p>Here are a few goodies we curated from recent shows:</p>
<ul>
<li><a href="https://youtu.be/MmO2SdKmw40?si=9jrLON4QLdwqI9CR" target="_blank" rel="noopener noreferrer">Huzaifa Asif</a> came to chat with us about his career journey and his new book <strong>Designing Scalable Systems</strong>.</li>
<li><a href="https://www.youtube.com/watch?v=OH_OrzhkqEA&amp;t=132s" target="_blank" rel="noopener noreferrer">Live Hacking Session Building a Slack Bot</a> - the first in a series of sessions where we build a Slack bot with Wing.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="community-events">Community Events<a class="hash-link" aria-label="Direct link to Community Events" title="Direct link to Community Events" href="https://www.winglang.io/blog/2024/03/13/magazine-008#community-events">​</a></h3>
<p>You can find details for all our events in the <a href="https://calendar.google.com/calendar/u/0?cid=Y18wZTljMGRkZjRiM2IyNzdmMmFlZTMzZjI2NDljYzNlMDAzMGE2OTI1NmRiNjQyNTk0YTc3YmFkZDhjNjc4YzQ4QGdyb3VwLmNhbGVuZGFyLmdvb2dsZS5jb20" target="_blank" rel="noopener noreferrer">Wingnuts Calendar</a>, amongst them:</p>
<ul>
<li><a href="https://calendar.google.com/calendar/event?action=TEMPLATE&amp;tmeid=NDN1dWpoNTQ4dGhhNDNvNzUwcW9yYW12dDBfMjAyNDAzMTJUMTQzMDAwWiBjXzBlOWMwZGRmNGIzYjI3N2YyYWVlMzNmMjY0OWNjM2UwMDMwYTY5MjU2ZGI2NDI1OTRhNzdiYWRkOGM2NzhjNDhAZw&amp;tmsrc=c_0e9c0ddf4b3b277f2aee33f2649cc3e0030a69256db642594a77badd8c678c48%40group.calendar.google.com&amp;scp=ALL" target="_blank" rel="noopener noreferrer">Winglang Community Meeting</a> is our bi-weekly gathering where members of our community showcase cool apps, demos, and other projects! The upcoming session is scheduled for <strong>Tuesday, December 19th, at 2:30 PM UTC</strong>. We look forward to seeing you there!</li>
<li><a href="https://calendar.google.com/calendar/event?action=TEMPLATE&amp;tmeid=ZnFtM3NrbHM0NGZqdTNjZGdyMDg2bHVidXBfMjAyMzEyMThUMTIwMDAwWiBjXzBlOWMwZGRmNGIzYjI3N2YyYWVlMzNmMjY0OWNjM2UwMDMwYTY5MjU2ZGI2NDI1OTRhNzdiYWRkOGM2NzhjNDhAZw&amp;tmsrc=c_0e9c0ddf4b3b277f2aee33f2649cc3e0030a69256db642594a77badd8c678c48%40group.calendar.google.com&amp;scp=ALL" target="_blank" rel="noopener noreferrer">Monday Office Hours</a> is our bi-weekly opportunity for you to share your feedback, thoughts, concerns, or simply drop by to say hi.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" href="https://www.winglang.io/blog/2024/03/13/magazine-008#summary">​</a></h3>
<p>That's it for this edition!</p>
<p>You are invited to join the <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">Wing Discord</a>! Come say hello and hang out with fellow Wingnuts!
Give <a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">winglang.io</a> a visit and take Wing out for a spin. If you're not already, stay updated on the latest changes in our <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">repo</a>.</p>
<p>Catch you in the next update!</p>
<p><strong>The Wing Team</strong></p>
</reactplayer>]]></content:encoded>
            <author>eladb@wing.cloud (Elad Ben-Israel)</author>
            <author>markm@wing.cloud (Mark McCulloh)</author>
            <author>revitalb@wing.cloud (Revital Barletz)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>winglang</category>
            <category>changelog</category>
            <category>newsletter</category>
        </item>
        <item>
            <title><![CDATA[Implementing a Production-Grade CRUD REST API with Winglang]]></title>
            <link>https://www.winglang.io/blog/2024/03/12/crud-rest-api</link>
            <guid>https://www.winglang.io/blog/2024/03/12/crud-rest-api</guid>
            <pubDate>Tue, 12 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Impementing a CRUD REST API using Winglang]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="Cover Art" src="https://www.winglang.io/assets/images/asher-blog2-cover-art-e4841dc79d34d47ff820d7b085b099b8.png" width="1456" height="816" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="abstract">Abstract<a class="hash-link" aria-label="Direct link to Abstract" title="Direct link to Abstract" href="https://www.winglang.io/blog/2024/03/12/crud-rest-api#abstract">​</a></h2>
<p>This is an experience report on the initial steps of implementing a CRUD (Create, Read, Update, Delete) REST API in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>, with a focus on addressing typical production environment concerns such as secure authentication, <a href="https://en.wikipedia.org/wiki/Observability_(software)" target="_blank" rel="noopener noreferrer">observability</a>, and error handling. It highlights how <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>'s distinctive features, particularly the separation of <a href="https://www.winglang.io/docs/concepts/inflights" target="_blank" rel="noopener noreferrer">Preflight</a> cloud resource configuration from <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">Inflight</a> API request handling, can facilitate more efficient integration of essential <a href="https://en.wikipedia.org/wiki/Middleware" target="_blank" rel="noopener noreferrer">middleware</a> components like logging and error reporting. This balance aims to reduce overall complexity and minimize the resulting code size. The applicability of various design patterns, including <a href="https://patterns.eecs.berkeley.edu/?page_id=19" target="_blank" rel="noopener noreferrer">Pipe-and-Filters</a>, <a href="https://en.wikipedia.org/wiki/Decorator_pattern" target="_blank" rel="noopener noreferrer">Decorator</a>, and <a href="https://en.wikipedia.org/wiki/Factory_method_pattern" target="_blank" rel="noopener noreferrer">Factory</a>, is evaluated. Finally, future directions for developing a fully-fledged <a href="https://en.wikipedia.org/wiki/Middleware" target="_blank" rel="noopener noreferrer">middleware</a> library for <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> are identified.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="introduction">Introduction<a class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction" href="https://www.winglang.io/blog/2024/03/12/crud-rest-api#introduction">​</a></h2>
<p>In my <a href="https://medium.com/itnext/hello-winglang-hexagon-6f2bdb550f37" target="_blank" rel="noopener noreferrer">previous publication</a>, I reported on my findings about the possible implementation of the <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Ports and Adapters</a> pattern in the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> programming language using the simplest possible <code>GreetingService</code> sample application. The main conclusions from this evaluation were:</p>
<ol>
<li>Cloud resources, such as API Gateway, play the role of drivers (in-) and driven (out-) Ports</li>
<li>Event handling functions play the role of Adapters leading to a pure Core, that might be implemented in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>, <a href="https://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer">TypeScript</a>, and in fact in any programming language, that compiles into <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank" rel="noopener noreferrer">JavaScript</a> and runs on the <a href="https://nodejs.org/en" target="_blank" rel="noopener noreferrer">NodeJS</a> runtime engine</li>
</ol>
<p>Initially, I planned to proceed with exploring possible ways of implementing a more general <a href="https://en.wikipedia.org/wiki/Staged_event-driven_architecture" target="_blank" rel="noopener noreferrer">Staged Event-Driven Architecture (SEDA)</a> architecture in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>. However, using the simplest possible <code>GreetingService</code> as an example left some very important architectural questions unanswered. Therefore I decided to explore in more depth what is involved in implementing a typical <a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete" target="_blank" rel="noopener noreferrer">Create/Retrieve/Update/Delete (CRUD)</a> service exposing standardized <a href="https://en.wikipedia.org/wiki/REST" target="_blank" rel="noopener noreferrer">REST API</a> and addressing typical production environment concerns such as secure authentication, <a href="https://en.wikipedia.org/wiki/Observability_(software)" target="_blank" rel="noopener noreferrer">observability</a>, error handling, and reporting.</p>
<p>To prevent domain-specific complexity from distorting the focus on important architectural considerations, I chose the simplest possible TODO service with four operations:</p>
<ol>
<li>Retrieve all Tasks (per user)</li>
<li>Create a new Task</li>
<li>Completely Replace an existing Task definition</li>
<li>Delete an existing Task</li>
</ol>
<p>Using this simple example allowed me to evaluate many important architectural options and to to come up with an initial prototype of a <a href="https://en.wikipedia.org/wiki/Middleware" target="_blank" rel="noopener noreferrer">middleware</a> library for the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> programming language compatible with and potentially surpassing popular libraries for mainstream programming languages, such as <a href="https://middy.js.org/" target="_blank" rel="noopener noreferrer">Middy</a> for <a href="https://nodejs.org/en" target="_blank" rel="noopener noreferrer">Node.js</a> middleware engine for AWS Lambda and <a href="https://github.com/aws-powertools" target="_blank" rel="noopener noreferrer">AWS Power Tools for Lambda</a>.</p>
<p>Unlike my <a href="https://medium.com/itnext/hello-winglang-hexagon-6f2bdb550f37" target="_blank" rel="noopener noreferrer">previous publication</a>, I will not describe the step-by-step process of how I arrived at the current arrangement. Software architecture and design processes are rarely linear, especially beyond beginner-level tutorials. Instead, I will describe a starting point solution, which, while far from final, is representative enough to sense the direction in which the final framework might eventually evolve. I will outline the requirements, I wanted to address, the current architectural decisions, and highlight directions for future research.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="simple-todo-in-winglang">Simple TODO in Winglang<a class="hash-link" aria-label="Direct link to Simple TODO in Winglang" title="Direct link to Simple TODO in Winglang" href="https://www.winglang.io/blog/2024/03/12/crud-rest-api#simple-todo-in-winglang">​</a></h2>
<p>Developing a simple, prototype-level TODO REST API service in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> is indeed very easy, and could be done within half an hour, using the <a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">Winglang Playground</a>:</p>
<p><img decoding="async" loading="lazy" alt="Wing Playground" src="https://www.winglang.io/assets/images/ashers-blog2-1-f7a1b34ab9cafd0c6c8e4bef663316bc.png" width="2000" height="901" class="img_ev3q"></p>
<p>To keep things simple, I put everything in one source, even though, it of course could be split into Core, Ports, and Adapters. Let’s look at the major parts of this sample.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resource-ports-definition">Resource (Ports) Definition<a class="hash-link" aria-label="Direct link to Resource (Ports) Definition" title="Direct link to Resource (Ports) Definition" href="https://www.winglang.io/blog/2024/03/12/crud-rest-api#resource-ports-definition">​</a></h2>
<p>First, we need to define cloud resources, aka Ports, that we are going to use. This this is done as follows:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring ex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> tasks </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Table</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Tasks"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  columns</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"id"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> ex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ColumnType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">STRING</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"title"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> ex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ColumnType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">STRING</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  primaryKey</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"id"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> counter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> api </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> path </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"/tasks"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Here we define a <a href="https://www.winglang.io/docs/standard-library/ex/table" target="_blank" rel="noopener noreferrer">Winglang Table</a> to keep TODO Tasks with only two columns: task ID and title. To keep things simple, we implement task ID as an auto-incrementing number using the <a href="https://www.winglang.io/docs/standard-library/cloud/counter" target="_blank" rel="noopener noreferrer">Winglang <code>Counter</code></a> resource. And finally, we expose the TODO Service API using the <a href="https://www.winglang.io/docs/standard-library/cloud/api" target="_blank" rel="noopener noreferrer">Winglang <code>Api</code></a> resource.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="api-request-handlers-adapters">API Request Handlers (Adapters)<a class="hash-link" aria-label="Direct link to API Request Handlers (Adapters)" title="Direct link to API Request Handlers (Adapters)" href="https://www.winglang.io/blog/2024/03/12/crud-rest-api#api-request-handlers-adapters">​</a></h2>
<p>Now, we are going to define a separate handler function for each of the four REST API requests. Getting a list of all tasks is implemented as:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> rows </span><span class="token operator">=</span><span class="token plain"> tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">list</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">var</span><span class="token plain"> result </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">MutArray</span><span class="token operator">&lt;</span><span class="token maybe-class-name">Json</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> row </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> rows </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">push</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">row</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"application/json"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Creating a new task record is implemented as:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">post</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> id </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"{counter.inc()}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> task </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryParse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> record </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        id</span><span class="token operator">:</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        title</span><span class="token operator">:</span><span class="token plain"> task</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"title"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">asStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">insert</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> record</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"application/json"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">record</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">400</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"text/plain"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Bad Request"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Updating an existing task is implemented as:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">put</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"{path}/:id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> id </span><span class="token operator">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">vars</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> task </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryParse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> record </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        id</span><span class="token operator">:</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        title</span><span class="token operator">:</span><span class="token plain"> task</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"title"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">asStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">update</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> record</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"application/json"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">record</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">400</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"text/plain"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Bad Request"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Finally, deleting an existing task is implemented as:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">delete</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"{path}/:id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> id </span><span class="token operator">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">vars</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">delete</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"text/plain"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>We could play with this API using the <a href="https://www.winglang.io/docs/tools/wing-console" target="_blank" rel="noopener noreferrer">Winglang Simulator</a>:</p>
<p><img decoding="async" loading="lazy" alt="Wing Console" src="https://www.winglang.io/assets/images/ashers-blog2-2-d4716ce0290ae872cd7e5f728adbbaa1.png" width="2000" height="1028" class="img_ev3q"></p>
<p>We could write one or more tests to validate the API automatically:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> url </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"{api.url}{path}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"run simple crud scenario"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> r1 </span><span class="token operator">=</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">r1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> r1_tasks </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">r1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">nil</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">r1_tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryGetAt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> r2 </span><span class="token operator">=</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">post</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">title</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"First Task"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">r2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> r2_task </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">r2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">r2_task</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"title"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">asStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"First Task"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> id </span><span class="token operator">=</span><span class="token plain"> r2_task</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">asStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> r3 </span><span class="token operator">=</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">put</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{url}/{id}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">title</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"First Task Updated"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">r3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> r3_task </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">r3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">r3_task</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"title"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">asStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"First Task Updated"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> r4 </span><span class="token operator">=</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">delete</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{url}/{id}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">r4</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Last but not least, this service can be deployed on any supported cloud platform using the <a href="https://www.winglang.io/docs/tools/cli" target="_blank" rel="noopener noreferrer">Winglang CLI</a>. The code for the TODO Service is completely cloud-neutral, ensuring compatibility across different platforms without modification.</p>
<p>Should there be a need to expand the task details or link them to other system entities, the approach remains largely unaffected, provided the operations adhere to straightforward CRUD logic and can be executed within a 29-second timeout limit.</p>
<p>This example unequivocally demonstrates that the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> programming environment is a top-notch tool for the rapid development of such services. If this is all you need, you need not read further. What follows is a kind of White Rabbit hole of multiple non-functional concerns that need to be addressed before we can even start talking about serious production deployment.</p>
<blockquote>
<p>You are warned. The forthcoming text is not for everybody, but rather for seasoned cloud software architects.</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="Architect" src="https://www.winglang.io/assets/images/ashers-blog2-3-b37cdb5082ee471419a277b08070c57a.png" width="2000" height="2000" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="usability">Usability<a class="hash-link" aria-label="Direct link to Usability" title="Direct link to Usability" href="https://www.winglang.io/blog/2024/03/12/crud-rest-api#usability">​</a></h2>
<p>TODO sample service implementation presented above belongs to the so-called Headless REST API. This approach focuses on core functionality, leaving user experience design to separate layers. This is often implemented as <a href="https://www.patterns.dev/react/client-side-rendering" target="_blank" rel="noopener noreferrer">Client-Side Rendering</a> or <a href="https://www.patterns.dev/react/server-side-rendering" target="_blank" rel="noopener noreferrer">Server Side Rendering</a> with an intermediate <a href="https://bff-patterns.com/" target="_blank" rel="noopener noreferrer">Backend for Frontend</a> tier, or by using multiple narrow-focused REST API services functioning as <a href="https://www.apollographql.com/docs/apollo-server/data/resolvers/" target="_blank" rel="noopener noreferrer">GraphQL Resolvers</a>. Each approach has its merits for specific contexts.</p>
<p>I advocate for supporting <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation" target="_blank" rel="noopener noreferrer">HTTP Content Negotiation</a> and providing a minimal UI for direct API interaction via a browser. While tools like <a href="https://www.postman.com/" target="_blank" rel="noopener noreferrer">Postman</a> or <a href="https://swagger.io/" target="_blank" rel="noopener noreferrer">Swagger</a> can facilitate API interaction, experiencing the API as an end user offers invaluable insights. This basic UI, or what I refer to as an "engineering UI," often suffices.</p>
<p>In this context, anything beyond simple <a href="https://www.patterns.dev/react/server-side-rendering" target="_blank" rel="noopener noreferrer">Server Side Rendering</a> deployed alongside headless protocol serialization, such as JSON, might be unnecessarily complex. While <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> provides support for <a href="https://www.winglang.io/docs/standard-library/cloud/website" target="_blank" rel="noopener noreferrer"><code>Website</code></a> cloud resource for web client assets (HTML pages, JavaScript, CSS), utilizing it for such purposes introduces additional complexity and cost.</p>
<p>A simpler solution would involve basic HTML templates, enhanced with <a href="https://htmx.org/" target="_blank" rel="noopener noreferrer">HTMX</a>'s features and a CSS framework like <a href="https://getbootstrap.com/" target="_blank" rel="noopener noreferrer">Bootstrap</a>. Currently, <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> does not natively support HTML templates, but for basic use cases, this can be easily managed with <a href="https://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer">TypeScript</a>. For instance, rendering a single task line could be implemented as follows:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">TaskData</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"core/task"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">formatTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">path</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> task</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">TaskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">    &lt;li class="list-group-item d-flex justify-content-between align-items-center"&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">        &lt;form hx-put="</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">path</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">task</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">taskID</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">" hx-headers='{"Accept": "text/plain"}' id="</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">task</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">taskID</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">-form"&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            &lt;span class="task-text"&gt;</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">task</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">title</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">&lt;/span&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            &lt;input </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                type="text"</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                name="title"</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                class="form-control edit-input" </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                style="display: none;" </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                value="</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">task</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">title</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">"&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">        &lt;/form&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">        &lt;div class="btn-group"&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            &lt;button class="btn btn-danger btn-sm delete-btn" </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                hx-delete="</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">path</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">task</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">taskID</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">" </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                hx-target="closest li" </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                hx-swap="outerHTML" </span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                hx-headers='{"Accept": "text/plain"}'&gt;✕&lt;/button&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            &lt;button class="btn btn-primary btn-sm edit-btn"&gt;✎&lt;/button&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">        &lt;/div&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">    &lt;/li&gt;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">    </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>That would result in the following UI screen:</p>
<p><img decoding="async" loading="lazy" alt="Asher Sterkin Tasks" src="https://www.winglang.io/assets/images/ashers-blog2-4-3f58770c7113ac27f233188669dd9617.png" width="1850" height="1075" class="img_ev3q"></p>
<p>Not super-fancy, but good enough for demo purposes.</p>
<p>Even purely Headless REST APIs require strong usability considerations. API calls should follow <a href="https://en.wikipedia.org/wiki/REST" target="_blank" rel="noopener noreferrer">REST conventions</a> for HTTP methods, URL formats, and payloads. Proper documentation of <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods" target="_blank" rel="noopener noreferrer">HTTP methods</a> and potential error handling are crucial. Client and server errors need to be logged, converted into appropriate <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" target="_blank" rel="noopener noreferrer">HTTP status codes</a>, and accompanied by clear explanation messages in the response body.</p>
<p>The need to handle multiple request parsers and response formatters based on content negotiation using Content-Type and Accept headers in HTTP requests led me to the following design approach:</p>
<p><img decoding="async" loading="lazy" alt="Diagram" src="https://www.winglang.io/assets/images/ashers-blog2-5-a7420a126d6328173f89638a13f375a3.png" width="1920" height="1080" class="img_ev3q"></p>
<p>Adhering to the <a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle" target="_blank" rel="noopener noreferrer">Dependency Inversion Principle</a> ensures that the system Core is completely isolated from Ports and Adapters. While there might be an inclination to encapsulate the Core within a generic CRUD framework, defined by a <code>ResourceData</code> type, I advise caution. This recommendation stems from several considerations:</p>
<ol>
<li>In practice, even CRUD request processing often entails complexities that extend beyond basic operations.</li>
<li>The Core should not rely on any specific framework, preserving its independence and adaptability.</li>
<li>The creation of such a framework would necessitate support for <a href="https://en.wikipedia.org/wiki/Generic_programming" target="_blank" rel="noopener noreferrer">Generic Programming</a>, a feature not currently supported by <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>.</li>
</ol>
<p>Another option would be to abandon the Core data types definition and rely entirely on untyped JSON interfaces, akin to a Lisp-like programming style. However, given <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>'s strong typing, I decided against this approach.</p>
<p>Overall, the <code>TodoServiceHandler</code> is quite simple and easy to understand:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./data.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./parser.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./formatter.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">TodoHandler</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _path</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _parser</span><span class="token operator">:</span><span class="token plain"> parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">TodoParser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _tasks</span><span class="token operator">:</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ITaskDataRepository</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    _formatter</span><span class="token operator">:</span><span class="token plain"> formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ITodoFormatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        path</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        tasks_</span><span class="token operator">:</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ITaskDataRepository</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        parser</span><span class="token operator">:</span><span class="token plain"> parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">TodoParser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        formatter</span><span class="token operator">:</span><span class="token plain"> formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ITodoFormatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_path</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tasks</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> tasks_</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_parser</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_formatter</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">getHomePage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> outFormat</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> userData </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parseUserData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">formatHomePage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">outFormat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> userData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">getAllTasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> query</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> outFormat</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> userData </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parseUserData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> tasks </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">getTasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">userData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">userID</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">formatTasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">outFormat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">createTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				user</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				body</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				inFormat</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				outFormat</span><span class="token operator">:</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> taskData </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parsePartialTaskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">addTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">taskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_formatter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">formatTasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">outFormat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">taskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">replaceTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				user</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				id</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				body</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				inFormat</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">				outFormat</span><span class="token operator">:</span><span class="token plain"> str</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> taskData </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parseFullTaskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">replaceTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">taskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> taskData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">title</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">deleteTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> id</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> userData </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_parser</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parseUserData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">user</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_tasks</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">deleteTask</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">userData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">userID</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> num</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>As you might notice, the code structure deviates slightly from the design diagram presented earlier. These minor adaptations are normal in software design; new insights emerge throughout the process, necessitating adjustments. The most notable difference is the <code>user: Json</code> argument defined for every function. We'll discuss the purpose of this argument in the next section.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="security">Security<a class="hash-link" aria-label="Direct link to Security" title="Direct link to Security" href="https://www.winglang.io/blog/2024/03/12/crud-rest-api#security">​</a></h2>
<p>Exposing the TODO service to the internet without security measures is a recipe for disaster. Hackers, bored teens, and professional attackers will quickly target its public IP address. The rule is very simple:</p>
<blockquote>
<p>any public interface <strong>must</strong> be protected unless exposed for a very short testing period. Security is non-negotiable.</p>
</blockquote>
<p>Conversely, overloading a service with every conceivable security measure can lead to prohibitively high operational costs. As I've argued in <a href="https://medium.com/@asher-sterkin/aws-mapu-65e888009916" target="_blank" rel="noopener noreferrer">previous writings</a>, making architects accountable for the costs of their designs might significantly reshape their approach:</p>
<blockquote>
<p>If cloud solution architects were responsible for the costs incurred by their systems, it could fundamentally change their design philosophy.</p>
</blockquote>
<p>What we need, is a reasonable protection of the service API, not less but not more either. Since I wanted to experiment with full-stack <a href="https://www.patterns.dev/react/server-side-rendering" target="_blank" rel="noopener noreferrer">Service Side Rendering</a> UI my natural choice was to enforce user login at the beginning, to produce a <a href="https://en.wikipedia.org/wiki/JSON_Web_Token" target="_blank" rel="noopener noreferrer">JWT Token</a> with reasonable expiration, say one hour, and then to use it for authentication of all forthcoming HTTP requests.</p>
<p>Due to the <a href="https://www.patterns.dev/react/server-side-rendering" target="_blank" rel="noopener noreferrer">Service Side Rendering</a> rendering specifics using <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies" target="_blank" rel="noopener noreferrer">HTTP Cookie</a> to carry over the session token was a natural (to be honest suggested by <a href="https://openai.com/blog/chatgpt/" target="_blank" rel="noopener noreferrer">ChatGPT</a>) choice. For the <a href="https://www.patterns.dev/react/client-side-rendering" target="_blank" rel="noopener noreferrer">Client-Side Rendering</a> option, I might need to use the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication" target="_blank" rel="noopener noreferrer">Bearer Token</a> delivered via the HTTP Request headers Authorization field.</p>
<p>With session tokens now incorporating user information, I could aggregate TODO tasks by the user. Although there are numerous methods to integrate session data, including user details into the domain, I chose to focus on <code>userID</code> and <code>fullName</code> attributes for this study.</p>
<p>For user authentication, several options are available, especially within the AWS ecosystem:</p>
<ol>
<li><a href="https://aws.amazon.com/cognito/" target="_blank" rel="noopener noreferrer">AWS Cognito</a>, utilizing its User Pools or integration with external Identity Providers like Google or Facebook.</li>
<li>Third-party authentication services such as <a href="https://auth0.com/" target="_blank" rel="noopener noreferrer">Auth0</a>.</li>
<li>A custom authentication service fully developed in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>.</li>
<li><a href="https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html" target="_blank" rel="noopener noreferrer">AWS Identity Center</a></li>
<li>…</li>
</ol>
<p>As an independent software technology researcher, I gravitate towards the simplest solutions with the fewest components, which also address daily operational needs. Leveraging the <a href="https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html" target="_blank" rel="noopener noreferrer">AWS Identity Center</a>, as detailed in a <a href="https://medium.com/@asher-sterkin/aws-mapu-65e888009916" target="_blank" rel="noopener noreferrer">separate publication</a>, was a logical step due to my existing multi-account/multi-user setup.</p>
<p>After integration, my <a href="https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html" target="_blank" rel="noopener noreferrer">AWS Identity Center</a> main screen looks like this:</p>
<p><img decoding="async" loading="lazy" alt="AWS Identity Center Image" src="https://www.winglang.io/assets/images/ashers-blog2-6-5aa63692569cbbeae54aa258fe1616a3.png" width="1800" height="886" class="img_ev3q"></p>
<p>That means that in my system, users, myself, or guests, could use the same AWS credentials for development, administration, and sample or housekeeping applications.</p>
<p>To integrate with <a href="https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html" target="_blank" rel="noopener noreferrer">AWS Identity Center</a> I needed to <a href="https://docs.aws.amazon.com/singlesignon/latest/userguide/customermanagedapps-saml2-setup.html#customermanagedapps-set-up-your-own-app-saml2" target="_blank" rel="noopener noreferrer">register my application</a> and provide a new endpoint implementing the so-called “<a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-saml.html" target="_blank" rel="noopener noreferrer">Assertion Consumer Service URL (ACS URL)</a>”. This publication is not about the <a href="https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language" target="_blank" rel="noopener noreferrer">SAML</a> standard. It would suffice to say that with <a href="https://openai.com/blog/chatgpt/" target="_blank" rel="noopener noreferrer">ChatGPT</a> and Google search assistance, it could be done. Some useful information can be found <a href="https://blog.purple-technology.com/how-to-build-serverless-app-with-saml-auth-via-aws-iam-identity-center/" target="_blank" rel="noopener noreferrer">here</a>. What came very handy was a <a href="https://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer">TypeScript</a> <a href="https://samlify.js.org/#/" target="_blank" rel="noopener noreferrer">samlify</a> library which encapsulates the whole heavy lifting of the <a href="https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language" target="_blank" rel="noopener noreferrer">SAML</a> Login Response validation process.</p>
<p>What I’m mostly interested in is how this variability point affects the overall system design. Let’s try to visualize it using a semi-formal data flow notation:</p>
<p><img decoding="async" loading="lazy" alt="AWS Identity Center 2" src="https://www.winglang.io/assets/images/ashers-blog2-7-45246842b1b45e9cd1d312509667ef74.png" width="1920" height="1080" class="img_ev3q"></p>
<p>While it might seem unusual this representation reflects with high fidelity how data flows through the system. What we see here is a special instance of the famous <a href="https://patterns.eecs.berkeley.edu/?page_id=19" target="_blank" rel="noopener noreferrer">Pipe-and-Filters</a> architectural pattern.</p>
<p>Here, data flows through a pipeline and each filter performs one well-defined task in fact following the <a href="https://en.wikipedia.org/wiki/Single_responsibility_principle" target="_blank" rel="noopener noreferrer">Single Responsibility Principle</a>. Such an arrangement allows me to replace filters should I want to switch to a simple <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication" target="_blank" rel="noopener noreferrer">Basic HTTP Authentication</a>, to use the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization" target="_blank" rel="noopener noreferrer">HTTP Authorization header</a>, or use a different secret management policy for <a href="https://en.wikipedia.org/wiki/JSON_Web_Token" target="_blank" rel="noopener noreferrer">JWT token</a> building and validation.</p>
<p>If we zoom into Parse and Format filters, we will see a typical dispatch logic using <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type" target="_blank" rel="noopener noreferrer">Content-Type</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept" target="_blank" rel="noopener noreferrer">Accept</a> HTTP headers respectively:</p>
<p><img decoding="async" loading="lazy" alt="Content Diagram" src="https://www.winglang.io/assets/images/ashers-blog2-8-f6796d404e8315a434599453a5e5422f.png" width="1920" height="529" class="img_ev3q"></p>
<p>Many engineers confuse design and architectural patterns with specific implementations. This misses the essence of what patterns are meant to achieve.</p>
<p>Patterns are about identifying a suitable approach to balance conflicting forces with minimal intervention. In the context of building cloud-based software systems, where security is paramount but should not be overpriced in terms of cost or complexity, this understanding is crucial. The <a href="https://patterns.eecs.berkeley.edu/?page_id=19" target="_blank" rel="noopener noreferrer">Pipe-and-Filters</a> design pattern helps with addressing such design challenges effectively. It allows for modularization and flexible configuration of processing steps, which in this case, relate to authentication mechanisms.</p>
<p>For instance, while robust security measures like <a href="https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language" target="_blank" rel="noopener noreferrer">SAML</a> authentication are necessary for production environments, they may introduce unnecessary complexity and overhead in scenarios such as automated end-to-end testing. Here, simpler methods like <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication" target="_blank" rel="noopener noreferrer">Basic HTTP Authentication</a> may suffice, providing a quick and cost-effective solution without compromising the system's overall integrity. The goal is to maintain the system's core functionality and code base uniformity while varying the
authentication strategy based on the environment or specific requirements.</p>
<p><a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>'s unique <a href="https://www.winglang.io/docs/concepts/inflights" target="_blank" rel="noopener noreferrer">Preflight</a> compilation feature facilitates this by allowing for configuration
adjustments at the build stage, eliminating runtime overhead. This capability presents a significant advantage of <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>-based solutions over other middleware libraries, such as <a href="https://middy.js.org/" target="_blank" rel="noopener noreferrer">Middy</a> and <a href="https://github.com/aws-powertools" target="_blank" rel="noopener noreferrer">AWS Power Tools for Lambda</a>, by offering a more efficient and flexible approach to managing the authentication pipeline.</p>
<p>Implementing <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication" target="_blank" rel="noopener noreferrer">Basic HTTP Authentication</a>, therefore, only requires modifying a single filter within the authentication pipeline, leaving the remainder of the system unchanged:</p>
<p><img decoding="async" loading="lazy" alt="Basic HTTP Auth" src="https://www.winglang.io/assets/images/ashers-blog2-9-951db377002e4cb51c921a69d1fe4338.png" width="1920" height="796" class="img_ev3q"></p>
<p>Due to some technical limitations, it’s currently not possible to implement <a href="https://patterns.eecs.berkeley.edu/?page_id=19" target="_blank" rel="noopener noreferrer">Pipe-and-Filters</a> in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> directly, but it could be quite easily simulated by a combination of <a href="https://en.wikipedia.org/wiki/Decorator_pattern" target="_blank" rel="noopener noreferrer">Decorator</a> and <a href="https://en.wikipedia.org/wiki/Factory_method_pattern" target="_blank" rel="noopener noreferrer">Factory</a> design patterns. How exactly, we will see shortly. Now, let’s proceed to the next topic.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="operation">Operation<a class="hash-link" aria-label="Direct link to Operation" title="Direct link to Operation" href="https://www.winglang.io/blog/2024/03/12/crud-rest-api#operation">​</a></h2>
<p>In this publication, I’m not going to cover all aspects of production operation. The topic is large and deserves a separate publication of its own. Below, is presented what I consider as a bare minimum:</p>
<p><img decoding="async" loading="lazy" alt="Operation Diagram" src="https://www.winglang.io/assets/images/ashers-blog2-10-f62179a51aee86b94d64c9d00915d4c6.png" width="1080" height="1920" class="img_ev3q"></p>
<p>To operate a service we need to know what happens with it, especially when something goes wrong. This is achieved via a <a href="https://opentelemetry.io/docs/specs/otel/logs/data-model/" target="_blank" rel="noopener noreferrer">Structured Logging</a> mechanism. At the moment, <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> provides only a basic <code>log(str)</code> function. For my investigation, I need more and implemented a poor man-structured logging class</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// A poor man implementation of configurable Logger</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Similar to that of Python and TypeScript</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./dateTime.w"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> dateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">enum</span><span class="token plain"> logging </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token constant" style="color:rgb(189, 147, 249)">TRACE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token constant" style="color:rgb(189, 147, 249)">DEBUG</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token constant" style="color:rgb(189, 147, 249)">INFO</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token constant" style="color:rgb(189, 147, 249)">WARNING</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token constant" style="color:rgb(189, 147, 249)">ERROR</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token constant" style="color:rgb(189, 147, 249)">FATAL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">//This is just enough configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">//A serious review including compliance</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">//with OpenTelemetry and privacy regulations</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">//Is required. The main insight:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">//Serverless Cloud logging is substantially</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">//different</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">interface</span><span class="token plain"> </span><span class="token class-name">ILoggingStrategy</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  inflight </span><span class="token function" style="color:rgb(80, 250, 123)">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  inflight </span><span class="token function" style="color:rgb(80, 250, 123)">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">DefaultLoggerStrategy</span><span class="token plain"> impl </span><span class="token maybe-class-name">ILoggingStrategy</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> dateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">DateTime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">toUtcString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Datetime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">utcNow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{message}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">//TBD: probably should go into a separate module</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring ex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">MockLoggerStrategy</span><span class="token plain"> impl </span><span class="token maybe-class-name">ILoggingStrategy</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  _name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  _counter</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  _messages</span><span class="token operator">:</span><span class="token plain"> ex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Table</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_name</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> name </span><span class="token operator">??</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MockLogger"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_counter</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Counter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_messages</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access maybe-class-name" style="color:rgb(80, 250, 123)">Table</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"{this._name}Messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      columns</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">ex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ColumnType</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"id"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> ex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ColumnType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">STRING</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"message"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> ex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ColumnType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">STRING</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      primaryKey</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"id"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"{this._counter.inc(1, this._name)}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">messages</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token maybe-class-name">Json</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> message </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> messages </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_messages</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">insert</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	      message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"timestamp"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">asStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	      </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"{message}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> expected </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_messages</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	    message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"timestamp"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">asStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"message"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">asStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{message}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> expected</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Logger</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  _labels</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  _levels</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">logging</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  _level</span><span class="token operator">:</span><span class="token plain"> num</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  _service</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  _strategy</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">ILoggingStrategy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">level</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> service</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> strategy</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">ILoggingStrategy</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_labels</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"TRACE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"DEBUG"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"INFO"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"WARNING"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"ERROR"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"FATAL"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_levels</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token known-class-name class-name">Array</span><span class="token operator">&lt;</span><span class="token plain">logging</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TRACE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEBUG</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">INFO</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">WARNING</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">ERROR</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">FATAL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_level</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_levels</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">indexOf</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_service</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_strategy</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> strategy </span><span class="token operator">??</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">DefaultLoggerStrategy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">level_</span><span class="token operator">:</span><span class="token plain"> logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> func</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> level </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_levels</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">indexOf</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">level_</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> label </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_labels</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">at</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">level</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_level</span><span class="token plain"> </span><span class="token operator">&lt;=</span><span class="token plain"> level </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_strategy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        timestamp</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_strategy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        level</span><span class="token operator">:</span><span class="token plain"> label</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        service</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">_service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token operator">:</span><span class="token plain"> func</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        message</span><span class="token operator">:</span><span class="token plain"> message</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">trace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">func</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TRACE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> func</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">debug</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">func</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DEBUG</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> func</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">info</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">func</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">INFO</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> func</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">warning</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">func</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">WARNING</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> func</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">func</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">ERROR</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> func</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">fatal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">func</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">logging</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">FATAL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> func</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>There is nothing spectacular here and, as I wrote in the comments, a cloud-based logging system requires a serious revision. Still, it’s enough for the current investigation. I’m fully convinced that logging is an integral part of any service specification and has to be tested with the same rigor as core functionality. For that purpose, I developed a simple mechanism to mock logs and check them against expectations.</p>
<p>For a REST API CRUD service, we need to log at least three types of things:</p>
<ol>
<li>HTTP Request</li>
<li>Original Error message if something wrong happened</li>
<li>HTTP Response</li>
</ol>
<p>In addition, depending on needs the original error message might need to be converted into a standard one, for example in order not to educate attackers.</p>
<p>How much if any details to log depends on multiple factors: deployment target, type of request, specific user, type of error, statistical sampling, etc. In development and test mode, we will normally opt for logging almost everything and returning the original error message directly to the client screen to ease debugging. In production mode, we might opt for removing some sensitive data because of regulation requirements, to return a general error message, such as “Bad Request”, without any details, and apply only statistical sample logging for particular types of requests <a href="https://aws.amazon.com/blogs/aws-cloud-financial-management/reinvent-2023-cost-optimization-highlights-that-you-were-not-expecting/" target="_blank" rel="noopener noreferrer">to save the cost</a>.</p>
<p>Flexible logging configuration was achieved by injecting four additional filters in every request handling pipeline:</p>
<ol>
<li>HTTP Request logging filter</li>
<li>Try/Catch Decorator to convert exceptions if any into HTTP status codes and to log original error messages (this could be extracted into a separate filter, but I decided to keep things simple)</li>
<li>Error message translator to convert original error messages into standard ones if required</li>
<li>HTTP Response logging filter</li>
</ol>
<p>This structure, although not an ultimate one, provides enough flexibility to implement a wide range of logging and error-handling strategies depending on the service and its deployment target specifics.</p>
<p>As with logs, <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> at the moment provides only a basic <code>throw &lt;str&gt;</code> operator, so I decided to implement my version of a poor man structured exceptions:</p>
<div class="language-tsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-tsx codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// A poor man structured exceptions</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub tag</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub message</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">tag</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">tag</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> tag</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">message</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">raise</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> err </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">fromJson</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> je </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	        je</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"tag"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">asStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	        je</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryGet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"message"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">?.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryAsStr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">	      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub </span><span class="token function" style="color:rgb(80, 250, 123)">toJson</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">//for logging</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">tag</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">tag</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Standard exceptions, similar to those of Python</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">KeyError</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">message</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"KeyError"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">ValueError</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">message</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"ValueError"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">InternalError</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">message</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"InternalError"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">NotImplementedError</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">message</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"NotImplementedError"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">//Two more HTTP-specific, yet useful</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">AuthenticationError</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token comment" style="color:rgb(98, 114, 164)">//aka HTTP 401 Unauthorized</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">message</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"AuthenticationError"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">AuthorizationError</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name">Exception</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">		</span><span class="token comment" style="color:rgb(98, 114, 164)">//aka HTTP 403 Forbidden</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">message</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token operator">?</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"AuthorizationError"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>These experiences highlight how the developer community can bridge gaps in new languages with temporary workarounds. <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> is still evolving, but its innovative features can be harnessed for progress despite the language's age.</p>
<p>Now, it’s time to take a brief look at the last production topic on my list, namely</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="scale">Scale<a class="hash-link" aria-label="Direct link to Scale" title="Direct link to Scale" href="https://www.winglang.io/blog/2024/03/12/crud-rest-api#scale">​</a></h2>
<p>Scaling is a crucial aspect of cloud development, but it's often misunderstood. Some neglect it entirely, leading to problems when the system grows. Others over-engineer, aiming to be a "FANG" system from day one. The proclamation "We run everything on Kubernetes" is a common refrain in technical circles, regardless of whether it's appropriate for the project at hand.</p>
<p>Neither—neglect nor over-engineering— extreme is ideal. Like security, scaling shouldn't be ignored, but it also shouldn't be over-emphasized.</p>
<p>Up to a certain point, cloud platforms provide cost-effective scaling mechanisms. Often, the choice between different options boils down to personal preference or inertia rather than significant technical advantages.</p>
<p>The prudent path involves starting small and cost-effectively, scaling out based on real-world usage and performance data, rather than assumptions. This approach necessitates a system designed for easy configuration changes to accommodate scaling, something not inherently supported by <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> but certainly within the realm of feasibility through further development and research. As an illustration, let's consider scaling within the AWS ecosystem:</p>
<ol>
<li>Initially, a cost-effective and swift deployment might involve a single <a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html" target="_blank" rel="noopener noreferrer">Lambda Function URL</a> for a full-stack CRUD API with <a href="https://www.patterns.dev/react/server-side-rendering" target="_blank" rel="noopener noreferrer">Server-Side Rendering</a>, using an <a href="https://aws.amazon.com/s3/" target="_blank" rel="noopener noreferrer">S3 Bucket</a> for storage. This setup enables rapid feedback essential for early development stages. Personally, I favor a "UX First" approach over "API First." You might be surprised how far you can get with this basic technology stack. While <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> doesn't currently support <a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html" target="_blank" rel="noopener noreferrer">Lambda Function URLs</a>, I believe it could be achieved with filter combinations and system adjustments. At this level, following <a href="https://medium.com/cto-as-a-service/purepwa-a-radical-u-turn-in-web-development-a386c0dc092e" target="_blank" rel="noopener noreferrer">Marc Van Neerven</a>'s recommendation to use standard <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components" target="_blank" rel="noopener noreferrer">Web Components</a> instead of heavy frameworks could be beneficial. This is a subject for future exploration.</li>
<li>Transitioning to an <a href="https://aws.amazon.com/api-gateway/" target="_blank" rel="noopener noreferrer">API Gateway</a> or <a href="https://aws.amazon.com/pm/appsync/?gclid=CjwKCAiAi6uvBhADEiwAWiyRdhl4AiIZkllfejb0Za3YevzuB4xXj1U8QcVcuMecAt89Jf8XIdtVAhoCX70QAvD_BwE&amp;trk=e37f908f-322e-4ebc-9def-9eafa78141b8&amp;sc_channel=ps&amp;ef_id=CjwKCAiAi6uvBhADEiwAWiyRdhl4AiIZkllfejb0Za3YevzuB4xXj1U8QcVcuMecAt89Jf8XIdtVAhoCX70QAvD_BwE:G:s&amp;s_kwcid=AL!4422!3!647301987556!e!!g!!aws%20appsync!19613610159!148358960849" target="_blank" rel="noopener noreferrer">GraphQL Gateway</a> becomes relevant when external API exposure or advanced features like <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" target="_blank" rel="noopener noreferrer">WebSockets</a> are required. If the initial data storage solution becomes a bottleneck, it might be time to consider switching to a more robust and scalable solution like <a href="https://aws.amazon.com/pm/dynamodb/?gclid=CjwKCAiAi6uvBhADEiwAWiyRdsq7X-awzsUATFWptQ2uk-qwYf8je9mBM1kIIigbB2l1PWTdR4fhAxoCw7gQAvD_BwE&amp;trk=5c0a5fc5-4392-49ca-8bcf-f023c39b7463&amp;sc_channel=ps&amp;ef_id=CjwKCAiAi6uvBhADEiwAWiyRdsq7X-awzsUATFWptQ2uk-qwYf8je9mBM1kIIigbB2l1PWTdR4fhAxoCw7gQAvD_BwE:G:s&amp;s_kwcid=AL!4422!3!645125273714!e!!g!!dynamodb!19574556905!145779852912" target="_blank" rel="noopener noreferrer">DynamoDB</a>. At this point, deploying separate Lambda Functions for each API request might offer simplicity in implementation, though it's not always the most cost-effective strategy.</li>
<li>The move to containerized solutions should be data-driven, considered only when there's clear evidence that the function-based architecture is either too costly or suffers from latency issues due to cold starts. An initial foray into containers might involve using <a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html" target="_blank" rel="noopener noreferrer">ECS Fargate</a> for its simplicity and cost-effectiveness, reserving <a href="https://aws.amazon.com/pm/eks/?gclid=CjwKCAiAi6uvBhADEiwAWiyRdhfIT2JlfvVJ21ERRZcgJNNtWy-T871InA7-ZHNwduW8QWDQo9qSZBoC2E4QAvD_BwE&amp;trk=c69c708c-c423-4c07-9fc8-513781540cc7&amp;sc_channel=ps&amp;ef_id=CjwKCAiAi6uvBhADEiwAWiyRdhfIT2JlfvVJ21ERRZcgJNNtWy-T871InA7-ZHNwduW8QWDQo9qSZBoC2E4QAvD_BwE:G:s&amp;s_kwcid=AL!4422!3!669047416746!e!!g!!eks!20433874212!155230227787" target="_blank" rel="noopener noreferrer">EKS</a> for scenarios with specific operational needs that require its capabilities. This evolution should ideally be managed through configuration adjustments and automated filter generation, leveraging <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>'s unique capabilities to support dynamic scaling strategies.</li>
</ol>
<p>In essence, <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>'s approach, emphasizing the <a href="https://www.winglang.io/docs/concepts/inflights" target="_blank" rel="noopener noreferrer">Preflight and Inflight</a> stages, holds promise for facilitating these scaling strategies, although it may still be in the early stages of fully realizing this potential. This exploration of scalability within cloud software development emphasizes starting small, basing decisions on actual data, and remaining flexible in adapting to changing requirements.</p>
<h1>Concluding Remarks</h1>
<p>In the mid-1990s, I learned about <a href="https://www.dre.vanderbilt.edu/~schmidt/PDF/Commonality_Variability.pdf" target="_blank" rel="noopener noreferrer">Commonality Variability Analysis</a> from <a href="https://www.linkedin.com/in/coplien/" target="_blank" rel="noopener noreferrer">Jim Coplien</a>. Since then, this approach, alongside <a href="https://en.wikipedia.org/wiki/Edsger_W._Dijkstra" target="_blank" rel="noopener noreferrer">Edsger W. Dijkstra</a>'s <a href="https://www.eecs.ucf.edu/~eurip/papers/dijkstra-the68.pdf" target="_blank" rel="noopener noreferrer">Layered Architecture</a>, has been a cornerstone of my software engineering practices. <a href="https://www.dre.vanderbilt.edu/~schmidt/PDF/Commonality_Variability.pdf" target="_blank" rel="noopener noreferrer">Commonality Variability Analysis</a> asks: "In our system, which parts will always be the same and which might need to change?" The <a href="https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle" target="_blank" rel="noopener noreferrer">Open-Closed Principle</a> dictates that variable parts should be replaceable without modifying the core system.</p>
<p>Deciding when to finalize the stable aspects of a system involves navigating the trade-off between flexibility and efficiency, with several stages from code generation to runtime offering opportunities for fixation. Dynamic language proponents might delay these decisions to runtime for maximum flexibility, whereas advocates for static, compiled languages typically secure crucial system components as early as possible.</p>
<p><a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>, with its unique <a href="https://www.winglang.io/docs/concepts/inflights" target="_blank" rel="noopener noreferrer">Preflight compilation phase</a>, stands out by allowing cloud resources to be fixed early in the development process. In this publication, I explored how <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> enables addressing non-functional aspects of cloud services through a flexible pipeline of filters, though this granularity introduces its own complexity. The challenge now becomes managing this complexity without compromising the system's efficiency or flexibility.</p>
<p>While the final solution is a work in progress, I can outline a high-level design that balances these forces:</p>
<p><img decoding="async" loading="lazy" alt="Pipeline" src="https://www.winglang.io/assets/images/ashers-blog2-11-d9e83063b06b75a32a44dda2f214a8bd.png" width="1920" height="756" class="img_ev3q"></p>
<p>This design combines several software <a href="https://en.wikipedia.org/wiki/Software_design_pattern" target="_blank" rel="noopener noreferrer">Design Patterns</a> to achieve the desired balance. The process involves:</p>
<ol>
<li>The Pipeline <a href="https://en.wikipedia.org/wiki/Builder_pattern" target="_blank" rel="noopener noreferrer">Builder</a> component is responsible for preparing a final set of <a href="https://www.winglang.io/docs/concepts/inflights" target="_blank" rel="noopener noreferrer">Preflight</a> components.</li>
<li>The Pipeline <a href="https://en.wikipedia.org/wiki/Builder_pattern" target="_blank" rel="noopener noreferrer">Builder</a> reads a Configuration which might be organized as a <a href="https://en.wikipedia.org/wiki/Composite_pattern" target="_blank" rel="noopener noreferrer">Composite</a> (think team-wide or organization-wide configuration).</li>
<li>Configurations specify capability requirements for resources (e.g., loggers).</li>
<li>Each Resource has several <a href="https://en.wikipedia.org/wiki/Specification_pattern" target="_blank" rel="noopener noreferrer">Specifications</a> each one defining conditions under which a <a href="https://en.wikipedia.org/wiki/Factory_method_pattern" target="_blank" rel="noopener noreferrer">Factory</a> needs to be invoked to produce the required <a href="https://patterns.eecs.berkeley.edu/?page_id=19" target="_blank" rel="noopener noreferrer">Filter</a>. Three filter types are envisioned:
<ol>
<li>Row HTTP Request/Response Filter</li>
<li>Extended HTTP Request/Response Filter with session information extracted after token validation</li>
<li>Generic CRUD requests filter to be forwarded to Core</li>
</ol>
</li>
</ol>
<p>This approach shifts complexity towards implementing the Pipeline <a href="https://en.wikipedia.org/wiki/Builder_pattern" target="_blank" rel="noopener noreferrer">Builder</a> machinery and Configuration specification. Experience teaches such machinery could be implemented (described for example in <a href="https://medium.com/python-in-plain-english/generic-composite-in-python-4b88d6727ad0" target="_blank" rel="noopener noreferrer">this publication</a>). That normally requires some generic programming and dynamic import capabilities. Coming up with a good configuration data model is more challenging.</p>
<p>Recent advances in <a href="https://martinfowler.com/articles/exploring-gen-ai.html" target="_blank" rel="noopener noreferrer">generative AI-based copilots</a> raise new questions about achieving the most cost-efficient outcome. To understand the problem, let's revisit the traditional compilation and configuration stack:</p>
<p><img decoding="async" loading="lazy" alt="Code Generator" src="https://www.winglang.io/assets/images/ashers-blog2-12-8a481c31abc3a1a1882c5d2f62522f84.png" width="1920" height="1080" class="img_ev3q"></p>
<p>This general case may not apply to every ecosystem. Here's a breakdown of the typical layers:</p>
<ol>
<li>The Core Language is designed to be small (”C” and Lisp tradition). It may or may not provide support for <a href="https://en.wikipedia.org/wiki/Reflective_programming" target="_blank" rel="noopener noreferrer">Reflection</a>.</li>
<li>As many as possible extended capabilities are provided by Standard Library and 3rd Party Libraries and Frameworks.</li>
<li>Generic Meta-Programming: Support for features like C++ templates or Lisp macros is introduced early (C++, Rust) or later (Java, C#). Generics are a source of ongoing debate:
<ol>
<li>Framework developers find them insufficiently expressive.</li>
<li>Application developers struggle with their complexity.</li>
<li>Scala exemplifies the potential downsides of overly complex generics.</li>
</ol>
</li>
<li>Despite criticism, macros (e.g., C preprocessor) persist as a tool for automated code generation, often compensating for generic limitations.</li>
<li>Third-party vendors (often open-source) provide solutions that enhance or compensate for the standard library, typically using external configuration files (YAML, JSON, etc.).</li>
<li>Specialized generators very often use external blueprints or templates.</li>
</ol>
<p>This complex structure has limitations. Generics can obscure the core language, macros are unsafe, configuration files are poorly disguised scripts, and code generators rely on inflexible static templates. These limitations are why I believe the current trend of <a href="https://platformengineering.org/blog/five-reasons-why-an-internal-developer-platform-is-worth-it" target="_blank" rel="noopener noreferrer">Internal Development Platforms</a> has limited growth potential.</p>
<p>As we look forward to the role of generative AI in streamlining these processes, the question becomes: Can generative <a href="https://martinfowler.com/articles/exploring-gen-ai.html" target="_blank" rel="noopener noreferrer">AI-based copilots</a> not only simplify but also enhance our ability to balance commonality and variability in software engineering?</p>
<p>This is going to be the main topic of my future research to be reported in the next publications. Stay tuned.</p>]]></content:encoded>
            <author>asher.sterkin@gmail.com (Asher Sterkin)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>winglang</category>
            <category>platforms</category>
        </item>
        <item>
            <title><![CDATA[Why are Private API Gateways so hard?]]></title>
            <link>https://www.winglang.io/blog/2024/02/15/private-api-gateways</link>
            <guid>https://www.winglang.io/blog/2024/02/15/private-api-gateways</guid>
            <pubDate>Thu, 15 Feb 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Exploring what private API gateways are and why they're used in the context of the serverless architecture landscape.]]></description>
            <content:encoded><![CDATA[<p>The landscape of serverless architectures is constantly evolving - and the patterns used by developers today range from <a href="https://en.wikipedia.org/wiki/Microservices" target="_blank" rel="noopener noreferrer">microservices</a>, to <a href="https://en.wikipedia.org/wiki/Hexagonal_architecture_(software)" target="_blank" rel="noopener noreferrer">hexagonal architectures</a>, to <a href="https://en.wikipedia.org/wiki/Multitier_architecture" target="_blank" rel="noopener noreferrer">multi-tier architectures</a>, to <a href="https://en.wikipedia.org/wiki/Event-driven_architecture" target="_blank" rel="noopener noreferrer">event-based architectures</a> (EDAs). One of the most important challenges every development team considers when designing and building their system is <a href="https://franklyspeaking.substack.com/p/frankly-speaking-52620-cloud-security" target="_blank" rel="noopener noreferrer">how well it secures their application</a>.</p>
<p>In this post, we’re going to deep dive on the private API gateway pattern: including what a private API gateway entails, its distinct advantages, and why you or your team might opt for this route over other services.</p>
<p>Based on our team’s experience, we’ll be focusing on the capabilities available when building private API gateways on AWS using their managed <a href="https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html" target="_blank" rel="noopener noreferrer">VPC</a> and <a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html" target="_blank" rel="noopener noreferrer">API Gateway</a> services. But many of the lessons will also apply to cloud applications built using Azure’s <a href="https://learn.microsoft.com/en-us/azure/api-management/private-endpoint" target="_blank" rel="noopener noreferrer">API Management service</a> and other major cloud providers.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="understanding-private-api-gateways">Understanding Private API Gateways<a class="hash-link" aria-label="Direct link to Understanding Private API Gateways" title="Direct link to Understanding Private API Gateways" href="https://www.winglang.io/blog/2024/02/15/private-api-gateways#understanding-private-api-gateways">​</a></h2>
<p>If we simplify what a private API gateway is, it's a secure means of exposing a set of APIs within a private network, typically established using a <a href="https://en.wikipedia.org/wiki/Virtual_private_cloud" target="_blank" rel="noopener noreferrer">Virtual Private Cloud</a> (VPC). Let’s first understand each of these.</p>
<p>An API Gateway makes it easy for developers to create, publish, maintain, monitor, and secure large numbers of API endpoints at scale. The gateway provides a central point where you can manage <a href="https://www.tibco.com/glossary/what-is-api-throttling" target="_blank" rel="noopener noreferrer">API throttling</a>, <a href="https://konghq.com/learning-center/api-gateway/api-gateway-authentication" target="_blank" rel="noopener noreferrer">authorization</a>, <a href="https://www.postman.com/api-platform/api-versioning/" target="_blank" rel="noopener noreferrer">API versioning</a>, and monitoring configuration.</p>
<p>On the other hand, a Virtual Private Cloud (or VPC), is a mechanism for creating a logically isolated virtual networking environment. Such a virtual network parallels a network that you’d operate in your own data center, including subnets, IP addressing capabilities, routing tables, and gateways to connect to other networks.</p>
<p>When your API gateway is located within a VPC, you have a private API gateway. Unlike their public counterparts accessible over the internet, private API gateways are crafted to be accessed exclusively from within the specified network. This means only backend services and databases created within your organization can access the API endpoints.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-choose-a-private-api-gateway">Why Choose a Private API Gateway?<a class="hash-link" aria-label="Direct link to Why Choose a Private API Gateway?" title="Direct link to Why Choose a Private API Gateway?" href="https://www.winglang.io/blog/2024/02/15/private-api-gateways#why-choose-a-private-api-gateway">​</a></h2>
<p>Let's take a look at three common use cases.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="improved-security">Improved security:<a class="hash-link" aria-label="Direct link to Improved security:" title="Direct link to Improved security:" href="https://www.winglang.io/blog/2024/02/15/private-api-gateways#improved-security">​</a></h3>
<p>By confining your API within a private network, you minimize exposure to potential security threats originating from a public API over the internet. For the security conscious, VPCs provide a much saner starting point for securing your application since private compute resources can simply say “allow any traffic from our private network,” reducing the need to manually manage firewalls and IP tables. In this scenario, it doesn’t really matter what you’re building - you just don’t want the public internet messing around with it!</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="compliance">Compliance:<a class="hash-link" aria-label="Direct link to Compliance:" title="Direct link to Compliance:" href="https://www.winglang.io/blog/2024/02/15/private-api-gateways#compliance">​</a></h3>
<p>Some compliance standards or organizational policies mandate the use of VPCs to ensure that sensitive data remains within controlled environments. For example, with regulations like <a href="https://www.hhs.gov/hipaa/for-professionals/security/laws-regulations/index.html" target="_blank" rel="noopener noreferrer">HIPAA</a> in the United States, <a href="https://blog.scottlogic.com/2021/10/11/vpcs-aws.html" target="_blank" rel="noopener noreferrer">deploying applications within VPCs is a common strategy</a> to ensure the confidentiality and security of patient data. In these situations, cloud architectures that are designed around API endpoint usage will benefit from being able to use private API gateways.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="hybrid-cloud-environments">Hybrid cloud environments:<a class="hash-link" aria-label="Direct link to Hybrid cloud environments:" title="Direct link to Hybrid cloud environments:" href="https://www.winglang.io/blog/2024/02/15/private-api-gateways#hybrid-cloud-environments">​</a></h3>
<p>For companies that operate in a <a href="https://docs.aws.amazon.com/whitepapers/latest/public-sector-cloud-transformation/selecting-the-right-cloud-for-workloads-differences-between-public-private-and-hybrid.html" target="_blank" rel="noopener noreferrer">hybrid cloud environment</a> (a mix of public cloud and on-premises data centers), a private API gateway can manage and route traffic within the private network. This is essential for sensitive data that cannot be transferred to public clouds due to policy or regulatory reasons. Migrating applications to the cloud is made easier by the fact that modern cloud providers like AWS <a href="https://docs.aws.amazon.com/AmazonECS/latest/bestpracticesguide/networking-connecting-vpc.html" target="_blank" rel="noopener noreferrer">allow application code running within VPCs to have secure access to the common services</a> like S3, DynamoDB, and IAM - all routed through the backbone of Amazon’s networking infrastructure.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="challenges">Challenges<a class="hash-link" aria-label="Direct link to Challenges" title="Direct link to Challenges" href="https://www.winglang.io/blog/2024/02/15/private-api-gateways#challenges">​</a></h2>
<p>While setting up cloud applications in private networks has many security benefits, accessing a private API from external environments, such as during development or testing phases, can be cumbersome. <a href="https://medium.com/@robertcurran5635/dragging-serverless-web-apps-into-the-vpc-d97cabd47e79" target="_blank" rel="noopener noreferrer">VPCs typically add complexity to serverless applications</a> by increasing the amount of infrastructure that needs to be managed through tools like Terraform and CloudFormation, and may require <a href="https://dev.to/aws-builders/bastion-host-in-aws-vpc-2i63" target="_blank" rel="noopener noreferrer">setting up bastion hosts for debugging applications</a> in production.</p>
<p>Furthermore, establishing secure connections to any networks outside of the VPC may require setting up Virtual Private Networks (VPNs) or using services like Amazon Direct Connect, which introduces extra complexity.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="overcoming-it">Overcoming it<a class="hash-link" aria-label="Direct link to Overcoming it" title="Direct link to Overcoming it" href="https://www.winglang.io/blog/2024/02/15/private-api-gateways#overcoming-it">​</a></h2>
<p>In the <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">Wing Discord</a> community, we’ve seen many developers share their advice and experiences building cloud applications of all shapes and sizes. Recently, we heard about a user’s positive experience building a cloud application with Wing that established API endpoints within their VPC through a private API Gateway. Inspired by their efforts, we extracted their solution into a template that makes it easy for anyone to turn their API gateway into a private one.</p>
<p>One of the biggest pains people have when using serverless is that they constantly have to wait for deployments to finish in order to test changes to their code. This is where Winglang and it's cloud simulator rocks - it allows you to develop your entire serverless application without having to deploy anything on the cloud, letting you iterate in milliseconds instead of minutes.</p>
<p>If you’re curious to learn more, check out our <a href="https://www.winglang.io/docs/guides/private-api-gateway-aws">tutorial</a> that walks you step-by-step through building a simple application with a private API gateway and deploy it to your own AWS account. If you have feedback or any other questions, let us know by dropping a comment in our <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">community discord</a>. Don’t be shy!</p>]]></content:encoded>
            <author>chrisr@wing.cloud (Chris Rybicki)</author>
            <category>private api gateway</category>
            <category>secure api gateway</category>
            <category>serverless api gateway</category>
            <category>private api gateway example</category>
            <category>private api gateway tutorial</category>
            <category>api gateway vpc</category>
            <category>private api gateway terraform</category>
            <category>application gateway</category>
            <category>private endpoint</category>
            <category>winglang</category>
            <category>wing cloud</category>
        </item>
        <item>
            <title><![CDATA[5 Ways to Skin a Lambda Function: A DevTools Comparison Guide]]></title>
            <link>https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function</link>
            <guid>https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function</guid>
            <pubDate>Wed, 14 Feb 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[A generours comparison between Wing, Pulumi, AWS-CDK-CDT for Terraform, and Terraform]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="Cover Art" src="https://www.winglang.io/assets/images/5-cloud-functions-1bc787ac651cbc0e0b465070802a09f2.png" width="800" height="420" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="tldr">TL;DR<a class="hash-link" aria-label="Direct link to TL;DR" title="Direct link to TL;DR" href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#tldr">​</a></h2>
<p>As the saying goes, there are several ways to skin a cat...in the tech world, there are 5 ways to skin a Lambda Function 🤩</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="lets-compare-5-devtools">Lets Compare 5 DevTools<a class="hash-link" aria-label="Direct link to Lets Compare 5 DevTools" title="Direct link to Lets Compare 5 DevTools" href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#lets-compare-5-devtools">​</a></h2>
<ul>
<li>
<p>✅ <a href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#1-wing">Wing</a></p>
</li>
<li>
<p>✅ <a href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#2-pulumi">Pulumi</a></p>
</li>
<li>
<p>✅ <a href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#3-awscdk">AWS-CDK</a></p>
</li>
<li>
<p>✅ <a href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#4-cdk-for-terraform">CDK for Terraform</a></p>
</li>
<li>
<p>✅ <a href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#5-terraform">Terraform</a></p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="introduction">Introduction<a class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction" href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#introduction">​</a></h2>
<p>As developers try to bridge the gap between development and DevOps, I thought it would be helpful to compare Programming Languages and DevTools.</p>
<p>Let's start with the idea of a simple function that would upload a text file to a Bucket in our cloud app.</p>
<p>The next step is to demonstrate several ways this could be accomplished.</p>
<p><strong>Note:</strong> In cloud development, managing permissions and bucket identities, packaging runtime code, and handling multiple files for infrastructure and runtime add layers of complexity to the development process.</p>
<p><img decoding="async" loading="lazy" alt="Let&amp;#39;s get started" src="https://www.winglang.io/assets/images/lets-go-c81567d41311d8a7d7150753964dc4ad.gif" width="576" height="576" class="img_ev3q"></p>
<p>Let's dive into some code!</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="1-wing">1. <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Wing</a><a class="hash-link" aria-label="Direct link to 1-wing" title="Direct link to 1-wing" href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#1-wing">​</a></h2>
<blockquote>
<p>After <a href="https://www.winglang.io/docs" target="_blank" rel="noopener noreferrer">installing Wing</a>, let's create a file: <code>main.w</code></p>
</blockquote>
<blockquote>
<p><strong>If you aren't familiar with the Wing Programming Language, please check out the open-source repo</strong> <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">HERE</a></p>
</blockquote>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-javascript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> bucket </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">put</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"hello.txt"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"world!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>Let's do a breakdown of what's happening in the code above.</strong></p>
<blockquote>
<p><code>bring cloud</code> is Wing's import syntax</p>
</blockquote>
<blockquote>
<p><strong>Create a Cloud Bucket:</strong> <code>let bucket = new cloud.Bucket();</code> initializes a new cloud bucket instance.</p>
</blockquote>
<blockquote>
<p>On the backend, the Wing platform provisions a new bucket in your cloud provider's environment. This bucket is used for storing and retrieving data.</p>
</blockquote>
<blockquote>
<p><strong>Create a Cloud Function:</strong> The <code>new cloud.Function(inflight () =&gt; { ... });</code> statement defines a new cloud function.</p>
</blockquote>
<blockquote>
<p>This function, when triggered, performs the actions defined within its body.</p>
</blockquote>
<blockquote>
<p><code>bucket.put("hello.txt", "world!");</code> uploads a file named hello.txt with the content world! to the cloud bucket created earlier.</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="compile--deploy-to-aws">Compile &amp; Deploy to AWS<a class="hash-link" aria-label="Direct link to Compile &amp; Deploy to AWS" title="Direct link to Compile &amp; Deploy to AWS" href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#compile--deploy-to-aws">​</a></h2>
<ul>
<li>
<p><code>wing compile --platform tf-aws main.w</code></p>
</li>
<li>
<p><code>terraform apply</code></p>
</li>
</ul>
<p>That's it, Wing takes care of the complexity of (permissions, getting the bucket identity in the runtime code, packaging the runtime code into a bucket, having to write multiple files - for infrastructure and runtime), etc.</p>
<p>Not to mention it generates IAC (TF or CF), plus Javascript that you can deploy with existing tools.</p>
<p><img decoding="async" loading="lazy" alt="Wing Console" src="https://www.winglang.io/assets/images/wing-console-577259522b412dba648019efc0ba5129.gif" width="1720" height="1080" class="img_ev3q"></p>
<p>But while you develop, you can use the local simulator to get instant feedback and shorten the iteration cycles</p>
<p>Wing even has a playground that you can try out in the browser!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="2-pulumi">2. <a href="https://www.pulumi.com/" target="_blank" rel="noopener noreferrer">Pulumi</a><a class="hash-link" aria-label="Direct link to 2-pulumi" title="Direct link to 2-pulumi" href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#2-pulumi">​</a></h2>
<blockquote>
<p>Step 1: Initialize a New Pulumi Project</p>
</blockquote>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">mkdir</span><span class="token plain"> pulumi-s3-lambda-ts</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> pulumi-s3-lambda-ts</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pulumi new aws-typescript</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>Step 2. Write the code to upload a text file to S3.</p>
</blockquote>
<p>This will be your project structure.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pulumi-s3-lambda-ts/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├─ src/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│  ├─ index.ts              </span><span class="token comment" style="color:rgb(98, 114, 164)"># Pulumi infrastructure code</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│  └─ lambda/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│     └─ index.ts           </span><span class="token comment" style="color:rgb(98, 114, 164)"># Lambda function code to upload a file to S3</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├─ tsconfig.json            </span><span class="token comment" style="color:rgb(98, 114, 164)"># TypeScript configuration</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">└─ package.json             </span><span class="token comment" style="color:rgb(98, 114, 164)"># Node.js project file with dependencies</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Let's add this code to <strong>index.ts</strong></p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-javascript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports operator">*</span><span class="token imports"> </span><span class="token imports keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token imports"> pulumi</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@pulumi/pulumi"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports operator">*</span><span class="token imports"> </span><span class="token imports keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token imports"> aws</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@pulumi/aws"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Create an AWS S3 bucket</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> bucket </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">aws</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">s3</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"myBucket"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">acl</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"private"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// IAM role for the Lambda function</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> lambdaRole </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">aws</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">iam</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Role</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"lambdaRole"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">assumeRolePolicy</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">JSON</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">Version</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2023-10-17"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">Statement</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">Action</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"sts:AssumeRole"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">Principal</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token literal-property property">Service</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambda.amazonaws.com"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">Effect</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Allow"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">Sid</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Attach the AWSLambdaBasicExecutionRole policy</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">aws</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">iam</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">RolePolicyAttachment</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"lambdaExecutionRole"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">role</span><span class="token operator">:</span><span class="token plain"> lambdaRole</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">policyArn</span><span class="token operator">:</span><span class="token plain"> aws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">iam</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ManagedPolicy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">AWSLambdaBasicExecutionRole</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Policy to allow Lambda function to access the S3 bucket</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> lambdaS3Policy </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">aws</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">iam</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Policy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"lambdaS3Policy"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">policy</span><span class="token operator">:</span><span class="token plain"> bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">arn</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">apply</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">arn</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token known-class-name class-name">JSON</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">Version</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2023-10-17"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">Statement</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token literal-property property">Action</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"s3:PutObject"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"s3:GetObject"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token literal-property property">Resource</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">arn</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">/*</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token literal-property property">Effect</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Allow"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Attach policy to Lambda role</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">aws</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">iam</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">RolePolicyAttachment</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"lambdaS3PolicyAttachment"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">role</span><span class="token operator">:</span><span class="token plain"> lambdaRole</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">policyArn</span><span class="token operator">:</span><span class="token plain"> lambdaS3Policy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">arn</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Lambda function</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> lambda </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">aws</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">lambda</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"myLambda"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">code</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">pulumi</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">asset</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">AssetArchive</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string-property property">"."</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">pulumi</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">asset</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">FileArchive</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"./src/lambda"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">runtime</span><span class="token operator">:</span><span class="token plain"> aws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">lambda</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Runtime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">NodeJS12dX</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">role</span><span class="token operator">:</span><span class="token plain"> lambdaRole</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">arn</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">handler</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"index.handler"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">environment</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">variables</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token constant" style="color:rgb(189, 147, 249)">BUCKET_NAME</span><span class="token operator">:</span><span class="token plain"> bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> bucketName </span><span class="token operator">=</span><span class="token plain"> bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> lambdaArn </span><span class="token operator">=</span><span class="token plain"> lambda</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">arn</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Next, create a <strong>lambda/index.ts</strong> directory for the Lambda function code:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-javascript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">S3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"aws-sdk"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> s3 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">S3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Promise</span><span class="token operator">&lt;</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> bucketName </span><span class="token operator">=</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">BUCKET_NAME</span><span class="token plain"> </span><span class="token operator">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> fileName </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"example.txt"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> content </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Pulumi!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> params </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">Bucket</span><span class="token operator">:</span><span class="token plain"> bucketName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">Key</span><span class="token operator">:</span><span class="token plain"> fileName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">Body</span><span class="token operator">:</span><span class="token plain"> content</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> s3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">putObject</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">promise</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token console class-name">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">File uploaded successfully at https://</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">bucketName</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">.s3.amazonaws.com/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">fileName</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token console class-name">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>Step 3: TypeScript Configuration (tsconfig.json)</p>
</blockquote>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-json codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"compilerOptions"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"target"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ES2018"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"module"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"CommonJS"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"strict"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"esModuleInterop"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"skipLibCheck"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"forceConsistentCasingInFileNames"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"include"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"src/**/*.ts"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"exclude"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"node_modules"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"**/*.spec.ts"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>After creating a Pulumi project, a yaml file will automatically be generated.</strong> <strong>pulumi.yaml</strong></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">name: s3-lambda-pulumi</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">runtime: nodejs</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">description: A simple example that uploads a </span><span class="token function" style="color:rgb(80, 250, 123)">file</span><span class="token plain"> to an S3 bucket using a Lambda </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">template:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  config:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    aws:region:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      description: The AWS region to deploy into</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      default: us-west-2</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="deploy-with-pulumi">Deploy with Pulumi<a class="hash-link" aria-label="Direct link to Deploy with Pulumi" title="Direct link to Deploy with Pulumi" href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#deploy-with-pulumi">​</a></h2>
<p>Ensure your <code>lambda</code> directory with the <code>index.js</code> file is correctly set up. Then, run the following command to deploy your infrastructure: <code>pulumi up</code></p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="3-aws-cdk">3. <a href="https://aws.amazon.com/cdk" target="_blank" rel="noopener noreferrer">AWS-CDK</a><a class="hash-link" aria-label="Direct link to 3-aws-cdk" title="Direct link to 3-aws-cdk" href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#3-aws-cdk">​</a></h2>
<blockquote>
<p>Step 1: Initialize a New CDK Project</p>
</blockquote>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">mkdir</span><span class="token plain"> cdk-s3-lambda</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> cdk-s3-lambda</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">cdk init app --language</span><span class="token operator">=</span><span class="token plain">typescript</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>Step 2: Add Dependencies</p>
</blockquote>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"> @aws-cdk/aws-lambda @aws-cdk/aws-s3</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>Step 3: Define the AWS Resources in CDK</p>
</blockquote>
<p>File: <strong>index.js</strong></p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-javascript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports operator">*</span><span class="token imports"> </span><span class="token imports keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token imports"> cdk</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@aws-cdk/core"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports operator">*</span><span class="token imports"> </span><span class="token imports keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token imports"> lambda</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@aws-cdk/aws-lambda"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports operator">*</span><span class="token imports"> </span><span class="token imports keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token imports"> s3</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@aws-cdk/aws-s3"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">CdkS3LambdaStack</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name">cdk</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Stack</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">constructor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">scope</span><span class="token parameter operator">:</span><span class="token parameter"> cdk</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token parameter property-access maybe-class-name">Construct</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> </span><span class="token parameter literal-property property">id</span><span class="token parameter operator">:</span><span class="token parameter"> string</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> props</span><span class="token parameter operator">?</span><span class="token parameter operator">:</span><span class="token parameter"> cdk</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token parameter property-access maybe-class-name">StackProps</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">scope</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> props</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// Create the S3 bucket</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> bucket </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">s3</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MyBucket"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">removalPolicy</span><span class="token operator">:</span><span class="token plain"> cdk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">RemovalPolicy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">DESTROY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// NOT recommended for production code</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// Define the Lambda function</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> lambdaFunction </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">lambda</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MyLambda"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">runtime</span><span class="token operator">:</span><span class="token plain"> lambda</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Runtime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">NODEJS_14_X</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// Define the runtime</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">handler</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"index.handler"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// Specifies the entry point</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">code</span><span class="token operator">:</span><span class="token plain"> lambda</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Code</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromAsset</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"lambda"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// Directory containing your Lambda code</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">environment</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token constant" style="color:rgb(189, 147, 249)">BUCKET_NAME</span><span class="token operator">:</span><span class="token plain"> bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">bucketName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// Grant the Lambda function permissions to write to the S3 bucket</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">grantWrite</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">lambdaFunction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>Step 4: Lambda Function Code</p>
</blockquote>
<p>Create the same file struct as above and in the pulumi directory: <strong>index.ts</strong></p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-javascript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">S3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'aws-sdk'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> s3 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">S3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">exports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(80, 250, 123)">handler</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">event</span><span class="token parameter operator">:</span><span class="token parameter"> any</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> bucketName </span><span class="token operator">=</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">BUCKET_NAME</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> fileName </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'uploaded_file.txt'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> content </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'Hello, CDK! This file was uploaded by a Lambda function!'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> result </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> s3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">putObject</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">Bucket</span><span class="token operator">:</span><span class="token plain"> bucketName</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">Key</span><span class="token operator">:</span><span class="token plain"> fileName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">Body</span><span class="token operator">:</span><span class="token plain"> content</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">promise</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token console class-name">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">File uploaded successfully: </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">result</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">statusCode</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">File uploaded successfully: </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">fileName</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token console class-name">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">statusCode</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">500</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">Failed to upload file: </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">error</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="deploy-the-cdk-stack">Deploy the CDK Stack<a class="hash-link" aria-label="Direct link to Deploy the CDK Stack" title="Direct link to Deploy the CDK Stack" href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#deploy-the-cdk-stack">​</a></h2>
<p>First, compile your TypeScript code: <code>npm run build</code>, then</p>
<p>Deploy your CDK to AWS: <code>cdk deploy</code></p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="4-cdk-for-terraform">4. <a href="https://developer.hashicorp.com/terraform/cdktf" target="_blank" rel="noopener noreferrer">CDK for Terraform</a><a class="hash-link" aria-label="Direct link to 4-cdk-for-terraform" title="Direct link to 4-cdk-for-terraform" href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#4-cdk-for-terraform">​</a></h2>
<blockquote>
<p>Step 1: Initialize a New CDKTF Project</p>
</blockquote>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">mkdir</span><span class="token plain"> cdktf-s3-lambda-ts</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> cdktf-s3-lambda-ts</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Then, initialize a new CDKTF project using TypeScript:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">cdktf init --template</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"typescript"</span><span class="token plain"> --local</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>Step 2: Install AWS Provider and Add Dependencies</p>
</blockquote>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"> @cdktf/provider-aws</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>Step 3: Define the Infrastructure</p>
</blockquote>
<p>Edit main.ts to define the S3 bucket and Lambda function:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-javascript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">Construct</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"constructs"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">App</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> </span><span class="token imports maybe-class-name">TerraformStack</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"cdktf"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">AwsProvider</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> s3</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> lambdafunction</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> iam </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@cdktf/provider-aws"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">MyStack</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">extends</span><span class="token plain"> </span><span class="token class-name">TerraformStack</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">constructor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">scope</span><span class="token parameter operator">:</span><span class="token parameter"> </span><span class="token parameter maybe-class-name">Construct</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> </span><span class="token parameter literal-property property">id</span><span class="token parameter operator">:</span><span class="token parameter"> string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">super</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">scope</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">AwsProvider</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"aws"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token literal-property property">region</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"us-west-2"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// S3 bucket</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> bucket </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">s3</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">S3Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambdaBucket"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">bucketPrefix</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"cdktf-lambda-"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// IAM role for Lambda</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> role </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">iam</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">IamRole</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambdaRole"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambda_execution_role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">assumeRolePolicy</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">JSON</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">Version</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2023-10-17"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">Statement</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token literal-property property">Action</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"sts:AssumeRole"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token literal-property property">Principal</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token literal-property property">Service</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambda.amazonaws.com"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token literal-property property">Effect</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Allow"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">iam</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">IamRolePolicyAttachment</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambdaPolicy"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">role</span><span class="token operator">:</span><span class="token plain"> role</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">policyArn</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> lambdaFunction </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">lambdafunction</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">LambdaFunction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MyLambda"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">functionName</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"myLambdaFunction"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">handler</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"index.handler"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">role</span><span class="token operator">:</span><span class="token plain"> role</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">arn</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">runtime</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"nodejs14.x"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">s3Bucket</span><span class="token operator">:</span><span class="token plain"> bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// Assuming the Lambda code is uploaded to this bucket</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">s3Key</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambda.zip"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// Assuming the Lambda code zip file is named lambda.zip</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">environment</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">variables</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token constant" style="color:rgb(189, 147, 249)">BUCKET_NAME</span><span class="token operator">:</span><span class="token plain"> bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// Grant the Lambda function permissions to write to the S3 bucket</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">s3</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">S3BucketPolicy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"BucketPolicy"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">bucket</span><span class="token operator">:</span><span class="token plain"> bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">policy</span><span class="token operator">:</span><span class="token plain"> bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">apply</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token known-class-name class-name">JSON</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token literal-property property">Version</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2023-10-17"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token literal-property property">Statement</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">              </span><span class="token literal-property property">Action</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"s3:*"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">              </span><span class="token literal-property property">Resource</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">arn:aws:s3:::</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">name</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">/*</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">              </span><span class="token literal-property property">Effect</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Allow"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">              </span><span class="token literal-property property">Principal</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token constant" style="color:rgb(189, 147, 249)">AWS</span><span class="token operator">:</span><span class="token plain"> role</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">arn</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> app </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">App</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">MyStack</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"cdktf-s3-lambda-ts"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">synth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>Step 4: Lambda Function Code</p>
</blockquote>
<p>The Lambda function code should be written in TypeScript and compiled into JavaScript, as AWS Lambda natively executes JavaScript. Here's an example <strong>index.ts</strong> for the Lambda function that you need to compile and zip:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-javascript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">S3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"aws-sdk"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> s3 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">S3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">exports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(80, 250, 123)">handler</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> bucketName </span><span class="token operator">=</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">BUCKET_NAME</span><span class="token plain"> </span><span class="token operator">||</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> content </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, CDKTF!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> params </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">Bucket</span><span class="token operator">:</span><span class="token plain"> bucketName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">Key</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">upload-</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation known-class-name class-name">Date</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation method function property-access" style="color:rgb(80, 250, 123)">now</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">.txt</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">Body</span><span class="token operator">:</span><span class="token plain"> content</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> s3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">putObject</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">promise</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token literal-property property">statusCode</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"File uploaded successfully"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token console class-name">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">err</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token literal-property property">statusCode</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">500</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Failed to upload file"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You need to compile this TypeScript code to JavaScript, zip it, and upload it to the S3 bucket manually or using a script.</p>
<p>Ensure the s3Key in the LambdaFunction resource points to the correct zip file in the bucket.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="compile--deploy-your-cdktf-project">Compile &amp; Deploy Your CDKTF Project<a class="hash-link" aria-label="Direct link to Compile &amp; Deploy Your CDKTF Project" title="Direct link to Compile &amp; Deploy Your CDKTF Project" href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#compile--deploy-your-cdktf-project">​</a></h2>
<p>Compile your project using <code>npm run build</code></p>
<p><strong>Generate Terraform Configuration Files</strong></p>
<p>Run the <code>cdktf synth</code> command. This command executes your CDKTF app, which generates Terraform configuration files (<code>*.tf.json</code> files) in the <code>cdktf.out</code> directory:</p>
<p><strong>Deploy Your Infrastructure</strong></p>
<p><code>cdktf deploy</code></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="5-terraform">5. <a href="https://developer.hashicorp.com/terraform" target="_blank" rel="noopener noreferrer">Terraform</a><a class="hash-link" aria-label="Direct link to 5-terraform" title="Direct link to 5-terraform" href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#5-terraform">​</a></h2>
<blockquote>
<p>Step 1: Terraform Setup</p>
</blockquote>
<p>Define your AWS Provider and S3 Bucket
Create a file named <strong>main.tf</strong> with the following:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-javascript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">provider </span><span class="token string" style="color:rgb(255, 121, 198)">"aws"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  region </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"us-west-2"</span><span class="token plain"> # </span><span class="token maybe-class-name">Choose</span><span class="token plain"> your </span><span class="token constant" style="color:rgb(189, 147, 249)">AWS</span><span class="token plain"> region</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">resource </span><span class="token string" style="color:rgb(255, 121, 198)">"aws_s3_bucket"</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambda_bucket"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  bucket_prefix </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambda-upload-bucket-"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  acl           </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"private"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">resource </span><span class="token string" style="color:rgb(255, 121, 198)">"aws_iam_role"</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambda_execution_role"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  name </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambda_execution_role"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  assume_role_policy </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">jsonencode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token maybe-class-name">Version</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2023-10-17"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token maybe-class-name">Statement</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token maybe-class-name">Action</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"sts:AssumeRole"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token maybe-class-name">Effect</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Allow"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token maybe-class-name">Principal</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token maybe-class-name">Service</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambda.amazonaws.com"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">resource </span><span class="token string" style="color:rgb(255, 121, 198)">"aws_iam_policy"</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambda_s3_policy"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  name        </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambda_s3_policy"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  description </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"IAM policy for Lambda to access S3"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  policy </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">jsonencode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token maybe-class-name">Version</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2023-10-17"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token maybe-class-name">Statement</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token maybe-class-name">Action</span><span class="token plain">   </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"s3:PutObject"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"s3:GetObject"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token maybe-class-name">Effect</span><span class="token plain">   </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Allow"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token maybe-class-name">Resource</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"${aws_s3_bucket.lambda_bucket.arn}/*"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">resource </span><span class="token string" style="color:rgb(255, 121, 198)">"aws_iam_role_policy_attachment"</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambda_s3_access"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  role       </span><span class="token operator">=</span><span class="token plain"> aws_iam_role</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">lambda_execution_role</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">name</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  policy_arn </span><span class="token operator">=</span><span class="token plain"> aws_iam_policy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">lambda_s3_policy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">arn</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">resource </span><span class="token string" style="color:rgb(255, 121, 198)">"aws_lambda_function"</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"uploader_lambda"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  function_name </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"S3Uploader"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  s3_bucket </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"YOUR_DEPLOYMENT_BUCKET_NAME"</span><span class="token plain"> # </span><span class="token known-class-name class-name">Set</span><span class="token plain"> your deployment bucket name here</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  s3_key    </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"lambda.zip"</span><span class="token plain"> # </span><span class="token maybe-class-name">Upload</span><span class="token plain"> your </span><span class="token constant" style="color:rgb(189, 147, 249)">ZIP</span><span class="token plain"> file to </span><span class="token constant" style="color:rgb(189, 147, 249)">S3</span><span class="token plain"> and </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">set</span><span class="token plain"> its key here</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  handler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"index.handler"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  role    </span><span class="token operator">=</span><span class="token plain"> aws_iam_role</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">lambda_execution_role</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">arn</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  runtime </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"nodejs14.x"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  environment </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    variables </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token constant" style="color:rgb(189, 147, 249)">BUCKET_NAME</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> aws_s3_bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">lambda_bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">bucket</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>Step 2: Lambda Function Code (TypeScript)</p>
</blockquote>
<p>Create a TypeScript file <strong>index.ts</strong> for the Lambda function:</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-javascript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">S3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'aws-sdk'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> s3 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">S3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">exports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(80, 250, 123)">handler</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">event</span><span class="token parameter operator">:</span><span class="token parameter"> any</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> bucketName </span><span class="token operator">=</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">BUCKET_NAME</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> fileName </span><span class="token operator">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">uploaded-</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation known-class-name class-name">Date</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation method function property-access" style="color:rgb(80, 250, 123)">now</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">.txt</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> content </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'Hello, Terraform and AWS Lambda!'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> s3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">putObject</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">Bucket</span><span class="token operator">:</span><span class="token plain"> bucketName</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">Key</span><span class="token operator">:</span><span class="token plain"> fileName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">Body</span><span class="token operator">:</span><span class="token plain"> content</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">promise</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token console class-name">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'Upload successful'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">statusCode</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">JSON</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token literal-property property">message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'Upload successful'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token console class-name">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'Upload failed:'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">statusCode</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">500</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">JSON</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token literal-property property">message</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'Upload failed'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Finally after uploading your Lambda function code to the specified S3 bucket, run <code>terraform apply</code>.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="rapping-it-up">Rapping it up!<a class="hash-link" aria-label="Direct link to Rapping it up!" title="Direct link to Rapping it up!" href="https://www.winglang.io/blog/2024/2/14/five-ways-to-skin-a-lambda-function#rapping-it-up">​</a></h2>
<p>I hope you enjoyed this comparison of five simple ways to write a function in our cloud app that uploads a text file to a Bucket.</p>
<p>As you can see, most of the code becomes very complex, except for Wing.</p>
<blockquote>
<p>If you are intrigued about Wing and like how we are simplifying the process of cloud development, please join our <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">community</a> and reach out to us on <a href="https://twitter.com/winglangio" target="_blank" rel="noopener noreferrer">Twitter</a>.</p>
</blockquote>]]></content:encoded>
            <author>nathant@wing.cloud (Nathan Tarbert)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>winglang</category>
            <category>platforms</category>
        </item>
        <item>
            <title><![CDATA[Hello, Winglang Hexagon!]]></title>
            <link>https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon</link>
            <guid>https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon</guid>
            <pubDate>Tue, 30 Jan 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Exploring Cloud Hexagonal Design with Winglang, TypeScript, and Ports & Adapters]]></description>
            <content:encoded><![CDATA[<h2 class="anchor anchorWithStickyNavbar_LWe7" id="exploring-cloud-hexagonal-design-with-winglang-typescript-and-ports--adapters">Exploring Cloud Hexagonal Design with Winglang, TypeScript, and Ports &amp; Adapters<a class="hash-link" aria-label="Direct link to Exploring Cloud Hexagonal Design with Winglang, TypeScript, and Ports &amp; Adapters" title="Direct link to Exploring Cloud Hexagonal Design with Winglang, TypeScript, and Ports &amp; Adapters" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#exploring-cloud-hexagonal-design-with-winglang-typescript-and-ports--adapters">​</a></h2>
<p>As I argued <a href="https://medium.com/@asher-sterkin/cloud-application-infrastructure-from-code-ifc-398140babf13" target="_blank" rel="noopener noreferrer">elsewhere</a>, automatically generating cloud infrastructure specifications directly from application code represents “The Next Logical Step in Cloud Automation.” This approach, sometimes referred to as “Infrastructure From Code” (IfC), aims to:</p>
<blockquote>
<p>Ensure automatic coordination of four types of interactions with cloud services: life cycle management, pre- and post-configuration, consumption, and operation, while making pragmatic choices of the most appropriate levels of API abstraction for each cloud service and leaving enough control to the end-user for choosing the most suitable vendor, based on personal preferences, regulations or brownfield deployment constraints</p>
</blockquote>
<p>While analyzing the <a href="https://medium.com/@asher-sterkin/ifc-2023-technology-landscape-91e11934f7ab" target="_blank" rel="noopener noreferrer">IfC Technology Landscape</a> a year ago, I identified five attributes essential for analyzing major offerings in this space:</p>
<ul>
<li><strong>Programming Language</strong> — is an IfC product based on an existing mainstream programming language(s) or embarks on developing a new one?</li>
<li><strong>Runtime Environment</strong> — does it still use some existing runtime environment (e.g. <a href="https://nodejs.org/en" target="_blank" rel="noopener noreferrer">NodeJS</a>)?</li>
<li><strong>API</strong> — is it proprietary or some form of standard/open source? Cloud-specific or cloud-agnostic?</li>
<li><strong>IDE</strong> — does it assume its proprietary, presumably cloud-based, Integrated Development Environment or could be integrated with one or more of existing IDEs?</li>
<li><strong>Deployment</strong> — does it assume deployment applications/services to its own cloud account or produced artifacts could be deployed to the customer’s own cloud account?</li>
</ul>
<p>At that time, <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> appeared on my radar as a brand-new cloud programming-oriented language running atop the <a href="https://nodejs.org/en" target="_blank" rel="noopener noreferrer">NodeJS</a> runtime. It comes with an optional plugin for <a href="https://code.visualstudio.com/" target="_blank" rel="noopener noreferrer">VSCode</a>, its own console, and fully supports cloud self-hosting via popular cloud orchestration engines such as <a href="https://www.terraform.io/" target="_blank" rel="noopener noreferrer">Terraform</a> and <a href="https://aws.amazon.com/cdk/" target="_blank" rel="noopener noreferrer">AWS CDK</a>.</p>
<p>Today, I want to explore how well <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> is suited for supporting the <a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" target="_blank" rel="noopener noreferrer">Clean Architecture</a> style, based on the <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Ports and Adapters</a> pattern. Additionally, I’m interested in how easily <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> can be integrated with <a href="https://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer">TypeScript</a>, a representative of mainstream programming languages that can be compiled into <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank" rel="noopener noreferrer">JavaScript</a> and run atop the <a href="https://nodejs.org/en" target="_blank" rel="noopener noreferrer">NodeJS</a> runtime engine.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="disclaimer">Disclaimer<a class="hash-link" aria-label="Direct link to Disclaimer" title="Direct link to Disclaimer" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#disclaimer">​</a></h2>
<p>This publication is a technology research report. While it could potentially be converted into a tutorial, it currently does not serve as one. The code snippets in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> are intended to be self-explanatory. The language syntax falls within the common Algol-60 family and is, in most cases, straightforward to understand. In instances of uncertainty, please consult the <a href="https://www.winglang.io/docs/language-reference" target="_blank" rel="noopener noreferrer">Winglang Language Reference</a>, <a href="https://www.winglang.io/docs/category/standard-library" target="_blank" rel="noopener noreferrer">Library</a>, and <a href="https://github.com/winglang/wing/tree/main/examples" target="_blank" rel="noopener noreferrer">Examples</a>. For introductory materials, refer to the <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#6888">References</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="acknowledgements">Acknowledgements<a class="hash-link" aria-label="Direct link to Acknowledgements" title="Direct link to Acknowledgements" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#acknowledgements">​</a></h2>
<p>Many thanks to <a href="https://www.linkedin.com/in/hackingonstuff/" target="_blank" rel="noopener noreferrer">Elad Ben-Israel</a>, <a href="https://www.linkedin.com/in/shai-ber-245b1226/" target="_blank" rel="noopener noreferrer">Shai Ber</a>, and <a href="https://www.linkedin.com/in/nathan-tarbert/" target="_blank" rel="noopener noreferrer">Nathan Tarbert</a> for the valuable feedback on the early draft of this paper.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="table-of-contents">Table of Contents<a class="hash-link" aria-label="Direct link to Table of Contents" title="Direct link to Table of Contents" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#table-of-contents">​</a></h2>
<ol>
<li><a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#disclaimer">Disclaimer</a></li>
<li><a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#acknowledgements">Acknowledgements</a></li>
<li><a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#part-one-creating-the-core">Part One: Creating the Core</a><br>
3.1 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-zero-hello-winglang-preflight">Step Zero: “Hello, Winglang!” Preflight</a><br>
3.2 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-one-hello-winglang-inflight">Step One: “Hello, Winglang!” Inflight</a><br>
3.3 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-two-generalizing-functionality-by-accepting-the-argument">Step Two: Generalizing Functionality by Accepting the Argument</a><br>
3.4 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#deciding-if-the-hexagon-approach-is-right-for-you">Deciding if the Hexagon Approach is Right for You</a></li>
<li><a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#part-two-encapsulating-the-core-within-hexagon">Part Two: Encapsulating the Core within Hexagon</a><br>
4.1 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-four-extracting-core">Step Four: Extracting Core</a><br>
4.2 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-five-extracting-the-makegreetingname-request-handler">Step Five: Extracting the makeGreeting(name) Request Handler</a><br>
4.3 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-six-connecting-the-handler-via-cloud-function-port">Step Six: Connecting the Handler via Cloud Function Port</a><br>
4.4 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-seven-reimplementing-the-core-in-typescript">Step Seven: Reimplementing the Core in TypeScript</a><br>
4.5 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-eight-implementing-the-rest-api-port">Step Eight: Implementing the REST API Port</a><br>
4.6 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-nine-extracting-the-rest-api-request-adapter">Step Nine: Extracting the REST API Request Adapter</a><br>
4.7 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-ten-testing-the-rest-api-request-adapter">Step Ten: Testing the REST API Request Adapter</a><br>
4.8 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-eleven-enhancing-the-greetingservice">Step Eleven: Extracting the GreetingService</a><br>
4.9 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-twelve-enhancing-rest-api-request-adapter-for-content-negotiation">Step Twelve: Enhancing REST API Request Adapter for Content Negotiation</a></li>
<li><a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#references">References</a><br>
6.1 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#winglang-publications">Winglang Publications</a><br>
6.2 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#my-publications-on-infrastructure-from-code">My Publications on “Infrastructure From Code”</a><br>
6.3 <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#hexagonal-architecture">Hexagonal Architecture</a></li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="part-one-creating-the-core">Part One: Creating the Core<a class="hash-link" aria-label="Direct link to Part One: Creating the Core" title="Direct link to Part One: Creating the Core" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#part-one-creating-the-core">​</a></h2>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-zero-hello-winglang-preflight">Step Zero: “Hello, Winglang!” Preflight<a class="hash-link" aria-label="Direct link to Step Zero: “Hello, Winglang!” Preflight" title="Direct link to Step Zero: “Hello, Winglang!” Preflight" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-zero-hello-winglang-preflight">​</a></h2>
<p>Creating the simplest possible “Hello, World!” application is a crucial, yet often overlooked, validation step in new software technology. Although such an application lacks practical utility, it reveals the general accessibility of the technology to newcomers. As a marketing wit once told me, “We have only one chance to make a first impression.” So, let’s begin with a straightforward one-liner in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>.</p>
<p><strong>About</strong> <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer"><strong>Winglang</strong></a>: <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> is an innovative cloud-oriented programming language designed to simplify cloud application development. It integrates seamlessly with cloud services, offering a unique approach to building and deploying applications directly in the cloud environment. This makes <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> an intriguing option for developers looking to leverage cloud capabilities more effectively.</p>
<p>Installing <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> is straightforward, assuming you already have <a href="https://www.npmjs.com/" target="_blank" rel="noopener noreferrer">npm</a> and <a href="https://www.terraform.io/" target="_blank" rel="noopener noreferrer">terraform</a> installed and configured on your computer. As a technology researcher, I primarily work with remote desktops. Therefore, I won’t delve into the details of preparing your workstation here. My personal setup, once stabilized, will be shared in a separate publication.</p>
<p>My first step is to create a one-line application that prints the sentence “Hello, Winglang!” In <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>, this is indeed could be done in a single line:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-text codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">log(“Hello, Winglang!”);</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>However, to <em>execute</em> this one line of code, we need to <em>compile</em> it by typing <code>wing compile</code>:</p>
<p><img decoding="async" loading="lazy" alt="Image1" src="https://www.winglang.io/assets/images/ashers-blog-1-980b95bea959ca9e7f4f69a471340617.png" width="1105" height="423" class="img_ev3q"></p>
<p><a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> adopts an intriguing approach by distinctly separating the phases of programmatic definition of cloud resources during compilation and their use during runtime. This is articulated in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> as <a href="https://www.winglang.io/docs/concepts/inflights" target="_blank" rel="noopener noreferrer">Preflight and Inflight</a> execution phases.</p>
<p>Simply put, the <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">Preflight</a> phase occurs when application code is compiled into a target orchestration engine template, such as a local simulator or <a href="https://www.terraform.io/" target="_blank" rel="noopener noreferrer">Terraform</a>, while the <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">Inflight</a> phase is when the application code executes within a Cloud Function or Container.</p>
<p>The ability to use the same syntax for programming the compilation phase and even print logs is quite a unique feature. For comparison, consider the ability to use the same syntax for programming “C” macros or C++ templates to print debugging logs of the compilation phase, just as you would program the runtime phase.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-one-hello-winglang-inflight">Step One: “Hello, Winglang!” Inflight<a class="hash-link" aria-label="Direct link to Step One: “Hello, Winglang!” Inflight" title="Direct link to Step One: “Hello, Winglang!” Inflight" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-one-hello-winglang-inflight">​</a></h2>
<p>Now, I aim to create the simplest possible application that prints the sentence “Hello, Winglang!” during runtime, that is during the <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">Inflight</a> phase. In <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>, accomplishing this requires just a couple of lines, similar to what you’d expect in any mainstream programming language:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Winglang, Preflight!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> helloWorld </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">event</span><span class="token parameter operator">:</span><span class="token parameter"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Winglang!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>By typing wing it in the <a href="https://code.visualstudio.com/docs/terminal/basics" target="_blank" rel="noopener noreferrer">VSCode Terminal</a>, you can bring up the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> simulator (I prefer the preview in the editor). Click on <code>cloud.Function</code>, then on <code>Invoke</code>, and you will see the following:</p>
<p><img decoding="async" loading="lazy" alt="Image2" src="https://www.winglang.io/assets/images/ashers-blog-2-5f967f411f7c78e1901069d3c1a103e6.png" width="1861" height="942" class="img_ev3q"></p>
<p>This is pretty cool and <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> definitely passes the initial smoke test.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-two-generalizing-functionality-by-accepting-the-name-argument">Step Two: Generalizing Functionality by Accepting the <code>name</code> Argument<a class="hash-link" aria-label="Direct link to step-two-generalizing-functionality-by-accepting-the-name-argument" title="Direct link to step-two-generalizing-functionality-by-accepting-the-name-argument" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-two-generalizing-functionality-by-accepting-the-name-argument">​</a></h2>
<p>To move beyond simply printing static text, we’re going to slightly modify our initial function to return the greeting “Hello,<code>&lt;name&gt;!</code>”, where <code>&lt;name&gt;</code> is the function’s argument. The updated code, along with the simulator’s output, will look something like this:</p>
<p><img decoding="async" loading="lazy" alt="Image3" src="https://www.winglang.io/assets/images/ashers-blog-3-f33af9fd551d2fbc83860d204ed3c54d.png" width="1863" height="938" class="img_ev3q"></p>
<p>Keep in mind, there’s no need to close the simulator. Simply edit the file, hit CTRL+S to save, and the simulator will automatically load the new version.</p>
<p>In today’s world, a system without test automation support hardly has a right to exist. Let’s add some tests to our simple function (now renamed to <code>makeGreeting</code>):</p>
<p><img decoding="async" loading="lazy" alt="Image4" src="https://www.winglang.io/assets/images/ashers-blog-4-63246fce2e11d7ef341a146b32596797.png" width="1873" height="942" class="img_ev3q"></p>
<p>Again, there’s no need to close the simulator. The entire process is interactive and flows quite smoothly.</p>
<p>You can also run the tests via the command line in the <a href="https://code.visualstudio.com/docs/terminal/basics" target="_blank" rel="noopener noreferrer">VSCode Terminal</a>:</p>
<p><img decoding="async" loading="lazy" alt="Image5" src="https://www.winglang.io/assets/images/ashers-blog-5-c385b04aaff8ef53b5c0469052a57417.png" width="580" height="258" class="img_ev3q"></p>
<p>The same test can also be run automatically in the cloud by typing, for example, <code>wing test -t tf-aws</code>. Additionally, the same code can be deployed on a target cloud.</p>
<p>Cloud neutrality support in <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> is important and fascinating topic, which will be covered in more details in the next <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#c484">Step Four: Extracting Core</a> section.</p>
<h1>Deciding if the Hexagon Approach is Right for You</h1>
<p>If all you need is to develop simple <a href="https://martinfowler.com/eaaCatalog/transactionScript.html" target="_blank" rel="noopener noreferrer">Transaction Scripts</a> that:</p>
<ul>
<li>Are triggered by an event happening to a cloud resource, e.g., <a href="https://www.winglang.io/docs/standard-library/cloud/api" target="_blank" rel="noopener noreferrer">REST API Gateway</a>.</li>
<li>Optionally retrieve data from another Cloud Resource, like a <a href="https://www.winglang.io/docs/standard-library/cloud/bucket" target="_blank" rel="noopener noreferrer">Blob Storage Bucket</a>.</li>
<li>Perform some very simple calculations.</li>
<li>Optionally send data to another Cloud Resource, such as a <a href="https://www.winglang.io/docs/standard-library/cloud/bucket" target="_blank" rel="noopener noreferrer">Blob Storage Bucket</a>.</li>
<li>Can ideally be written once and require minimal maintenance.</li>
</ul>
<p>Then you may choose to stop here. Explore <a href="https://github.com/winglang/wing/tree/main/examples" target="_blank" rel="noopener noreferrer">Winglang Examples</a> to see what can be achieved today, and visit <a href="https://github.com/winglang/wing/issues" target="_blank" rel="noopener noreferrer">Winglang Issues</a> for insights on current limitations and future plans. However, if you’re interested in exploring how <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> supports complex software architectures with potentially intricate computational logic and long-term support requirements, you are welcome to proceed to Part Two of this publication.</p>
<h1>Part Two: Encapsulating the Core within Hexagon</h1>
<p><a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Architecture</a>, introduced by <a href="https://en.wikipedia.org/wiki/Alistair_Cockburn" target="_blank" rel="noopener noreferrer">Alistair Cockburn</a> in 2005, represented a significant shift in the way software applications were structured. Also known as the Ports and Adapters pattern, this architectural style was designed to create a clear separation between an application’s core logic and its external components. It enables applications to be equally driven by users, programs, automated tests, or batch scripts, and allows for development and testing in isolation from runtime devices and databases. By organizing interactions through ‘ports’ and ‘adapters’, the architecture ensures that the application remains agnostic to the nature of external technologies and interfaces. This approach not only prevented the infiltration of business logic into user interface code but also enhanced the flexibility and maintainability of software, making it adaptable to various environments and technologies.</p>
<p>While I believe that <a href="https://en.wikipedia.org/wiki/Alistair_Cockburn" target="_blank" rel="noopener noreferrer">Alistair Cockburn</a>, like many other practitioners, may have misinterpreted the original intent of layered software architecture as introduced by <a href="https://en.wikipedia.org/wiki/Edsger_W._Dijkstra" target="_blank" rel="noopener noreferrer">E.W. Dijkstra</a> in his seminal work, <a href="https://www.eecs.ucf.edu/~eurip/papers/dijkstra-the68.pdf" target="_blank" rel="noopener noreferrer">“The Structure of ‘THE’ Multiprogramming System”</a> (a topic I plan to address in a separate publication), the foundational idea he presents remains useful. As I argued in my <a href="https://medium.com/analytics-vidhya/if-your-computer-is-cloud-how-its-operating-system-should-look-like-24f62e274a95" target="_blank" rel="noopener noreferrer">earlier publication</a>, the Ports metaphor aligns well with cloud resources that trigger specific events, while software modules interacting directly with the cloud SDK effectively function as Adapters.</p>
<p>Numerous attempts (see <a href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#6888">References</a>) have been made to apply <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Architecture</a> concepts to cloud and, more specifically, serverless development. A notable example is the blog post <a href="https://aws.amazon.com/blogs/compute/developing-evolutionary-architecture-with-aws-lambda/" target="_blank" rel="noopener noreferrer">“Developing Evolutionary Architecture with AWS Lambda,”</a> which showcases a repository structure closely aligned with what I envision. However, even this example employs a more complex application than what I believe is necessary for initial exploration. I firmly hold that we should fully understand and explore the simplest possible applications, at the “Hello, World!” level, before delving into more complex scenarios. With this in mind, let’s examine how far we can go in building a straightforward Greeting Service.</p>
<h1>Step Four: Extracting Core</h1>
<p>First and foremost, our goal is to extract the Core and ensure its complete independence from any external dependencies:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Greeting</span><span class="token plain"> impl cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IFunctionHandler</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, {name}!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>At the moment, the <a href="https://www.winglang.io/docs/language-reference#4-module-system" target="_blank" rel="noopener noreferrer">Winglang Module System</a> does not support public functions. I does, however, support public static class functions, which semantically are equivalent. Unfortunately, I cannot directly pass a public static inflight function to <code>cloud.Function</code> (it only works for closures), and I need to implement the <code>cloud.IFunctionHandler</code> interface. These limitations are fairly understandable and quite typical for a new programming system.</p>
<p>By extracting the core into a separate module, we can focus on what brings the application to life in the first place. This also enables extensive testing of the core logic independently, as shown below:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./core"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greeting </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">core</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 'Hello, &lt;name&gt;!'"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, World!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"World"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Winglang!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Winglang"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Keeping the simulator up with only the core test allows us to quickly explore application logic and discuss it with stakeholders without worrying about cloud resources. This approach often epitomizes what a true MVP (Minimum Viable Product) is about:</p>
<p><img decoding="async" loading="lazy" alt="Image6" src="https://www.winglang.io/assets/images/ashers-blog-6-543e64dc8c6c0fa54b1afd82103b6bd6.png" width="1509" height="804" class="img_ev3q"></p>
<p>The main file is now streamlined, focusing on system-level packaging and testing:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./core"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> makeGreeting </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token parameter">str</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Received: {name}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greeting </span><span class="token operator">=</span><span class="token plain"> core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Returned: {greeting}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 'Hello, `&lt;name&gt;`!'"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Winglang!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Winglang"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To consolidate everything, it’s time to introduce a <code>Makefile</code> to automate the entire process:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">PHONY</span><span class="token operator">:</span><span class="token plain"> all test_core test_local test_remote</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">cloud </span><span class="token operator">?</span><span class="token operator">=</span><span class="token plain"> aws</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token literal-property property">all</span><span class="token operator">:</span><span class="token plain"> test_remote</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token literal-property property">test_core</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wing test test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">t sim</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token literal-property property">test_local</span><span class="token operator">:</span><span class="token plain"> test_core</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wing test main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">t sim</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token literal-property property">test_remote</span><span class="token operator">:</span><span class="token plain"> test_local</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wing test main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">t tf</span><span class="token operator">-</span><span class="token function" style="color:rgb(80, 250, 123)">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Here, I’ve defined a <code>Makefile</code> variable <code>cloud</code> with the default value <code>aws</code>, which specifies the target cloud platform for remote tests. By using <a href="https://www.terraform.io/" target="_blank" rel="noopener noreferrer">Terraform</a> as an orchestration engine, I ensure that the same code and <code>Makefile</code> will run without any changes on any cloud platform supported by <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>, such as <code>aws</code>, <code>gcp</code>, or <code>azure</code>.</p>
<p>The output of remote testing is worth examining:</p>
<p><img decoding="async" loading="lazy" alt="Image7" src="https://www.winglang.io/assets/images/ashers-blog-7-aafc787f9399e65828a5e0581bb50b40.png" width="1217" height="937" class="img_ev3q"></p>
<p>As we can see, <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> automatically converts the <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">Preflight</a> code into <a href="https://www.terraform.io/" target="_blank" rel="noopener noreferrer">Terraform</a> templates and invokes <a href="https://www.terraform.io/" target="_blank" rel="noopener noreferrer">Terraform</a> commands to deploy the resulting stack to the cloud. It then runs the same test, effectively executing the <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">Inflight</a> code on the actual cloud, <code>aws</code> in this case, and finally deletes all resources. In such cases, I don't even need to access the cloud console to monitor the process. I can treat the cloud as a supercomputer, working with it through <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>'s <a href="https://en.wikipedia.org/wiki/Cross_compiler" target="_blank" rel="noopener noreferrer">cross-compilation</a> mechanism.</p>
<p>The project structure now mirrors our architectural intent:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">greeting</span><span class="token operator">-</span><span class="token plain">service</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── core</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│ └── </span><span class="token maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token maybe-class-name">Makefile</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">└── test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h1>Step Five: Extracting the <code>makeGreeting(name)</code> Request Handler</h1>
<p>The core functionality should be purely computational, stateless, and free from side effects. This is crucial to ensure that the core does not depend on any external framework and can be fully tested automatically. Introducing states or external side effects would generally hinder this possibility. However, we still aim to isolate application logic from the real environment represented by Ports and Adapters. To achieve this, we introduce a separate Request Handler module, as follows:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"../core"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Greeting</span><span class="token plain"> impl cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IFunctionHandler</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Received: {name}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greeting </span><span class="token operator">=</span><span class="token plain"> core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Returned: {greeting}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>In this case, the <code>GreetingHandler</code> is responsible for logging, which is a side effect. In more complex applications, it would communicate with external databases, message buses, third-party services, etc., via Ports and Adapters.</p>
<p>The core logic is now encapsulated as a plain function and is no longer derived from the <code>cloud.IFunctionHandler</code> interface:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Greeting</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> inflight </span><span class="token function" style="color:rgb(80, 250, 123)">makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, {name}!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The unit test for the core logic is accordingly simplified:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./core"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 'Hello, &lt;name&gt;!'"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, World!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"World"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Wing!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Wing"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The responsibility of connecting the handler and core logic now falls to the <code>main.w</code> module:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./handlers"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> handlers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greetingHandler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">handlers</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> makeGreetingFunction </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greetingHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 'Hello, &lt;name&gt;!'"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Wing!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> makeGreetingFunction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Wing"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Once again, the project structure reflects our architectural intent:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">greeting</span><span class="token operator">-</span><span class="token plain">service</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── core</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── handlers</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token maybe-class-name">Makefile</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">└── test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>It should be noted that for a simple service like Greeting, such an evolved structure could be considered over-engineering and not justified by actual business needs. However, as a software architect, it’s essential for me to outline a general skeleton for a fully-fledged service without getting bogged down in application-specific complexities that might not yet be known. By isolating different system components from one another, we make future system evolution less painful, and in many cases just practically feasible. In such cases, investing in a preliminary system structure by following best practices is fully justified and necessary. As <a href="https://en.wikipedia.org/wiki/Grady_Booch" target="_blank" rel="noopener noreferrer">Grady Booch</a> famously said, “One cannot refactor a doghouse into a skyscraper.”</p>
<p>In general, keeping core functionality purely stateless and free from side effects, and isolating stateful application behavior with potential side effects into separate handlers, is conceptually equivalent to the <a href="https://en.wikipedia.org/wiki/Monad_(functional_programming)" target="_blank" rel="noopener noreferrer">monadic programming</a> style widely adopted in Functional Programming environments.</p>
<h1>Step Six: Connecting the Handler via Cloud Function Port</h1>
<p>We can now remove the direct <code>cloud.Function</code> creation from the main module and encapsulate it into a separate <code>GreetingFunction</code> port as follows:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./handlers"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> handlers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./ports"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greetingHandler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">handlers</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> makeGreetingService </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ports</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">GreetingFunction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greetingHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 'Hello, &lt;name&gt;!'"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Wing!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> makeGreetingService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Wing"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>GreetingFunction</code> is defined in a separate module like this:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">GreetingFunction</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    \_f</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token known-class-name class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IFunctionHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\_f </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Function</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\_f</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This separation of concerns allows the <code>main.w</code> module to focus on connecting different parts of the system together. Specific port configuration is performed in a separate module dedicated to that purpose. While such isolation of <code>GreetingHandler</code> might seem unnecessary at this stage, it becomes more relevant when considering the nuanced configuration supported by <a href="https://www.winglang.io/docs/standard-library/cloud/function" target="_blank" rel="noopener noreferrer">Winglang cloud.Function</a>, including execution platform (e.g., AWS Lambda vs Container), environment variables, timeout, maximum resources, etc. Extracting the <code>GreetingFunction</code> port definition into a separate module naturally facilitates the concealment of these details.</p>
<p>The project structure is updated accordingly:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">greeting</span><span class="token operator">-</span><span class="token plain">service</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── core</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── handlers</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── ports</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── greetingFunction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token maybe-class-name">Makefile</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">└── test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The adopted naming convention for port modules also allows for the inclusion of multiple port definitions within the same project, enabling the selection of the required one based on external configuration.</p>
<h1>Step Seven: Reimplementing the Core in TypeScript</h1>
<p>There are several reasons why a project might consider implementing its core functionality in a mainstream programming language that can still run atop the underlying runtime environment. For example, using <a href="https://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer">TypeScript</a>, which compiles into <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank" rel="noopener noreferrer">JavaScript</a>, and can be integrated with <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a>. Here are some of the most common reasons:</p>
<ul>
<li><strong>Risk Mitigation:</strong> Preserving the core regardless of the cloud programming environment in use.</li>
<li><strong>Available Skills:</strong> It’s often easier to find developers familiar with a mainstream language than with a new one.</li>
<li><strong>Existing Code Base:</strong> Typical brownfield situations.</li>
<li><strong>3rd Party Libraries:</strong> Essential for core functionality, such as specific algorithms.</li>
<li><strong>Automation Ecosystem Maturity:</strong> More options are available for exhaustive testing of core functionality in mainstream languages.</li>
<li><strong>Support for Specific Styles:</strong> For instance, better support for pure functional programming.</li>
</ul>
<p>The Greeting service core functionality, redeveloped in <a href="https://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer">TypeScript</a>, would look like this:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">name</span><span class="token parameter operator">:</span><span class="token parameter"> string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> string </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> \`</span><span class="token maybe-class-name">Hello</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> $</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token operator">!</span><span class="token plain">\`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Its unit test, developed using the <a href="https://jestjs.io/" target="_blank" rel="noopener noreferrer">jest</a> framework, would be:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> makeGreeting </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@core/makeGreeting"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">describe</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"makeGreeting"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">it</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"should return a greeting with the provided name"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> name </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"World"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> expected </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, World!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> result </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">toBe</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">expected</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To make it accessible to <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> language modules, a simple wrapper is needed:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Greeting</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub extern </span><span class="token string" style="color:rgb(255, 121, 198)">"../target/core/makeGreeting.js"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> inflight  </span><span class="token function" style="color:rgb(80, 250, 123)">makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The main technical challenge is to place the compiled <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank" rel="noopener noreferrer">JavaScript</a> version where the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> wrapper can find it. For this project, I decided to use the <code>target</code> folder, where the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> compiler puts its artifacts. To achieve this, I created a dedicated <code>tsconfig.build.json</code>:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-json codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"extends"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./tsconfig.json"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"compilerOptions"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"outDir"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./target"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token comment" style="color:rgb(98, 114, 164)">// ... production-specific compiler options ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"exclude"</span><span class="token operator">:</span><span class="token plain"> \</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token string" style="color:rgb(255, 121, 198)">"core/\*.test.ts"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    \</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>Makefile</code> was also modified to automate the process:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">PHONY</span><span class="token operator">:</span><span class="token plain"> all install test\_core test\_local test\_remote</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">cloud </span><span class="token operator">?</span><span class="token operator">=</span><span class="token plain"> aws</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token literal-property property">all</span><span class="token operator">:</span><span class="token plain"> test\_remote</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token literal-property property">install</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> npm install</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test\_core</span><span class="token operator">:</span><span class="token plain"> install</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> npm run test</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">build\_core</span><span class="token operator">:</span><span class="token plain"> test\_core</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> npm run build</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test\_local</span><span class="token operator">:</span><span class="token plain"> build\_core</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wing test main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">t sim</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test\_remote</span><span class="token operator">:</span><span class="token plain"> test\_local</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wing test main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">t tf</span><span class="token operator">-</span><span class="token function" style="color:rgb(80, 250, 123)">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The folder structure reflects the changes made:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">greeting</span><span class="token operator">-</span><span class="token plain">service</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── core</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── handlers</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── ports</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── greetingFunction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── jest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token maybe-class-name">Makefile</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">package</span><span class="token operator">-</span><span class="token plain">lock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">package</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── tsconfig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">build</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">└── tsconfig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-eight-implementing-the-rest-api-port">Step Eight: Implementing the REST API Port<a class="hash-link" aria-label="Direct link to Step Eight: Implementing the REST API Port" title="Direct link to Step Eight: Implementing the REST API Port" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-eight-implementing-the-rest-api-port">​</a></h2>
<p>Now, let’s consider making our Greeting service accessible via a REST API. This could be necessary, for instance, to enable demonstrations from a web browser or to facilitate calls from external services that, due to security or technological constraints, cannot communicate directly with the <code>GreetingFunction</code> port. To accomplish this, we need to introduce a new Port definition and modify the <code>main.w</code> module, while keeping everything else unchanged:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">GreetingApi</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub apiUrl</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IFunctionHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> api </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"/greetings"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token parameter maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token literal-property property">status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"name"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">apiUrl</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> result </span><span class="token operator">=</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{this.apiUrl}/greetings?name={name}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">assert</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">200</span><span class="token plain"> </span><span class="token operator">==</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To maintain a consistent testing interface, I implemented an <code>invoke</code> method that functions similarly to the <code>GreetingFunction</code> port. This design choice is not mandatory but rather a matter of convenience to minimize the amount of change.</p>
<p>The <code>main.w</code> module now allocates the <code>GreetingApi</code> port:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./handlers"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> handlers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./ports"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greetingHandler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">handlers</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> makeGreetingService </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ports</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">GreetingApi</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greetingHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 'Hello, &lt;name&gt;!'"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Wing!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> makeGreetingService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Wing"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Since there is now something to use externally, the <code>Makefile</code> was modified to include <code>deploy</code> and <code>destroy</code> targets,as follows:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">PHONY</span><span class="token operator">:</span><span class="token plain"> all install test\_core build\_core update test\_adapters test\_local test\_remote compile tf</span><span class="token operator">-</span><span class="token plain">init deploy destroy</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">cloud </span><span class="token operator">?</span><span class="token operator">=</span><span class="token plain"> aws</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token literal-property property">target</span><span class="token plain"> </span><span class="token operator">:</span><span class="token operator">=</span><span class="token plain"> target</span><span class="token operator">/</span><span class="token plain">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tf$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token literal-property property">all</span><span class="token operator">:</span><span class="token plain"> test\_remote</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token literal-property property">install</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> npm install</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test\_core</span><span class="token operator">:</span><span class="token plain"> install</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> npm run test</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">build\_core</span><span class="token operator">:</span><span class="token plain"> test\_core</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> npm run build</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token literal-property property">update</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> sudo npm update </span><span class="token operator">-</span><span class="token plain">g wing</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test\_adapters</span><span class="token operator">:</span><span class="token plain"> update</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wing test test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">adapters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">t sim</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test\_local</span><span class="token operator">:</span><span class="token plain"> build\_core test\_adapters</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wing test test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">t sim</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test\_remote</span><span class="token operator">:</span><span class="token plain"> test\_local</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wing test test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">t tf</span><span class="token operator">-</span><span class="token function" style="color:rgb(80, 250, 123)">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token literal-property property">compile</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wing compile main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">t tf</span><span class="token operator">-</span><span class="token function" style="color:rgb(80, 250, 123)">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">tf</span><span class="token operator">-</span><span class="token plain">init</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">compile</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"> \\</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  cd </span><span class="token function" style="color:rgb(80, 250, 123)">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">target</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">\\</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  terraform init \\</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token literal-property property">deploy</span><span class="token operator">:</span><span class="token plain"> tf</span><span class="token operator">-</span><span class="token function" style="color:rgb(80, 250, 123)">init</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"> \\</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  cd </span><span class="token function" style="color:rgb(80, 250, 123)">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">target</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">\\</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  terraform apply </span><span class="token operator">-</span><span class="token plain">auto</span><span class="token operator">-</span><span class="token plain">approve \\</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token literal-property property">destroy</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"> \\</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  cd </span><span class="token function" style="color:rgb(80, 250, 123)">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">target</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">\\</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  terraform destroy </span><span class="token operator">-</span><span class="token plain">auto</span><span class="token operator">-</span><span class="token plain">approve \\</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The browser screen looks almost as expected, but notice a strange <code>JSON.parse</code> error message (will be addressed in the forthcoming section):</p>
<p>The project structure is updated to reflect these changes:</p>
<p><img decoding="async" loading="lazy" alt="Image8" src="https://www.winglang.io/assets/images/ashers-blog-8-0790d08f3daea6fe17b814a0d8072c88.png" width="1011" height="300" class="img_ev3q"></p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">greeting</span><span class="token operator">-</span><span class="token plain">service</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── core</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── handlers</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── ports</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── greetingApi</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── greetingFunction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── jest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token maybe-class-name">Makefile</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">package</span><span class="token operator">-</span><span class="token plain">lock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">package</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── tsconfig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">build</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">└── tsconfig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-nine-extracting-the-rest-api-request-adapter">Step Nine: Extracting the REST API Request Adapter<a class="hash-link" aria-label="Direct link to Step Nine: Extracting the REST API Request Adapter" title="Direct link to Step Nine: Extracting the REST API Request Adapter" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-nine-extracting-the-rest-api-request-adapter">​</a></h2>
<p>The <code>GreetingApi</code> port implementation introduced in the previous section slightly violates the <a href="https://en.wikipedia.org/wiki/Single_responsibility_principle" target="_blank" rel="noopener noreferrer">Single Responsibility Principle</a>, which states: “A class should have only one reason to change.” Currently, there are multiple potential reasons for change:</p>
<ol>
<li><strong>HTTP Routing Conventions:</strong> URL path with or without variable parts.</li>
<li><strong>HTTP Request Processing.</strong></li>
<li><strong>HTTP Response Formatting.</strong></li>
</ol>
<p>We can generally agree that while HTTP Request Processing and HTTP Response Formatting are closely related, HTTP Routing stands apart. To decouple these functionalities, we introduce an <code>ApiAdapter</code> responsible for converting <code>cloud.ApiRequest</code> to <code>cloud.ApiResponse</code>, thereby extracting this functionality from the <code>GreetingApi</code> port.</p>
<p>To achieve this, we introduce a new <code>IRestApiAdapter</code> interface:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">interface</span><span class="token plain"> </span><span class="token class-name">IRestApiAdapter</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    inflight </span><span class="token function" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>GreetingApiAdapter</code> class is defined as follows:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./IRestApiAdapter.w"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> restApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">GreetingApiAdapter</span><span class="token plain"> impl restApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IRestApiAdapter</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    \_h</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IFunctionHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IFunctionHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\_h </span><span class="token operator">=</span><span class="token plain"> handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    inflight pub </span><span class="token function" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token literal-property property">status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\_h</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"name"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The modified <code>GreetingApi</code> port class is now:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"../adapters/IRestApiAdapter.w"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> restApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">GreetingApi</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    \_apiUrl</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    \_adapter</span><span class="token operator">:</span><span class="token plain"> restApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IRestApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">adapter</span><span class="token operator">:</span><span class="token plain"> restApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IRestApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> api </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\_adapter </span><span class="token operator">=</span><span class="token plain"> adapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"/greetings"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token parameter maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\_adapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\_apiUrl </span><span class="token operator">=</span><span class="token plain"> api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub inflight </span><span class="token function" style="color:rgb(80, 250, 123)">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> result </span><span class="token operator">=</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"{this.\_apiUrl}/greetings?name={name}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">assert</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">200</span><span class="token plain"> </span><span class="token operator">==</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>main.w</code> module is updated accordingly:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./handlers"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> handlers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./ports"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./adapters"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> adapters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greetingHandler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">handlers</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greetingStringAdapter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">adapters</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">GreetingApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greetingHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> makeGreetingService </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ports</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">GreetingApi</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greetingStringAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 'Hello, &lt;name&gt;!'"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Wing!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> makeGreetingService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Wing"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The project structure reflects these changes:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">greeting</span><span class="token operator">-</span><span class="token plain">service</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── adapters</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── greetingApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">IRestApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── core</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── handlers</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── ports</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── greetingApi</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── greetingFunction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── jest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token maybe-class-name">Makefile</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">package</span><span class="token operator">-</span><span class="token plain">lock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">package</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── tsconfig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">build</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">└── tsconfig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-ten-testing-the-rest-api-request-adapter">Step Ten: Testing the REST API Request Adapter<a class="hash-link" aria-label="Direct link to Step Ten: Testing the REST API Request Adapter" title="Direct link to Step Ten: Testing the REST API Request Adapter" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-ten-testing-the-rest-api-request-adapter">​</a></h2>
<p>Extracting the <code>GreetingApiAdapter</code> from the <code>GreetingApi</code> port might seem like a purist action, performed to demonstrate the potential value of Adapters, even if artificially and not strictly necessary. However, this perspective changes when we consider serious testing. The <code>GreetingApiAdapter</code> implementation from the previous section assumes that the <code>name</code> argument always comes within the <code>query</code> part of the HTTP request. But what happens if it doesn't? The system will crash, while according to standard it should respond with the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400" target="_blank" rel="noopener noreferrer">HTTP 400 (Bad Request)</a> status code in such cases. The modified structure allows us to introduce a separate unit test fully dedicated to testing the <code>GreetingApiAdapter</code>:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./adapters"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> adapters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./handlers"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> handlers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greetingHandler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">handlers</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greetingStringAdapter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">adapters</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">GreetingStringRestApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greetingHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 200 and correct answer when name supplied"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> request </span><span class="token operator">=</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">method</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">HttpMethod</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">GET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">path</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"/greetings"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">query</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"name"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Wing"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">vars</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> greetingStringAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Wing!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 400 and error message when name is not supplied"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> request </span><span class="token operator">=</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">method</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">HttpMethod</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">GET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">path</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"/greetings"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">query</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"somethingElse"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"doesNotMatter"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">vars</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> greetingStringAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">400</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Query name=&lt;name&gt; is missing"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Running this test with the existing implementation will result in failure, necessitating the following changes:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./IRestApiAdapter.w"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> restApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">GreetingStringRestApiAdapter</span><span class="token plain"> impl restApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IRestApiAdapter</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    \_h</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IFunctionHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IFunctionHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\_h </span><span class="token operator">=</span><span class="token plain"> handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    inflight pub </span><span class="token function" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> name </span><span class="token operator">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryGet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"name"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token literal-property property">status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\_h</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token literal-property property">status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">400</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Query name=&lt;name&gt; is missing"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The main lesson from this story is that system complexity can exist in multiple places, not always within the core logic. Separation of concerns aids in managing this complexity through dedicated and isolated test suites.</p>
<h1>Step Eleven: Extracting the <code>GreetingService</code></h1>
<p>After all the modifications made, the resulting version of the <code>main.w</code> module has become quite complex, incorporating the logic of wiring system handlers, ports, and adapters. Additionally, maintaining end-to-end system tests within the same module is only feasible up to a point. Different testing and production environments may be necessary to address various security and cost considerations. To tackle these issues, it's advisable to extract the <code>GreetingService</code> configuration into a separate module:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./handlers"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> handlers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./ports"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./adapters"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> adapters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Greeting</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    pub api</span><span class="token operator">:</span><span class="token plain"> ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">GreetingApi</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greetingHandler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">handlers</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greetingStringAdapter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">adapters</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">GreetingStringRestApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greetingHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">api</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ports</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">GreetingApi</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greetingStringAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Ideally, the creation of the Greeting service object should be implemented using a static method, following the <a href="https://en.wikipedia.org/wiki/Factory_method_pattern" target="_blank" rel="noopener noreferrer">Factory Method</a> design pattern. However, I encountered difficulties in this approach, as <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">Preflight</a> static functions require a context, which I was unable to determine how to obtain. Nonetheless, even in this form, extracting the Greeting service class opens up multiple possibilities for different configurations in testing and production environments. The main.w module can now be relieved of the testing code:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./service.w"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greetingService </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">service</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The system end-to-end test is now placed in its dedicated <code>test.main.w</code> module:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./service.w"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greetingService </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">service</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 'Hello, &lt;name&gt;!'"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Wing!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> greetingService</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">api</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Wing"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>In this case, code duplication is minimal, and as previously mentioned, a real system will have different configurations for test and production environments. The detailed specifications for these will be passed to the <code>Greeting</code> service class constructor.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-twelve-enhancing-rest-api-request-adapter-for-content-negotiation">Step Twelve: Enhancing REST API Request Adapter for Content Negotiation<a class="hash-link" aria-label="Direct link to Step Twelve: Enhancing REST API Request Adapter for Content Negotiation" title="Direct link to Step Twelve: Enhancing REST API Request Adapter for Content Negotiation" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#step-twelve-enhancing-rest-api-request-adapter-for-content-negotiation">​</a></h2>
<p>Now, I aim to put the resulting architecture to the final test by partially implementing <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation" target="_blank" rel="noopener noreferrer">HTTP Content Negotiation</a>. Specifically, the <code>Greeting</code> service should support returning a greeting statement as plain text, HTML, or JSON, depending on the client's request. The appropriate way to express these requirements is to modify the <code>GreetingApiAdapter</code> unit test as follows:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./adapters"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> adapters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./handlers"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> handlers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greetingHandler </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">handlers</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greetingStringAdapter </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">adapters</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">GreetingApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greetingHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 200 and plain text answer when name is supplied without headers"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> request </span><span class="token operator">=</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">method</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">HttpMethod</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">GET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">path</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"/greetings"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">query</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"name"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Wing"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">vars</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> greetingStringAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Wing!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"text/plain"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">headers</span><span class="token operator">?.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 200 and json answer when name is supplied with headers Accept: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> request </span><span class="token operator">=</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">method</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">HttpMethod</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">GET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">path</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"/greetings"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">query</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"name"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Wing"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"Accept"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"application/json"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">vars</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> greetingStringAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"application/json"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">headers</span><span class="token operator">?.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> data </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryParse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> expected </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token maybe-class-name">Json</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">greeting</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Wing!"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">expected</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 200 and html answer when name is supplied with headers Accept: text/html"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> request </span><span class="token operator">=</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">method</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">HttpMethod</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">GET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">path</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"/greetings"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">query</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"name"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Wing"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"Accept"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"text/html"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">vars</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> greetingStringAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"text/html"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">headers</span><span class="token operator">?.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> body </span><span class="token operator">=</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">assert</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">contains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, Wing!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"it will return 400 and error message when name is not supplied"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> request </span><span class="token operator">=</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">method</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">HttpMethod</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">GET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">path</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"/greetings"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">query</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"somethingElse"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"doesNotMatter"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token literal-property property">vars</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> greetingStringAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">400</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">status</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Query name=&lt;name&gt; is missing"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"text/plain"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">headers</span><span class="token operator">?.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Suddenly, having a separate class for HTTP request/response handling doesn’t seem like a purely theoretical exercise, but rather a very pragmatic architectural decision. To make these tests pass, substantial modifications are needed in the <code>GreetingApiAdapter</code> class:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"./IRestApiAdapter.w"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> restApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring </span><span class="token string" style="color:rgb(255, 121, 198)">"../core"</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">GreetingApiAdapter</span><span class="token plain"> impl restApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IRestApiAdapter</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    \_h</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IFunctionHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">handler</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IFunctionHandler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\_h </span><span class="token operator">=</span><span class="token plain"> handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> \</span><span class="token function" style="color:rgb(80, 250, 123)">_textPlain</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greeting</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    inflight </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> \</span><span class="token function" style="color:rgb(80, 250, 123)">_applicationJson</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greeting</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> responseBody </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token literal-property property">greeting</span><span class="token operator">:</span><span class="token plain"> greeting</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stringify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">responseBody</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    inflight \</span><span class="token function" style="color:rgb(80, 250, 123)">_findContentType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">formatters</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token literal-property property">headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> str </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> contentTypes </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">headers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryGet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Accept"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">split</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">","</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> ct </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> contentTypes </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> formatters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">has</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">ct</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> ct</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"text/plain"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    inflight \</span><span class="token function" style="color:rgb(80, 250, 123)">_buildOkResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token known-class-name class-name">Map</span><span class="token operator">&lt;</span><span class="token plain">str</span><span class="token operator">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token literal-property property">name</span><span class="token operator">:</span><span class="token plain"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> greeting </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\_h</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// TODO: guard against empty greeting or what??</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> formatters </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"text/plain"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token maybe-class-name">GreetingApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\_textPlain</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"text/html"</span><span class="token plain">  </span><span class="token arrow operator">=&gt;</span><span class="token plain"> core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">formatHtml</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"application/json"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token maybe-class-name">GreetingApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\_applicationJson</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> contentType </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\</span><span class="token function" style="color:rgb(80, 250, 123)">_findContentType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">formatters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> headers</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token literal-property property">status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">200</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> formatters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">contentType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token literal-property property">headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> contentType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    inflight pub </span><span class="token function" style="color:rgb(80, 250, 123)">handle</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> name </span><span class="token operator">=</span><span class="token plain"> request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryGet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"name"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">\</span><span class="token function" style="color:rgb(80, 250, 123)">_buildOkResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">headers</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">ApiResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token literal-property property">status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">400</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token literal-property property">body</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Query name=&lt;name&gt; is missing"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token literal-property property">headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type"</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"text/plain"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Notice how quickly the complexity escalates. We’re not done yet, as we need a proper HTML formatter. The easiest way to implement it seemed to be in <a href="https://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer">TypeScript</a>, so I decided to place it in the core package:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">formatHtml</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">greeting</span><span class="token parameter operator">:</span><span class="token parameter"> string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> string </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> \`</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token operator">&lt;</span><span class="token operator">!</span><span class="token constant" style="color:rgb(189, 147, 249)">DOCTYPE</span><span class="token plain"> html</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token operator">&lt;</span><span class="token plain">html lang</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"en"</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token operator">&lt;</span><span class="token plain">head</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token operator">&lt;</span><span class="token plain">meta charset</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"UTF-8"</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token operator">&lt;</span><span class="token plain">meta name</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"viewport"</span><span class="token plain"> content</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"width=device-width, initial-scale=1.0"</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token operator">&lt;</span><span class="token plain">title</span><span class="token operator">&gt;</span><span class="token maybe-class-name">Wing</span><span class="token plain"> </span><span class="token maybe-class-name">Greeting</span><span class="token plain"> </span><span class="token maybe-class-name">Service</span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token plain">title</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token operator">&lt;</span><span class="token operator">!</span><span class="token operator">--</span><span class="token plain"> </span><span class="token maybe-class-name">Tailwind</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">CSS</span><span class="token plain"> </span><span class="token maybe-class-name">Play</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">CDN</span><span class="token plain"> </span><span class="token literal-property property">https</span><span class="token operator">:</span><span class="token operator">/</span><span class="token operator">/</span><span class="token plain">tailwindcss</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">com</span><span class="token operator">/</span><span class="token plain">docs</span><span class="token operator">/</span><span class="token plain">installation</span><span class="token operator">/</span><span class="token plain">play</span><span class="token operator">-</span><span class="token plain">cdn </span><span class="token operator">--</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token operator">&lt;</span><span class="token plain">script src</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"https://cdn.tailwindcss.com"</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token plain">script</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token plain">head</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token operator">&lt;</span><span class="token plain">body </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"flex items-center justify-center h-screen"</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token operator">&lt;</span><span class="token plain">div </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"text-center"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> id</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"greeting"</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token operator">&lt;</span><span class="token plain">h1 </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"text-2xl font-bold"</span><span class="token operator">&gt;</span><span class="token plain">$</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token plain">h1</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token plain">div</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token plain">body</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token operator">&lt;</span><span class="token operator">/</span><span class="token plain">html</span><span class="token operator">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    \`</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>There is, of course, a separate unit test for it:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> formatHtml </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@core/formatHtml"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">describe</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"formatHtml"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">it</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"should return a properly formatted HTML greeting page"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> greeting </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hello, World!"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> result </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">formatHtml</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">toContain</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Placing the HTML response formatter in the core package could be debated as a violation of <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Architecture</a> principles. Indeed, formatting an HTML response doesn’t seem to belong to the core application logic. Technically, relocating it wouldn’t be too hard, and in a larger real-world system, that’s probably what should be done. However, I chose to place it there to consolidate all <a href="https://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer">TypeScript</a>-related components in one place and to test and build them through the same set of <code>Makefile</code> targets.</p>
<p>Now, the browser gets response in format it could understand and render properly:</p>
<p><img decoding="async" loading="lazy" alt="Image9" src="https://www.winglang.io/assets/images/ashers-blog-9-d5d3d5c0c79534d6370f4fa3759c3f73.png" width="1873" height="1025" class="img_ev3q"></p>
<p>As stated at the outset, the objectives of this technology research report were to explore:</p>
<ul>
<li>How well <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> supports the <a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" target="_blank" rel="noopener noreferrer">Clean Architecture</a> style, based on the <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Ports and Adapters</a> pattern.</li>
<li>The ease of integrating <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> with <a href="https://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer">TypeScript</a>, a mainstream programming language that compiles into <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank" rel="noopener noreferrer">JavaScript</a> and runs on the <a href="https://nodejs.org/en" target="_blank" rel="noopener noreferrer">NodeJS</a> runtime engine.</li>
</ul>
<p>The exploration was conducted using the simplest “Hello, World!” application, which evolved into the <code>GreetingService</code> through twelve incremental steps, each introducing a minor modification to the previous code base. This resulted in the following project structure:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">greeting</span><span class="token operator">-</span><span class="token plain">service</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── adapters</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── greetingApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">IRestApiAdapter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── core</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── makeGreeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── handlers</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── </span><span class="token maybe-class-name">Greeting</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── ports</span><span class="token operator">/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── greetingApi</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│   └── greetingFunction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── jest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">js</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token maybe-class-name">Makefile</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">package</span><span class="token operator">-</span><span class="token plain">lock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">package</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">adapters</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── test</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">├── tsconfig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">build</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">└── tsconfig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">json</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>In my view, this structure reflects the overall service architecture quite well. As a minor improvement, I would consider relocating the <a href="https://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer">TypeScript</a> related files to a sub-level within the <code>core</code> folder.</p>
<p>Overall, the <a href="https://www.winglang.io/docs/language-reference#4-module-system" target="_blank" rel="noopener noreferrer">Winglang Module System</a> passed the initial test, providing substantial support for the separation of concerns as prescribed by the <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">Hexagonal Ports and Adapters</a> pattern. It also offers reasonable support for interoperability with <a href="https://nodejs.org/en" target="_blank" rel="noopener noreferrer">NodeJS</a> runtime engine-based languages, such as <a href="https://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer">TypeScript</a>. My wish list for potential improvements includes:</p>
<ul>
<li>Support for <a href="https://www.winglang.io/docs/concepts/inflights#preflight-code" target="_blank" rel="noopener noreferrer">Preflight</a> static functions in modules other than <code>main.w</code>, essential for the effective implementation of the <a href="https://en.wikipedia.org/wiki/Factory_method_pattern" target="_blank" rel="noopener noreferrer">Factory Method</a> design pattern, crucial for supporting non-trivial service configurations.</li>
<li>Automatic lifting of <a href="https://www.winglang.io/docs/concepts/inflights#inflight-code" target="_blank" rel="noopener noreferrer">Inflight</a> static functions in modules other than <code>main.w</code> (this worked for <a href="https://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer">TypeScript</a> external functions), to eliminate the need for some extra boilerplate.</li>
<li>Automatic generation of <a href="https://www.winglang.io/" target="_blank" rel="noopener noreferrer">Winglang</a> wrappers for external functions.</li>
</ul>
<p>This report evaluates the <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> programming language for implementing one sequential <em>stage</em> of a more general <a href="https://en.wikipedia.org/wiki/Staged_event-driven_architecture" target="_blank" rel="noopener noreferrer">Staged Event-Driven Architecture (SEDA)</a>. The assessment of how well <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Winglang</a> supports the full-fledged Event-Driven part and asynchronous stage implementation (most likely for Handlers) will be the subject of future research. Stay tuned.</p>
<h1>References</h1>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="winglang-publications">Winglang Publications<a class="hash-link" aria-label="Direct link to Winglang Publications" title="Direct link to Winglang Publications" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#winglang-publications">​</a></h2>
<ol>
<li>Elad Ben-Israel, <a href="https://medium.com/@hackingonstuff/cloud-why-so-difficult-%EF%B8%8F-4e9ef1446a64" target="_blank" rel="noopener noreferrer">“Cloud, why so difficult?”</a></li>
<li>Pouya Hallaj, <a href="https://medium.com/@pouyahallaj/wing-programing-language-for-the-cloud-5b8e52348b17" target="_blank" rel="noopener noreferrer">“Wing: Programing language for the cloud”</a></li>
<li>Artem Sokhin, <a href="https://artemsokhin.medium.com/cloud-oriented-language-or-deploy-your-infrastructure-anywhere-with-wing-34f1d32bf336" target="_blank" rel="noopener noreferrer">“Revolutionize Cloud Programming with Wing: A New Cloud-Oriented Language”</a></li>
<li>Jin, <a href="https://medium.com/p/ffc4ec57a192" target="_blank" rel="noopener noreferrer">“Wing Language: Streamlining Cloud-Oriented Programming for Human-AI Collaboration”</a></li>
<li>Sebastian Korfmann, <a href="https://dev.to/skorfmann/a-cloud-development-troubleshooting-treasure-hunt-495c" target="_blank" rel="noopener noreferrer">“A Cloud Development Troubleshooting Treasure Hunt”</a></li>
<li>Jesse Warden, <a href="https://www.linkedin.com/pulse/wing-programming-language-cloud-jesse-warden/" target="_blank" rel="noopener noreferrer">“Wing — Programming Language for the Cloud”</a></li>
<li>Shai Ber, <a href="https://thenewstack.io/winglang-cloud-development-programming-for-the-ai-era/" target="_blank" rel="noopener noreferrer">“Winglang: Cloud Development Programming for the AI Era”</a></li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="my-publications-on-infrastructure-from-code">My Publications on “Infrastructure From Code”<a class="hash-link" aria-label="Direct link to My Publications on “Infrastructure From Code”" title="Direct link to My Publications on “Infrastructure From Code”" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#my-publications-on-infrastructure-from-code">​</a></h2>
<ol>
<li>Asher Sterkin, <a href="https://medium.com/analytics-vidhya/if-your-computer-is-cloud-how-its-operating-system-should-look-like-24f62e274a95" target="_blank" rel="noopener noreferrer">“If your Computer is the Cloud, what should its Operating System look like?”</a></li>
<li>Asher Sterkin, <a href="https://medium.com/@asher-sterkin/cloud-application-infrastructure-from-code-ifc-398140babf13" target="_blank" rel="noopener noreferrer">“Cloud Application Infrastructure from Code (IfC): The Next Logical Step in Cloud Automation”</a></li>
<li>Asher Sterkin, <a href="https://medium.com/@asher-sterkin/4-pillars-of-the-infrastructure-from-code-5146c8f1dd59" target="_blank" rel="noopener noreferrer">“4 Pillars of the “Infrastructure from Code”</a></li>
<li>Asher Sterkin, <a href="https://medium.com/@asher-sterkin/ifc-2023-technology-landscape-6953ff9ab9e5" target="_blank" rel="noopener noreferrer">“IfC-2023: Technology Landscape”</a></li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="hexagonal-architecture">Hexagonal Architecture<a class="hash-link" aria-label="Direct link to Hexagonal Architecture" title="Direct link to Hexagonal Architecture" href="https://www.winglang.io/blog/2024/1/30/hello-winglang-hexagon#hexagonal-architecture">​</a></h2>
<ol>
<li>Alistar Cockburn, <a href="https://alistair.cockburn.us/hexagonal-architecture/" target="_blank" rel="noopener noreferrer">“Hexagonal architecture”</a></li>
<li>Robert C. Martin, <a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" target="_blank" rel="noopener noreferrer">“Clean Architecture”</a></li>
<li>Krzysztof Słomka, <a href="https://kisztof.medium.com/hexagonal-architecture-with-nest-js-and-typescript-f181cc7b6452" target="_blank" rel="noopener noreferrer">“Hexagonal Architecture with Nest.js and TypeScript”</a></li>
<li>Sairyss, <a href="https://github.com/Sairyss/domain-driven-hexagon" target="_blank" rel="noopener noreferrer">“Domain-Driven Hexagon”</a></li>
<li>Carlos Cunha, <a href="https://betterprogramming.pub/how-to-ports-and-adapter-with-typescript-32a50a0fc9eb" target="_blank" rel="noopener noreferrer">“A Hexagonal Approach to Writing Microservices for Scalable and Decentralized Business: How to use Ports and Adapter with TypeScript”</a></li>
<li>Walid Karray, <a href="https://medium.com/@walid.karray/building-a-todo-app-with-typescript-using-clean-hexagonal-architecture-a-detailed-look-at-the-d9e177f9f31" target="_blank" rel="noopener noreferrer">“Building a Todo App with TypeScript Using Clean Architecture: A Detailed Look at the Directory Structure”</a></li>
<li>Andy Blackledge, <a href="https://aws.hashnode.com/hexagonal-architecture-with-cdk-lambda-and-typescript" target="_blank" rel="noopener noreferrer">“Hexagonal Architecture with CDK, Lambda, and TypeScript”</a></li>
<li>Dyarlen Iber, <a href="https://dev.to/dyarleniber/hexagonal-architecture-and-clean-architecture-with-examples-48oi" target="_blank" rel="noopener noreferrer">“Hexagonal Architecture and Clean Architecture (with examples)”</a></li>
<li>Khalil Stemmler, <a href="https://khalilstemmler.com/articles/enterprise-typescript-nodejs/clean-nodejs-architecture/" target="_blank" rel="noopener noreferrer">“Clean Node.js Architecture”</a></li>
<li>James Beswick, Luca Mezzalira, <a href="https://aws.amazon.com/blogs/compute/developing-evolutionary-architecture-with-aws-lambda/" target="_blank" rel="noopener noreferrer">“Developing evolutionary architecture with AWS Lambda”</a></li>
<li>Adam Fanello, <a href="https://github.com/onicagroup/hexagonal-example" target="_blank" rel="noopener noreferrer">“Hexagonal Architecture by Example (in TypeScript)<strong>”</strong></a></li>
<li>Royi Benita, <a href="https://betterprogramming.pub/clean-node-js-architecture-with-nestjs-and-typescript-34b9398d790f" target="_blank" rel="noopener noreferrer">“Clean Node.js Architecture — With NestJs and TypeScript”</a></li>
</ol>]]></content:encoded>
            <author>asher.sterkin@gmail.com (Asher Sterkin)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>winglang</category>
            <category>platforms</category>
        </item>
        <item>
            <title><![CDATA[Crafting Custom Platforms in a Cloudy World]]></title>
            <link>https://www.winglang.io/blog/2024/01/04/platforms-building-part1</link>
            <guid>https://www.winglang.io/blog/2024/01/04/platforms-building-part1</guid>
            <pubDate>Thu, 04 Jan 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[How to build a Wing Custom Platform]]></description>
            <content:encoded><![CDATA[<p>Wow its 2024, almost a quarter of the way through the 21st century, if you are reading this you probably should pat yourself on the back, because you did it! You have survived the crazy roller coaster ride that has lingered over the last several years, ranging from a pandemic to global insecurity with ongoing wars.</p>
<p>So finally 2024 is here, and we all get to ask ourselves, "Is this the year things finally start going back to normal?"... probably not! Though, as we all sit on the edge of our seats waiting for the next global crisis (my bingo card has mole people rising to the surface) we can take solace in one silver lining. Wing Custom Platforms are all the rage, and easier than ever to build!</p>
<p>In this blog series I'm going to be walking through how to build, publish, and use your own Wing Custom Platforms. Now before we get too deep, and since this is the first installment of what will probably be many procrastinated iterations, lets just do a quick level set.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="let-me-introduce-wing">Let me introduce Wing<a class="hash-link" aria-label="Direct link to Let me introduce Wing" title="Direct link to Let me introduce Wing" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#let-me-introduce-wing">​</a></h2>
<p>A programming language for the cloud.</p>
<p>Wing combines infrastructure and runtime code in one language, enabling developers to stay in their creative flow, and to deliver better software, faster and more securely.</p>
<p><img decoding="async" loading="lazy" alt="lightbult-moment" src="https://www.winglang.io/assets/images/platform-building-lightbulb-moment-730178ea3da11ad28c329bd80c7463ac.gif" width="800" height="420" class="img_ev3q"></p>
<p><a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Please star ⭐ Wing</a></p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-are-wing-custom-platforms">What Are Wing Custom Platforms?<a class="hash-link" aria-label="Direct link to What Are Wing Custom Platforms?" title="Direct link to What Are Wing Custom Platforms?" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#what-are-wing-custom-platforms">​</a></h2>
<p>The purpose of the post is not to explain all the dry details of Wing Platforms, thats the job of the Wing docs (I'll provide reference links down below). Rather we want to get into the fun of building one, so Ill briefly explain.</p>
<p>Wing Custom Platforms offer us a way to hook into a Wing application's compilation process. This is done through various hooks that a custom platform can implement. As of the today, some of these hooks include:</p>
<ul>
<li>preSynth: called before the compiler begins to synthesize, and gives us access to the root app in the construct tree.</li>
<li>postSynth: called right after artifacts are synthesized, and will give us access to manipulate the resulting configuration. In the case of a Terraform provisioner this is the Terraform JSON configuration.</li>
<li>validate: called right after the <code>postSynth</code> hook and provides the same input, however the key difference is the passed config is immutable. Which is important for validation operations</li>
</ul>
<p>There are several other hooks that exist though, we wont go into all those in this blog.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="lets-get-building">Lets Get Building!<a class="hash-link" aria-label="Direct link to Lets Get Building!" title="Direct link to Lets Get Building!" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#lets-get-building">​</a></h2>
<p>One more bit of information we need before we start building our very own Custom Platform which is kind of important is, "what is our platform going to do?"</p>
<p>I'm glad you asked! We are going to build a Custom Platform that will enhance the developer experience when working with Terraform based platforms, some of which come builtin with Wing installation such as <code>tf-aws</code>, <code>tf-azure</code>, and <code>tf-gcp</code>.</p>
<p>The specific enhancement is we want to add is the functionality to configure how Terraform state files are managed through the use of Terraform backends. By default all of the builtin Terraform based platforms will use local state file configurations, which is nice for quick experimentation, but lacks some rigor for production quality deployments.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-goal">The Goal<a class="hash-link" aria-label="Direct link to The Goal" title="Direct link to The Goal" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#the-goal">​</a></h3>
<p>Build and publish a Wing Custom Platform that provides a way to configure your Terraform backend state management.</p>
<p>For the purpose of brevity we will focus on 3 backend types, <code>s3</code>, <code>azurerm</code>, and <code>gcs</code></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="required-materials">Required Materials<a class="hash-link" aria-label="Direct link to Required Materials" title="Direct link to Required Materials" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#required-materials">​</a></h3>
<ul>
<li>Wing</li>
<li>NPM &amp; Node</li>
<li>A bit of Typescript know-hows</li>
<li>A wish and a prayer</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="creating-the-project">Creating The Project<a class="hash-link" aria-label="Direct link to Creating The Project" title="Direct link to Creating The Project" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#creating-the-project">​</a></h2>
<p>To begin lets just create a new npm project, I'm going to be a little bit more bare bones in this guide, so ill just create a <code>package.json</code> and <code>tsconfig.json</code></p>
<p>Below is my <code>package.json</code> file, the only real interesting part about it is the dev dependency on <code>@winglang/sdk</code> this is so we can use some of the exposed Platform types, which we will see an example of soon.</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-json codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"name"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@wingplatforms/tf-backends"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"version"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0.0.1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"main"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"index.js"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"repository"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"type"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"git"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"url"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://github.com/hasanaburayyan/wing-tf-backends"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"license"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ISC"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"devDependencies"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"typescript"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"5.3.3"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"@winglang/sdk"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0.54.30"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"files"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"lib"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Here is the <code>tsconfig.json</code> Ive omitted a few other details for brevity since some other options are just personal preference. Whats worth noting here is how I have decided to structure the project. All my code will exist in a <code>src</code> folder and my expectations are that output of compilation will be in the <code>lib</code> folder. Now you might set your project up different and thats fine, but its worth explaining if you are just following along.</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-json codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"compilerOptions"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"target"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ES2020"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"module"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"commonjs"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"rootDir"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./src"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"outDir"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./lib"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"lib"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"es2020"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"dom"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"include"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"./src/**/*"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"exclude"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"./node_modules"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Then to prep our dependencies we can just run <code>npm install</code></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="lets-code">Lets Code!<a class="hash-link" aria-label="Direct link to Lets Code!" title="Direct link to Lets Code!" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#lets-code">​</a></h3>
<p>Okay now that that initial setup is out of the way, time to start writing our Platform!!</p>
<p>First Ill create a file <code>src/platform.ts</code> this will contain the main code for our Platform, which is used by the Wing compiler. The bare minimum code required for a Platform would look like this</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-typescript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> platform </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@winglang/sdk"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Platform</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">implements</span><span class="token plain"> </span><span class="token class-name">platform</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">IPlatform </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">readonly</span><span class="token plain"> target </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"tf-*"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Here we create and export the our Platform class, which implements the <code>IPlatform</code> interface. All the platform hooks are optional so we don't actually have to define anything else for this to technically be valid.</p>
<p>Now the required bit is defining <code>target</code> this mechanism allows a platform to define the provisioning engine and cloud provider it is compatible with. At the time of this blog post there is not actually an enforcement of this compatibly but... we imagine it works :)</p>
<p>Okay, so we have a barebones Platform but its not actually useful yet, lets change that! First we will plan on using environment variables to determine which type of backend our users want to use, as well as what is the <code>key</code> for the state file.</p>
<p>So we will provide a constructor in our Platform:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-typescript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> platform </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@winglang/sdk"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Platform</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">implements</span><span class="token plain"> </span><span class="token class-name">platform</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">IPlatform </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">readonly</span><span class="token plain"> target </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"tf-*"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">readonly</span><span class="token plain"> backendType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">readonly</span><span class="token plain"> stateFileKey</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">constructor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_BACKEND_TYPE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">TF_BACKEND_TYPE environment variable must be set.</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_STATE_FILE_KEY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"TF_STATE_FILE_KEY environment variable must be set."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendType </span><span class="token operator">=</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_BACKEND_TYPE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">stateFileKey </span><span class="token operator">=</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_STATE_FILE_KEY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Cool, now we are starting to get moving. Our Platform will require the users to have two environment variables set when compiling their Wing code, <code>TF_BACKEND_TYPE</code> and <code>TF_STATE_FILE_KEY</code> for now we will just persist this data as instance variables.</p>
<p>One more house keeping item we need to do is export our Platform code, to do this lets create an <code>index.ts</code> with a single line that looks like this:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-typescript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./platform"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="testing-our-platform">Testing Our Platform<a class="hash-link" aria-label="Direct link to Testing Our Platform" title="Direct link to Testing Our Platform" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#testing-our-platform">​</a></h4>
<p>Before we get much further I just want to show how to test your Platform locally to see it working. In order to test this code we need to first compile it using the command <code>npx tsc</code> and since we already defined everything in our <code>tsconfig.json</code> we will conveniently have a folder named <code>lib</code> that contains all the generated JavaScript code.</p>
<p>Lets create a super simple Wing application to use this Platform with.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// main.w</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The above Wing code will just import the cloud library and use it to create a Bucket resource.</p>
<p>Next we will run a Wing compile command using our Platform in combination with some other Terraform based Platform, in my case it will be <code>tf-aws</code></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing compile main.w --platform tf-aws --platform ./lib</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>Note</strong>: We are providing two Platforms <code>tf-aws</code> and a relative path to our compiled Platform <code>./lib</code> The ordering of these Platforms is also important <code>tf-aws</code> MUST come first since its a Platform that implements the <code>newApp()</code> API. We won't dive deeper into that in this post but the reference reading materials down below will provide links if you want to dive deeper.</p>
<p>Now running this code will result in the following error:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing compile main.w -t tf-aws -t ./lib</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">An error occurred </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">while</span><span class="token plain"> loading the custom platform: Error: TF_BACKEND_TYPE environment variable must be set.</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now before you freak out, just know thats one of them good errors :) we can indeed see our Platform code was loaded and run because the Error was thrown requiring <code>TF_BACKEND_TYPE</code> as an environment variable. If we now rerun the compile command with the required variables we should get a successful compilation</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">TF_BACKEND_TYPE</span><span class="token operator">=</span><span class="token plain">s3 </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">TF_STATE_FILE_KEY</span><span class="token operator">=</span><span class="token plain">mystate.tfstate wing compile main.w -t tf-aws -t ./lib</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To be extra sure the compilation worked we can inspect the generated Terraform code in <code>target/main.tfaws/main.tf.json</code></p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-json codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"//"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"metadata"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"backend"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"local"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"stackName"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"root"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"version"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0.17.0"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"provider"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"aws"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"resource"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"aws_s3_bucket"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"cloudBucket"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"//"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token property">"metadata"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token property">"path"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"root/Default/Default/cloud.Bucket/Default"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token property">"uniqueId"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"cloudBucket"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"bucket_prefix"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"cloud-bucket-c87175e7-"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"force_destroy"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"terraform"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"backend"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"local"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"path"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./terraform.tfstate"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"required_providers"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"aws"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"source"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"aws"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"version"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"5.31.0"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>We should see that a single Bucket is being created, however it is still using the <code>local</code> Terraform backend and that is because we still have some work to do!</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="implementing-the-postsynth-hook">Implementing The postSynth Hook<a class="hash-link" aria-label="Direct link to Implementing The postSynth Hook" title="Direct link to Implementing The postSynth Hook" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#implementing-the-postsynth-hook">​</a></h3>
<p>Since we want to edit the generated Terraform configuration file after the code has been synthesized, we will implement the postSynth hook. As I explained earlier this hook is called right after synthesis completes and passes the resulting configuration file.</p>
<p>What is more useful about this hook is it allows us to return a mutated version of the configuration file.</p>
<p>To implement this hook we will update our Platform code with this</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-typescript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Platform</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">implements</span><span class="token plain"> </span><span class="token class-name">platform</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">IPlatform </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">postSynth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">config</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">any</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">any</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendType </span><span class="token operator">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"s3"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_S3_BACKEND_BUCKET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token string" style="color:rgb(255, 121, 198)">"TF_S3_BACKEND_BUCKET environment variable must be set."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_S3_BACKEND_BUCKET_REGION</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token string" style="color:rgb(255, 121, 198)">"TF_S3_BACKEND_BUCKET_REGION environment variable must be set."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">terraform</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backend </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        s3</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          bucket</span><span class="token operator">:</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_S3_BACKEND_BUCKET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          region</span><span class="token operator">:</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_S3_BACKEND_BUCKET_REGION</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          key</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">stateFileKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now we can see there is some control flow logic happening here, if the user wants to use an <code>s3</code> backend we will need some additional input such as the name and region of the bucket, which we will use <code>TF_S3_BACKEND_BUCKET</code> and <code>TF_S3_BACKEND_BUCKET_REGION</code> to configure.</p>
<p>Assuming all of the required environment variables exist, we can then manipulate the provided config object, where we set <code>config.terraform.backend</code> to use an <code>s3</code> configuration block. Finally the config object is returned.</p>
<p>Now to see this all in action we will need to compile our code (<code>npx tsc</code>) and provide all four required s3 environment variables. To make the commands easier to read Ill do it in multiple lines:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># compile platform code</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">npx tsc</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># set env vars</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">TF_BACKEND_TYPE</span><span class="token operator">=</span><span class="token plain">s3</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">TF_STATE_FILE_KEY</span><span class="token operator">=</span><span class="token plain">mystate.tfstate</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">TF_S3_BACKEND_BUCKET</span><span class="token operator">=</span><span class="token plain">myfavorites3bucket</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">TF_S3_BACKEND_BUCKET_REGION</span><span class="token operator">=</span><span class="token plain">us-east-1</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># compile wing code!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing compile main.w -t tf-aws -t ./lib</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And viola! We should now be able to look at our Terraform config and see that a remote s3 backend is being used:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-json codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// Parts of the config have been omitted for brevity</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"terraform"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"required_providers"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"aws"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"version"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"5.31.0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"source"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"aws"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"backend"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"s3"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"bucket"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"myfavorites3bucket"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"region"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"us-east-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"key"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"mystate.tfstate"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"resource"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"aws_s3_bucket"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"cloudBucket"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"bucket_prefix"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"cloud-bucket-c87175e7-"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"force_destroy"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"//"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token property">"metadata"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token property">"path"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"root/Default/Default/cloud.Bucket/Default"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token property">"uniqueId"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"cloudBucket"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="its-alive">ITS ALIVE!!!<a class="hash-link" aria-label="Direct link to ITS ALIVE!!!" title="Direct link to ITS ALIVE!!!" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#its-alive">​</a></h3>
<p>If you have been following along, pat yourself on the back again! Now on top of surviving the early 2020s you have also written your first Wing Custom Platform!</p>
<p>Now before we go into how to make it available for use to other Wingnuts, lets actually make our code a little cleaner, and a bit more usefully robust.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="supporting-multiple-backends">Supporting Multiple Backends<a class="hash-link" aria-label="Direct link to Supporting Multiple Backends" title="Direct link to Supporting Multiple Backends" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#supporting-multiple-backends">​</a></h2>
<p>In order to live up to its name <code>tf-backends</code> it should probably support multiple backends! To accomplish this lets just use some good ol' coding chops to abstract a bit.</p>
<p>We want our Platform to support <code>s3</code>, <code>azurerm</code>, and <code>gcs</code> to accomplish this we just have to define different <code>config.terraform.backend</code> blocks based on the desired backend.</p>
<p>To make this work I'm going to create a few more files:</p>
<p><code>src/backends/backend.ts</code></p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-typescript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// simple interface to define a backend behavior</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">interface</span><span class="token plain"> </span><span class="token class-name">IBackend</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">generateConfigBlock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">stateFileKey</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now several backend classes that implement this interface</p>
<p><code>src/backends/s3.ts</code></p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-typescript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> IBackend </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./backend"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name constant" style="color:rgb(189, 147, 249)">S3</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">implements</span><span class="token plain"> </span><span class="token class-name">IBackend</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">readonly</span><span class="token plain"> backendBucket</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">readonly</span><span class="token plain"> backendBucketRegion</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">constructor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_S3_BACKEND_BUCKET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"TF_S3_BACKEND_BUCKET environment variable must be set."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_S3_BACKEND_BUCKET_REGION</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"TF_S3_BACKEND_BUCKET_REGION environment variable must be set."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendBucket </span><span class="token operator">=</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_S3_BACKEND_BUCKET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendBucketRegion </span><span class="token operator">=</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_S3_BACKEND_BUCKET_REGION</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">generateConfigBlock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">stateFileKey</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">any</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      s3</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        bucket</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendBucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        region</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendBucketRegion</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        key</span><span class="token operator">:</span><span class="token plain"> stateFileKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><code>src/backends/azurerm.ts</code></p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-ts codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> IBackend </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./backend"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">AzureRM</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">implements</span><span class="token plain"> </span><span class="token class-name">IBackend</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">readonly</span><span class="token plain"> backendStorageAccountName</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">readonly</span><span class="token plain"> backendStorageAccountResourceGroupName</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">readonly</span><span class="token plain"> backendContainerName</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">constructor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_AZURERM_BACKEND_STORAGE_ACCOUNT_NAME</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"TF_AZURERM_BACKEND_STORAGE_ACCOUNT_NAME environment variable must be set."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_AZURERM_BACKEND_STORAGE_ACCOUNT_RESOURCE_GROUP_NAME</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"TF_AZURERM_BACKEND_STORAGE_ACCOUNT_RESOURCE_GROUP_NAME environment variable must be set."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_AZURERM_BACKEND_CONTAINER_NAME</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"TF_AZURERM_BACKEND_CONTAINER_NAME environment variable must be set."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendStorageAccountName </span><span class="token operator">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_AZURERM_BACKEND_STORAGE_ACCOUNT_NAME</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendStorageAccountResourceGroupName </span><span class="token operator">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_AZURERM_BACKEND_STORAGE_ACCOUNT_RESOURCE_GROUP_NAME</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendContainerName </span><span class="token operator">=</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_AZURERM_BACKEND_CONTAINER_NAME</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">generateConfigBlock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">stateFileKey</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">any</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      azurerm</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        storage_account_name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendStorageAccountName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        resource_group_name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendStorageAccountResourceGroupName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        container_name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendContainerName</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        key</span><span class="token operator">:</span><span class="token plain"> stateFileKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><code>src/backends/gcs.ts</code></p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-ts codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> IBackend </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./backend"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name constant" style="color:rgb(189, 147, 249)">GCS</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">implements</span><span class="token plain"> </span><span class="token class-name">IBackend</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">readonly</span><span class="token plain"> backendBucket</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">constructor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_GCS_BACKEND_BUCKET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"TF_GCS_BACKEND_BUCKET environment variable must be set."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_GCS_BACKEND_PREFIX</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"TF_GCS_BACKEND_PREFIX environment variable must be set."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendBucket </span><span class="token operator">=</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_GCS_BACKEND_BUCKET</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">generateConfigBlock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">stateFileKey</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">any</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      gcs</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        bucket</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendBucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        key</span><span class="token operator">:</span><span class="token plain"> stateFileKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now that we have our backend classes defined, we can update our Platform code to use them. My final Platform code looks like this:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-typescript codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> platform </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@winglang/sdk"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">S3</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./backends/s3"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> IBackend </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./backends/backend"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> AzureRM </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./backends/azurerm"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">GCS</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./backends/gcs"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> Local </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"./backends/local"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// TODO: support more backends: https://developer.hashicorp.com/terraform/language/settings/backends/local</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">SUPPORTED_TERRAFORM_BACKENDS</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"s3"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"azurerm"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"gcs"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Platform</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">implements</span><span class="token plain"> </span><span class="token class-name">platform</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">IPlatform </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">readonly</span><span class="token plain"> target </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"tf-*"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">readonly</span><span class="token plain"> backendType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">readonly</span><span class="token plain"> stateFileKey</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">constructor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_BACKEND_TYPE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">TF_BACKEND_TYPE environment variable must be set. Available options: (</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation constant" style="color:rgb(189, 147, 249)">SUPPORTED_TERRAFORM_BACKENDS</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation function" style="color:rgb(80, 250, 123)">join</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string interpolation"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string interpolation">          </span><span class="token template-string interpolation string" style="color:rgb(255, 121, 198)">", "</span><span class="token template-string interpolation"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string interpolation">        </span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">)</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">!</span><span class="token plain">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_STATE_FILE_KEY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"TF_STATE_FILE_KEY environment variable must be set."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendType </span><span class="token operator">=</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_BACKEND_TYPE</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">stateFileKey </span><span class="token operator">=</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">TF_STATE_FILE_KEY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">postSynth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">config</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">any</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">any</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">terraform</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backend </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getBackend</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">generateConfigBlock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">stateFileKey</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">/**</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">   * Determine which backend class to initialize based on the backend type</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">   *</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">   * @returns the backend instance based on the backend type</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">   */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">getBackend</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> IBackend </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">backendType</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"s3"</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name constant" style="color:rgb(189, 147, 249)">S3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"azurerm"</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">AzureRM</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"gcs"</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name constant" style="color:rgb(189, 147, 249)">GCS</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">default</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">Unsupported backend type: </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string interpolation">            </span><span class="token template-string interpolation keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">backendType</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string interpolation">          </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">, available options: (</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation constant" style="color:rgb(189, 147, 249)">SUPPORTED_TERRAFORM_BACKENDS</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation function" style="color:rgb(80, 250, 123)">join</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string interpolation string" style="color:rgb(255, 121, 198)">", "</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">)</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>BOOM!! Our Platform now supports all 3 different backends we wanted to support!</p>
<p>Feel free to build and test each one.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="publishing-our-platform-for-use">Publishing Our Platform For Use<a class="hash-link" aria-label="Direct link to Publishing Our Platform For Use" title="Direct link to Publishing Our Platform For Use" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#publishing-our-platform-for-use">​</a></h3>
<p>Now I'm not going to explain all the intricate details about how <code>npm</code> packages work, since I would do a poor job of that as indicated by the fact my below examples will use a version <code>0.0.3</code> (third times the charm!)</p>
<p>However if you have followed along thus far you will be able to run the following commands
<strong>Note:</strong> in order to publish this library you will need to have defined a package name that you are authorized to publish to. If you use mine (@wingplatforms/tf-backends) you're gonna have a bed time</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-text codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">```bash</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># compile platform code again</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">npx tsc</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># package your code</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">npm pack</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># publish your package</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">npm publish</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If done right you should see something along the lines of</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> notice </span><span class="token operator">==</span><span class="token operator">=</span><span class="token plain"> Tarball Details </span><span class="token operator">==</span><span class="token operator">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> notice name:          @wingplatforms/tf-backends</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> notice version:       </span><span class="token number">0.0</span><span class="token plain">.3</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> notice filename:      wingplatforms-tf-backends-0.0.3.tgz</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> notice package size:  </span><span class="token number">36.8</span><span class="token plain"> kB</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> notice unpacked size: </span><span class="token number">119.5</span><span class="token plain"> kB</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> notice shasum:        0186c558fa7c1ff587f2caddd686574638c9cc4c</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> notice integrity:     sha512-mWIeg8yRE7CG/</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">..</span><span class="token plain">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain">cT8Kh8q/QwlGg</span><span class="token operator">==</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> notice total files:   </span><span class="token number">17</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> notice</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> notice Publishing to https://registry.npmjs.org/ with tag latest and default access</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="using-the-published-platform">Using The Published Platform<a class="hash-link" aria-label="Direct link to Using The Published Platform" title="Direct link to Using The Published Platform" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#using-the-published-platform">​</a></h2>
<p>With the Platform created lets try it out.
<strong>Note</strong>: I suggest using a clean directory for playing with it</p>
<p>Using the same simple Wing application as before</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-text codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">// main.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">new cloud.Bucket()</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>We need to add one more thing to use a Custom Platform, a <code>package.json</code> file which only needs to define the published Platform as a dependency:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-json codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"dependencies"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"@wingplatforms/tf-backends"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0.0.3"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>With both those files create lets install our custom Platform using <code>npm install</code></p>
<p>Finally we lets set up all the environment variables for GCS and run our Wing compile command. <strong>Note</strong>: since we are using a installed npm library we will provide the package name and not <code>./lib</code> anymore!</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-bash codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token builtin class-name" style="color:rgb(189, 147, 249)">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">TF_BACKEND_TYPE</span><span class="token operator">=</span><span class="token plain">gcs</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">TF_STATE_FILE_KEY</span><span class="token operator">=</span><span class="token plain">mystate.tfstate</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">TF_GCS_BACKEND_BUCKET</span><span class="token operator">=</span><span class="token plain">mygcsbucket</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing compile main.w -t tf-aws -t @wingplatforms/tf-backends</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now we should be able to see that the generated Terraform config is using the correct remote backend!</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-json codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"terraform"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"required_providers"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"aws"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"version"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"5.31.0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"source"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"aws"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"backend"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"gcs"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"bucket"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"mygcsbucket"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"key"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"mystate.tfstate"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"resource"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"aws_s3_bucket"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"cloudBucket"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"bucket_prefix"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"cloud-bucket-c87175e7-"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"force_destroy"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"//"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token property">"metadata"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token property">"path"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"root/Default/Default/cloud.Bucket/Default"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token property">"uniqueId"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"cloudBucket"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="whats-next">Whats Next?<a class="hash-link" aria-label="Direct link to Whats Next?" title="Direct link to Whats Next?" href="https://www.winglang.io/blog/2024/01/04/platforms-building-part1#whats-next">​</a></h2>
<p>Now that we have built and published our first Wing Custom Platform, the sky is the limit! Get out there and start building the Custom Platforms to your hearts content &lt;3 and keep a look out for the next addition to this series on Platform building!</p>
<p>In the meantime make sure you to join the Wing Discord community: <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">https://t.winglang.io/discord</a> and share what you are working on, or any issues you run into.</p>
<p>Want to read more about Wing Platforms? Check out the <a href="https://www.winglang.io/docs/concepts/platforms" target="_blank" rel="noopener noreferrer">Wing Platform Docs</a></p>
<ul>
<li>
<p>Check out the <a href="https://www.winglang.io/docs/concepts/platforms" target="_blank" rel="noopener noreferrer">Wing Platform Docs</a></p>
</li>
<li>
<p>Feel free to checkout the full source code at: <a href="https://github.com/hasanaburayyan/wing-tf-backends" target="_blank" rel="noopener noreferrer">https://github.com/hasanaburayyan/wing-tf-backends</a></p>
</li>
</ul>
<hr>
<p>If you enjoyed this article <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">Please star ⭐ Wing</a></p>]]></content:encoded>
            <author>hasana@wing.cloud (Hasan Abu-Rayyan)</author>
            <category>cloud-oriented</category>
            <category>programming</category>
            <category>winglang</category>
            <category>platforms</category>
        </item>
        <item>
            <title><![CDATA[Inflight Magazine no. 6]]></title>
            <link>https://www.winglang.io/blog/2023/12/21/magazine-006</link>
            <guid>https://www.winglang.io/blog/2023/12/21/magazine-006</guid>
            <pubDate>Thu, 21 Dec 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Updates from the Winglang project]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>The 6th issue of the Wing Inflight Magazine.</p>
</blockquote>
<p>Hey folks!</p>
<p>We are back with another issue of the <strong>Wing Inflight Magazine</strong> and excited to share some updates about the <a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">Winglang</a> project.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="an-open-source-programming-language-for-the-cloud">An open source programming language for the cloud<a class="hash-link" aria-label="Direct link to An open source programming language for the cloud" title="Direct link to An open source programming language for the cloud" href="https://www.winglang.io/blog/2023/12/21/magazine-006#an-open-source-programming-language-for-the-cloud">​</a></h3>
<p>Winglang is an open-source programming language for the cloud. It combines infrastructure and runtime into a single programming model, making it easy for any developer
to build serverless cloud-native applications without having to become a DevOps expert.</p>
<p>Winglang code compiles to Terraform + JavaScript and can be deployed on AWS, GCP and Azure (see <a href="https://www.winglang.io/docs/api/standard-library/compatibility-matrix" target="_blank" rel="noopener noreferrer">support matrix</a>).</p>
<p>Winglang is designed to be a familiar and friendly language to learn for developers who come from modern object-oriented background, so it will take you <a href="https://github.com/winglang/workshop-react/blob/main/cheatsheet.md" target="_blank" rel="noopener noreferrer">5 minutes</a> to learn.</p>
<p>Check out our <a href="https://www.winglang.io/docs/" target="_blank" rel="noopener noreferrer">getting started tutorial</a> or hit the Wing Playground for an online experience.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="in-todays-issue">In today's issue<a class="hash-link" aria-label="Direct link to In today's issue" title="Direct link to In today's issue" href="https://www.winglang.io/blog/2023/12/21/magazine-006#in-todays-issue">​</a></h3>
<ul>
<li>🚀 <a href="https://www.winglang.io/blog/2023/12/21/magazine-006#introducing-custom-platforms">New: Introducing custom platforms</a></li>
<li>🚀 <a href="https://www.winglang.io/blog/2023/12/21/magazine-006#singletons-the-wing-way">New: Singletons, the Wing way</a></li>
<li>🔥 <a href="https://www.winglang.io/blog/2023/12/21/magazine-006#string-interpolation-syntax-is-getting-a-face-lift">String interpolation syntax is getting a face lift</a></li>
<li>🔥 <a href="https://www.winglang.io/blog/2023/12/21/magazine-006#constructors-are-now-called-new-instead-of-init">Constructors are now called <code>new()</code> instead of <code>init()</code></a></li>
<li>🔥 <a href="https://www.winglang.io/blog/2023/12/21/magazine-006#httpfetch-response-body-is-not-optional-anymore"><code>http.fetch()</code> response <code>body</code> is not optional anymore</a></li>
<li>🚀 <a href="https://www.winglang.io/blog/2023/12/21/magazine-006#down-casting-from-cloud-to-aws">New: Down-casting from <code>cloud.*</code> to <code>aws.*</code></a></li>
<li>🚀 <a href="https://www.winglang.io/blog/2023/12/21/magazine-006#sourcemaps-and-stacktraces">New: Sourcemaps and Stacktraces</a></li>
<li>📅 <a href="https://www.winglang.io/blog/2023/12/21/magazine-006#upcoming-events">Upcoming Events</a></li>
<li>🎥 <a href="https://www.winglang.io/blog/2023/12/21/magazine-006#the-wingly-update">The Wingly Update</a></li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="introducing-custom-platforms">Introducing custom platforms<a class="hash-link" aria-label="Direct link to Introducing custom platforms" title="Direct link to Introducing custom platforms" href="https://www.winglang.io/blog/2023/12/21/magazine-006#introducing-custom-platforms">​</a></h3>
<p>An integral part of Wing's power comes from the use of <a href="https://www.winglang.io/docs/concepts/platforms" target="_blank" rel="noopener noreferrer">platform providers</a>. Platform providers are libraries which specify how and where your application is deployed. They determine both the cloud environment (e.g. AWS, GCP, Azure) and the provisioning engine (e.g. Terraform, CloudFormation) that the application will be deployed with.</p>
<p>Today, Wing is shipped with the following built-in platforms:</p>
<ul>
<li><code>sim</code> - runs your entire app on a single machine. Used for development with the Wing Console or for unit tests with <code>wing test</code>.</li>
<li><code>tf-aws</code>, <code>tf-azure</code>, <code>tf-gcp</code> - deployes your app to AWS, Azure or GCP using Terraform.</li>
<li><code>awscdk</code> - deploys your app to AWS using the AWS CDK (CloudFormation).</li>
</ul>
<p>Platform providers can also hook into the compliation process to perform any type of "bellow the abstraction" customization during preflight, either on the construct nodes or directly on the output Terraform our CloudFormation.</p>
<p>Built-in platforms look the same as our previously supported targets:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing compile </span><span class="token operator">-</span><span class="token plain">t tf</span><span class="token operator">-</span><span class="token plain">aws</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing compile </span><span class="token operator">--</span><span class="token plain">platform tf</span><span class="token operator">-</span><span class="token plain">aws</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Platform providers can also be composed together:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">wing compile </span><span class="token operator">--</span><span class="token plain">platform tf</span><span class="token operator">-</span><span class="token plain">aws </span><span class="token operator">--</span><span class="token plain">platform tf</span><span class="token operator">-</span><span class="token plain">aws</span><span class="token operator">-</span><span class="token plain">soc2</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Check out our documentation about <a href="https://www.winglang.io/docs/concepts/platforms" target="_blank" rel="noopener noreferrer">platforms</a> for more details.</p>
<p>❤️ <a href="https://github.com/hasanaburayyan" target="_blank" rel="noopener noreferrer">Hasan Abu-Rayan</a> ❤️</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="singletons-the-wing-way">Singletons, the Wing way<a class="hash-link" aria-label="Direct link to Singletons, the Wing way" title="Direct link to Singletons, the Wing way" href="https://www.winglang.io/blog/2023/12/21/magazine-006#singletons-the-wing-way">​</a></h3>
<p>There are situations where it makes sense for a certain resource to have only a single
instance within a Wing application.
To facilitate that, we are now making it easy to access the root node of the app through <code>Node.of(this).root</code>. Then, with <code>tryFindChild()</code> you can get to singleton nirvana:</p>
<p>A common use cases for singletons in Wing is to add a <a href="https://registry.terraform.io/browse/providers" target="_blank" rel="noopener noreferrer">Terraform provider</a> only once. Other examples could be a shared resource such as a VPC that other resources across the app can use.</p>
<p>Check this out:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">SingletonBucket</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pub </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">static</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">of</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">scope</span><span class="token operator">:</span><span class="token plain"> std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">IResource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Bucket</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> uid </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"SingletonBucket"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> root </span><span class="token operator">=</span><span class="token plain"> std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">of</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">scope</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">root</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> rootNode </span><span class="token operator">=</span><span class="token plain"> std</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">of</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">root</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">unsafeCast</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">rootNode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">tryFindChild</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">uid</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> uid </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> root</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> q1 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Queue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"q1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> store1 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">SingletonBucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">of</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">q1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"singleton"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  store1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">put</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"hello"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"world"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>❤️ <a href="https://github.com/eladb" target="_blank" rel="noopener noreferrer">Elad Ben-Israel</a> ❤️</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="string-interpolation-syntax-is-getting-a-face-lift">String interpolation syntax is getting a face lift<a class="hash-link" aria-label="Direct link to String interpolation syntax is getting a face lift" title="Direct link to String interpolation syntax is getting a face lift" href="https://www.winglang.io/blog/2023/12/21/magazine-006#string-interpolation-syntax-is-getting-a-face-lift">​</a></h3>
<p>We decided to change the syntax of string interpolations from <code>${foo}</code> to <code>{foo}</code>. It's a stylistic choice which also offers better ergonomics in the IDE (you can just select a portion of the string and click <code>{</code> to get that portion interpolated).</p>
<p>Unsurprisingly, this change stirred a major emotional response in our team, and we would love to hear what people think about it.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> s1 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"hello"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Before</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> s2 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"${s1}, world"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// After</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> s3 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"{s1}, world"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>❤️ <a href="https://github.com/yoav-steinberg" target="_blank" rel="noopener noreferrer">Yoav Steinberg</a> ❤️</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="constructors-are-now-called-new-instead-of-init">Constructors are now called <code>new()</code> instead of <code>init()</code><a class="hash-link" aria-label="Direct link to constructors-are-now-called-new-instead-of-init" title="Direct link to constructors-are-now-called-new-instead-of-init" href="https://www.winglang.io/blog/2023/12/21/magazine-006#constructors-are-now-called-new-instead-of-init">​</a></h3>
<p>Another stylistic choice (this one with much less pushback) was to change the name of class constructors to <code>new()</code> instead of <code>init()</code>:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Nice</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">isNice</span><span class="token operator">:</span><span class="token plain"> bool</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">isNice</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>❤️ <a href="https://github.com/eladb" target="_blank" rel="noopener noreferrer">Elad Ben-Israel</a> ❤️</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="httpfetch-response-body-is-not-optional-anymore"><code>http.fetch()</code> response <code>body</code> is not optional anymore<a class="hash-link" aria-label="Direct link to httpfetch-response-body-is-not-optional-anymore" title="Direct link to httpfetch-response-body-is-not-optional-anymore" href="https://www.winglang.io/blog/2023/12/21/magazine-006#httpfetch-response-body-is-not-optional-anymore">​</a></h3>
<p>To streamline the interaction with HTTP responses, we've changed the <code>body</code> field of <code>HttpResponse</code> (returned from <code>http.fetch()</code>, <code>http.get()</code>, etc)
to return a non-optional <code>str</code> instead of <code>str?</code>. If there is no body, the <code>body</code> will an empty string (<code>""</code>).</p>
<p>This means that, for example, you can simply call <code>Json.parse(response.body)</code> or <code>Struct.parseJson(response.body)</code> and move on with your life.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"wingly"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> http</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"https://someapi.org"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> jsonBody </span><span class="token operator">=</span><span class="token plain"> </span><span class="token maybe-class-name">Json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// 💝</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>❤️ <a href="https://github.com/Chriscbr" target="_blank" rel="noopener noreferrer">Chris Rybicki</a> ❤️</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="down-casting-from-cloud-to-aws">Down-casting from <code>cloud.*</code> to <code>aws.*</code><a class="hash-link" aria-label="Direct link to down-casting-from-cloud-to-aws" title="Direct link to down-casting-from-cloud-to-aws" href="https://www.winglang.io/blog/2023/12/21/magazine-006#down-casting-from-cloud-to-aws">​</a></h3>
<p>Winglang now supports a way to cast down an abstract <code>cloud.Bucket</code> or any Wing Cloud Library resource into its AWS counterpart.
This makes it easy to access AWS-specific attributes (such as ARNs) given a <code>cloud</code> resoufce.</p>
<p>For example, let's say we want to obtain the ARN of an S3 Bucket:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring aws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> bucket </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> b </span><span class="token operator">=</span><span class="token plain"> aws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> bucketArn </span><span class="token operator">=</span><span class="token plain"> b</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">bucketArn</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>Notice that <code>aws.Bucket.from()</code> returns an optional (<code>str?</code>), which will be <code>nil</code> in case the casting failed. This makes it easy to write
code that's conditional on the target platform.</p>
</blockquote>
<p>❤️ <a href="https://github.com/marciocadev" target="_blank" rel="noopener noreferrer">Marcio Cruz</a> ❤️</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="sourcemaps-and-stacktraces">Sourcemaps and Stacktraces<a class="hash-link" aria-label="Direct link to Sourcemaps and Stacktraces" title="Direct link to Sourcemaps and Stacktraces" href="https://www.winglang.io/blog/2023/12/21/magazine-006#sourcemaps-and-stacktraces">​</a></h3>
<p>We've added <a href="https://developer.chrome.com/blog/sourcemaps" target="_blank" rel="noopener noreferrer">source maps</a> to the generated JavaScript output. These are used, for example, to show <code>.w</code> files in stack traces emitted in errors.</p>
<p>As an example, the <code>except.equal()</code> call fails (because 5 != 8) and the stack trace ion the error only showed the compiled JavaScript code, now you'll see the <code>.w</code> files:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> x </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> y </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">x </span><span class="token operator">+</span><span class="token plain"> y</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">8</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Here's how this looks now:</p>
<p><img decoding="async" loading="lazy" alt="sourcemaps_and_stacktraces_after" src="https://www.winglang.io/assets/images/wing_sourcemaps_stacktraces_after-a088a0242751d33136099b7cda004a1e.png" width="1036" height="276" class="img_ev3q"></p>
<p>❤️ <a href="https://github.com/MarkMcCulloh" target="_blank" rel="noopener noreferrer">Mark McCulloh</a> ❤️</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="upcoming-events">Upcoming Events<a class="hash-link" aria-label="Direct link to Upcoming Events" title="Direct link to Upcoming Events" href="https://www.winglang.io/blog/2023/12/21/magazine-006#upcoming-events">​</a></h3>
<p><strong>🔥 Workshop: Wing + Amazon Bedrock = ❤️ - January 3rd @4:30 - 6pm IST</strong>
Get your hands dirty <a href="https://github.com/ekeren" target="_blank" rel="noopener noreferrer">Eyal Keren</a> as we build together an  application that allows you to load any PDF file and ask questions about it using one of <a href="https://aws.amazon.com/bedrock/" target="_blank" rel="noopener noreferrer">Amazon Bedrock</a>'s generative AI models.
<a href="https://www.eventbrite.com/e/amazon-bedrock-winglang-tickets-769562721817?aff=oddtdtcreator" target="_blank" rel="noopener noreferrer">Reserve your spot</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-wingly-update">The Wingly Update<a class="hash-link" aria-label="Direct link to The Wingly Update" title="Direct link to The Wingly Update" href="https://www.winglang.io/blog/2023/12/21/magazine-006#the-wingly-update">​</a></h3>
<p><strong><a href="https://www.twitch.tv/winglangio" target="_blank" rel="noopener noreferrer">The Wingly Update</a></strong> is our weird biweekly stream where we share the latest developments of the project, chat with folks from the cloud industry, geek out and celebrate the beauty of the cloud.</p>
<p>If you haven't been able to catch our show, you can find the complete stack of <a href="https://youtube.com/playlist?list=PL-P8v-FRassZBWsNoSafL_ReO0JO0xJVm&amp;si=trffVrtGGMUZ-SKb" target="_blank" rel="noopener noreferrer">all our episodes here</a>.</p>
<p>Here are a few segments from the previous shows we thought might be interesting to check out:</p>
<ul>
<li><a href="https://www.youtube.com/watch?v=i2ge8MNulqI" target="_blank" rel="noopener noreferrer">Ron Record shares war stories from the early days of open source</a>: In this clip from The Wingly Update #23, <a href="https://github.com/eladb" target="_blank" rel="noopener noreferrer">Elad</a> and <a href="https://github.com/ekeren" target="_blank" rel="noopener noreferrer">Eyal</a> host <a href="https://twitter.com/ronrecord" target="_blank" rel="noopener noreferrer">Ron</a> who has been involved in open-source for the last 30 years! Ron shows us how he added Wing support to <a href="https://kasmweb.com/" target="_blank" rel="noopener noreferrer">Kasm Workspaces</a>, a container streaming platform that runs in your browser.</li>
<li><a href="https://youtu.be/0aMmCFf9K6o" target="_blank" rel="noopener noreferrer">Ben Kehoe talks about serverless, serviceful and everything in between</a>: <a href="https://github.com/eladb" target="_blank" rel="noopener noreferrer">Elad</a> and <a href="https://github.com/ekeren" target="_blank" rel="noopener noreferrer">Eyal</a> are diving deep with <a href="https://twitter.com/ben11kehoe" target="_blank" rel="noopener noreferrer">Ben</a>, who have been one of the most prolific thought leaders in the serverless world about his previous role at iRobot, his journey to educate developers about "serviceful" systems and his upcoming challenge at Siemens.</li>
<li><a href="https://www.youtube.com/watch?v=pS5BK18_7ys&amp;t=1s" target="_blank" rel="noopener noreferrer">Looking to get your hands dirty with some open-source?</a>: <a href="https://github.com/revitalbarletz" target="_blank" rel="noopener noreferrer">Revital</a> and <a href="https://github.com/ekeren" target="_blank" rel="noopener noreferrer">Eyal</a> walk through some of the Wing's <code>good first issues</code>, which are an excellent starting point for contributors who with to take their first steps to contributing to the Wing project.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="community-meetings">Community Meetings<a class="hash-link" aria-label="Direct link to Community Meetings" title="Direct link to Community Meetings" href="https://www.winglang.io/blog/2023/12/21/magazine-006#community-meetings">​</a></h3>
<p>If you are looking to interact more directly with the Wing team, we are hosting a bunch of reccuring meetings. Feel free to pop in any time and hang out with us:</p>
<p><strong><a href="https://calendar.google.com/calendar/event?action=TEMPLATE&amp;tmeid=a3U2dm1lNnNnYzZtMWNwZjZnb3NoZHVvamlfMjAyMzEyMTlUMTQzMDAwWiBjXzBlOWMwZGRmNGIzYjI3N2YyYWVlMzNmMjY0OWNjM2UwMDMwYTY5MjU2ZGI2NDI1OTRhNzdiYWRkOGM2NzhjNDhAZw&amp;tmsrc=c_0e9c0ddf4b3b277f2aee33f2649cc3e0030a69256db642594a77badd8c678c48%40group.calendar.google.com&amp;scp=ALL" target="_blank" rel="noopener noreferrer">Winglang Community Meeting</a></strong> is our bi-weekly gathering where members of our community showcase cool apps, demos, and other projects! The upcoming session is scheduled for Tuesday, December 19th, at 2:30 PM UTC. We look forward to seeing you there!</p>
<p><strong><a href="https://calendar.google.com/calendar/event?action=TEMPLATE&amp;tmeid=ZnFtM3NrbHM0NGZqdTNjZGdyMDg2bHVidXBfMjAyMzEyMThUMTIwMDAwWiBjXzBlOWMwZGRmNGIzYjI3N2YyYWVlMzNmMjY0OWNjM2UwMDMwYTY5MjU2ZGI2NDI1OTRhNzdiYWRkOGM2NzhjNDhAZw&amp;tmsrc=c_0e9c0ddf4b3b277f2aee33f2649cc3e0030a69256db642594a77badd8c678c48%40group.calendar.google.com&amp;scp=ALL" target="_blank" rel="noopener noreferrer">Monday Office Hours</a></strong> is our bi-weekly opportunity for you to share your feedback, thoughts, concerns, or simply drop by to say hi.</p>
<p>You can find details for all our events in the <a href="https://calendar.google.com/calendar/u/0?cid=Y18wZTljMGRkZjRiM2IyNzdmMmFlZTMzZjI2NDljYzNlMDAzMGE2OTI1NmRiNjQyNTk0YTc3YmFkZDhjNjc4YzQ4QGdyb3VwLmNhbGVuZGFyLmdvb2dsZS5jb20" target="_blank" rel="noopener noreferrer">Wingnuts calendar</a>!
We'd love to see you at one or all of them :)</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" href="https://www.winglang.io/blog/2023/12/21/magazine-006#summary">​</a></h3>
<p>That's it for this edition!</p>
<p>If you're not already, stay updated on the latest changes in our <a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">repo</a>.</p>
<p>You'll find us regularly on <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">Discord</a>, so feel free to say hello! Give <a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">winglang.io</a> a visit and take Wing out for a spin.</p>
<p>Catch you in the next update!</p>]]></content:encoded>
            <author>revitalb@wing.cloud (Revital Barletz)</author>
            <author>eladb@wing.cloud (Elad Ben-Israel)</author>
            <author>urib@wing.cloud (Uri Bar)</author>
            <category>cloud-oriented programming</category>
            <category>winglang</category>
            <category>changelog</category>
            <category>newsletter</category>
        </item>
        <item>
            <title><![CDATA[Inflight Magazine no. 7]]></title>
            <link>https://www.winglang.io/blog/2023/12/12/magazine-007</link>
            <guid>https://www.winglang.io/blog/2023/12/12/magazine-007</guid>
            <pubDate>Tue, 12 Dec 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Updates from the Winglang project]]></description>
            <content:encoded><![CDATA[<blockquote>
<p>The 7th issue of the Wing Inflight Magazine.</p>
</blockquote>
<p>Hey folks!</p>
<p>We are back with another issue of the <strong>Wing Inflight Magazine</strong> and excited to share some updates
about the <a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">Winglang</a> project.</p>
<p><em><strong>An open source programming language for the ☁️</strong></em></p>
<p>Winglang combines infrastructure and runtime into a single programming model, making it easy for any
developer to build serverless applications without having to become a DevOps expert.</p>
<p>Winglang compiles to Terraform + JavaScript and can be deployed on AWS, GCP and Azure (see <a href="https://www.winglang.io/docs/api/standard-library/compatibility-matrix" target="_blank" rel="noopener noreferrer">support
matrix</a>).</p>
<p>Winglang is designed to be a familiar and friendly language to learn for developers who come from modern object-oriented background, so it will take you <a href="https://github.com/winglang/workshop-react/blob/main/cheatsheet.md" target="_blank" rel="noopener noreferrer">5 minutes</a> to learn.</p>
<p>Check out our <a href="https://www.winglang.io/docs/" target="_blank" rel="noopener noreferrer">getting started tutorial</a> or hit the Wing Playground for an online experience.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="in-todays-issue">In today's issue<a class="hash-link" aria-label="Direct link to In today's issue" title="Direct link to In today's issue" href="https://www.winglang.io/blog/2023/12/12/magazine-007#in-todays-issue">​</a></h3>
<ul>
<li>🚀 <a href="https://www.winglang.io/blog/2023/12/12/magazine-007#Built-in-support-for-env-files">New: Built-in support for <code>.env</code> files</a></li>
<li>🚀 <a href="https://www.winglang.io/blog/2023/12/12/magazine-007#gcp-support-in-wing-test">New: GCP support in <code>wing test</code></a></li>
<li>🔥 <a href="https://www.winglang.io/blog/2023/12/12/magazine-007#ux-improvements-to-Wing-Console">UX improvements to Wing Console</a></li>
<li>🔥 <a href="https://www.winglang.io/blog/2023/12/12/magazine-007#bring-websockets"><code>bring websockets</code></a></li>
<li>🎥 <a href="https://www.winglang.io/blog/2023/12/12/magazine-007#the-wingly-update">The Wingly Update</a></li>
<li>🎤 <a href="https://www.winglang.io/blog/2023/12/12/magazine-007#the-wingly-workshops">The Wingly Workshops</a></li>
<li>🎭 <a href="https://www.winglang.io/blog/2023/12/12/magazine-007#winglang-community">Winglang Community</a></li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="built-in-support-for-env-files">Built-in support for <code>.env</code> files<a class="hash-link" aria-label="Direct link to built-in-support-for-env-files" title="Direct link to built-in-support-for-env-files" href="https://www.winglang.io/blog/2023/12/12/magazine-007#built-in-support-for-env-files">​</a></h3>
<p><a href="https://www.npmjs.com/package/dotenv" target="_blank" rel="noopener noreferrer"><code>.env</code> files</a> are now automatically loaded across all CLI
workflows (<code>run</code>, <code>test</code>, <code>compile</code>).</p>
<blockquote>
<p>Environment variables can be consumed only <em>during preflight</em> via <code>util.env("VAR")</code>, or <code>tryEnv()</code>
for the risk-averse of us.</p>
</blockquote>
<p>We also support interpolation:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-sh codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">BASE_URL=https://www.winglang.io</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">API_BASE_URL=${BASE_URL}/api</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You can also override environment variables based on the the CLI subcommand:</p>
<ul>
<li><code>.env</code> - Always loaded</li>
<li><code>.env.[mode]</code> - Only loaded in the specified mode (eg. <code>run</code>, <code>compile</code>, <code>test</code>, etc.)</li>
</ul>
<p>❤️ <a href="https://github.com/garysassano" target="_blank" rel="noopener noreferrer">Gary Sassano</a></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="gcp-support-in-wing-test">GCP support in <code>wing test</code><a class="hash-link" aria-label="Direct link to gcp-support-in-wing-test" title="Direct link to gcp-support-in-wing-test" href="https://www.winglang.io/blog/2023/12/12/magazine-007#gcp-support-in-wing-test">​</a></h3>
<p>The Wing Test Framework is one of the coolest things about Wing. It allows developers to write tests
that cover <strong>both infrastructure and runtime code</strong> and can run across multiple cloud platforms.</p>
<p>Now that Google Cloud Platform (GCP) is supported, <code>wing test</code> supports all built-in Terraform
platforms (AWS, Azure and GCP).</p>
<p>For example, the following Wing program includes a test for the <code>store()</code> function:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring cloud</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring util</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> bucket </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">cloud</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">Bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> store </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter literal-property property">data</span><span class="token parameter operator">:</span><span class="token parameter"> str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">put</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"data.txt"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">test </span><span class="token string" style="color:rgb(255, 121, 198)">"store puts data into the bucket"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> data </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"my data "</span><span class="token plain"> </span><span class="token operator">+</span><span class="token plain"> util</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">uuidv4</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">store</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">equal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">bucket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"data.txt"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now, we can run this test within the Wing Simulator (the <code>sim</code> target):</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-console codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">$ wing test main.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pass ─ main.wsim » root/env0/test:store puts data into the bucket</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Tests 1 passed (1)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Test Files 1 passed (1)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Duration 0m1.23s</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>-t</code> flag can be used to compile and deploy this test to the target platform:</p>
<div class="language-console codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-console codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">$ wing test -t tf-gcp main.w</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">✔ Compiling main.w to tf-gcp...</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">⠋ terraform init</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">...</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>❤️ <a href="https://github.com/tsuf239" target="_blank" rel="noopener noreferrer">Tsuf Cohen</a></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="ux-improvements-to-wing-console">UX improvements to Wing Console<a class="hash-link" aria-label="Direct link to UX improvements to Wing Console" title="Direct link to UX improvements to Wing Console" href="https://www.winglang.io/blog/2023/12/12/magazine-007#ux-improvements-to-wing-console">​</a></h3>
<p>We've made some improvements to how Wing Console visualizes connections between nodes.</p>
<p>Before:</p>
<p><img decoding="async" loading="lazy" alt="console-connections-cleanup-before" src="https://www.winglang.io/assets/images/console-connections-cleanup-before-f21b83b79fe2313f2fd87398aa3077cb.png" width="1256" height="700" class="img_ev3q"></p>
<p>After:</p>
<p><img decoding="async" loading="lazy" alt="console-connections-cleanup-before" src="https://www.winglang.io/assets/images/console-connections-cleanup-after-cd62cd5778e1e8e6fc88aee7937acfce.png" width="1240" height="676" class="img_ev3q"></p>
<p>❤️ <a href="https://github.com/skyrpex" target="_blank" rel="noopener noreferrer">Cristian Pallarés</a></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="bring-websockets"><code>bring websockets</code><a class="hash-link" aria-label="Direct link to bring-websockets" title="Direct link to bring-websockets" href="https://www.winglang.io/blog/2023/12/12/magazine-007#bring-websockets">​</a></h3>
<p>A very cool <a href="https://github.com/winglang/winglibs" target="_blank" rel="noopener noreferrer">winglib</a> was born and already <a href="https://www.linkedin.com/posts/marcio-almeida-25891669_winglang-cloud-activity-7146152178737463296-s5gW" target="_blank" rel="noopener noreferrer">making the
rounds</a>
on the internets.</p>
<p>You can now use the <code>websockets</code> library to deploy a WebSocket server. This works in the Wing
Simulator and supported on the AWS platforms (<code>tf-aws</code> and <code>awscdk</code>) backed by API Gateway V2.</p>
<p>Check out the library's
<a href="https://github.com/winglang/winglibs/blob/main/websockets/README.md" target="_blank" rel="noopener noreferrer">README</a> for more details and
examples.</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-sh codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">npm i @winglibs/websockets</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Here's a stupid little example:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring websockets </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> ws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> server </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ws</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">WebSocket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"my-server"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">server</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">onConnect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"client {id} connected"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">server</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">onDisconnect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"client {id} disconnected"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">server</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">onMessage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">id</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"client {id} sent {message}"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Common use case is tracking and maintaining connection pool.</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bring ex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> conections </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">ex</span><span class="token class-name punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token class-name">DynamodbTable</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Connections"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">hashkey</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">attributeDefinitions</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"S"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And here are few usages:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_m3Ux"><pre tabindex="0" class="prism-code language-js codeBlock_qGQc thin-scrollbar"><code class="codeBlockLines_p187"><span class="token-line" style="color:#F8F8F2"><span class="token plain">ws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">onConnect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  connections</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">putItem</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">item</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token plain"> id </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">onDisconnect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  connections</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">deleteItem</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token literal-property property">key</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token plain"> id </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">onMessage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">inflight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">id</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> conn </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> tb</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">scan</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access maybe-class-name">Items</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    ws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">sendMessage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">fromJson</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">conn</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup_6DOT"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>❤️ <a href="https://github.com/marciocadev" target="_blank" rel="noopener noreferrer">Marcio Cruz</a></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-wingly-update">The Wingly Update<a class="hash-link" aria-label="Direct link to The Wingly Update" title="Direct link to The Wingly Update" href="https://www.winglang.io/blog/2023/12/12/magazine-007#the-wingly-update">​</a></h3>
<p><strong><a href="https://www.twitch.tv/winglangio" target="_blank" rel="noopener noreferrer">The Wingly Update</a></strong> is our weird biweekly stream where we
share the latest developments of the project, chat with folks from the cloud industry, geek out and
celebrate the beauty of the cloud.</p>
<p>If you haven't been able to catch our show, you can find the complete stack of <a href="https://youtube.com/playlist?list=PL-P8v-FRassZBWsNoSafL_ReO0JO0xJVm&amp;si=trffVrtGGMUZ-SKb" target="_blank" rel="noopener noreferrer">all our episodes
here</a>.</p>
<p>Here are a few segments from the previous shows we thought might be interesting to check out:</p>
<ul>
<li><a href="https://youtu.be/3kFcyzKt3MU" target="_blank" rel="noopener noreferrer">Containers are finally taking flight</a>: In this video from our Wingly Update, Elad and Eyal are playing around with containers in Wing. They show how local simulation works with Docker and how apps can be seamlessly deployed to Kubernetes through Helm. Exciting times!</li>
<li><a href="https://www.youtube.com/watch?v=7jbm0LXulCA" target="_blank" rel="noopener noreferrer">Creating a FIFO Queue</a>: <a href="https://github.com/ekeren" target="_blank" rel="noopener noreferrer">Eyal</a> and <a href="https://github.com/eladcohen" target="_blank" rel="noopener noreferrer">Elad</a> are walking us through on how to create a <em>FIfo</em> Queue!</li>
<li><a href="https://youtu.be/wJVT1DaH8lA" target="_blank" rel="noopener noreferrer">Winglang - How to Build Resources</a>: In this clip from The Wingly Update #21, Elad walks us through building resources in Winglang. Listen in to get some details on more advanced topics such as sim.State and tokens.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="winglang-workshops">Winglang Workshops<a class="hash-link" aria-label="Direct link to Winglang Workshops" title="Direct link to Winglang Workshops" href="https://www.winglang.io/blog/2023/12/12/magazine-007#winglang-workshops">​</a></h3>
<ul>
<li>
<p><a href="https://youtu.be/LMDnTCRXzJU" target="_blank" rel="noopener noreferrer">Deploy React + Winglang to the Cloud Workshop</a>: In this workshop, Eyal constructs a full-fledged React.js application supported by Winglang, early from developing and bundling a React website
up to deploying the site on Amazon S3 with AWS’s Content Delivery Network.</p>
</li>
<li>
<p><a href="https://youtu.be/0o1BYccryNQ" target="_blank" rel="noopener noreferrer">Amazon Bedrock + Winglang Workshop</a>: In the workshop, Eyal shows how to implement a GitHub bot from zero to hero using Amazon Bedrock &amp; Winglang.
In only 90 minutes, you can build an application that allows you to load any PDF file and ask questions about it using one of <a href="https://aws.amazon.com/bedrock/" target="_blank" rel="noopener noreferrer">Amazon
Bedrock</a>'s generative AI models.</p>
</li>
</ul>
<p>If you are looking to interact more directly with the Wing team, we are hosting a bunch of recurring
meetings. Feel free to pop in any time and hang out with us:</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="winglang-community">Winglang Community<a class="hash-link" aria-label="Direct link to Winglang Community" title="Direct link to Winglang Community" href="https://www.winglang.io/blog/2023/12/12/magazine-007#winglang-community">​</a></h3>
<p><strong><a href="https://calendar.google.com/calendar/event?action=TEMPLATE&amp;tmeid=a3U2dm1lNnNnYzZtMWNwZjZnb3NoZHVvamlfMjAyMzEyMTlUMTQzMDAwWiBjXzBlOWMwZGRmNGIzYjI3N2YyYWVlMzNmMjY0OWNjM2UwMDMwYTY5MjU2ZGI2NDI1OTRhNzdiYWRkOGM2NzhjNDhAZw&amp;tmsrc=c_0e9c0ddf4b3b277f2aee33f2649cc3e0030a69256db642594a77badd8c678c48%40group.calendar.google.com&amp;scp=ALL" target="_blank" rel="noopener noreferrer">Winglang Community Meeting</a></strong> is our bi-weekly gathering where members of our community showcase cool apps, demos, and other projects! The upcoming session is scheduled for Tuesday, December 19th, at 2:30 PM UTC. We look forward to seeing you there!</p>
<p><strong><a href="https://calendar.google.com/calendar/event?action=TEMPLATE&amp;tmeid=ZnFtM3NrbHM0NGZqdTNjZGdyMDg2bHVidXBfMjAyMzEyMThUMTIwMDAwWiBjXzBlOWMwZGRmNGIzYjI3N2YyYWVlMzNmMjY0OWNjM2UwMDMwYTY5MjU2ZGI2NDI1OTRhNzdiYWRkOGM2NzhjNDhAZw&amp;tmsrc=c_0e9c0ddf4b3b277f2aee33f2649cc3e0030a69256db642594a77badd8c678c48%40group.calendar.google.com&amp;scp=ALL" target="_blank" rel="noopener noreferrer">Monday Office Hours</a></strong> is our bi-weekly opportunity for you to share your feedback, thoughts, concerns, or simply drop by to say hi.</p>
<p>You can find details for all our events in the <a href="https://calendar.google.com/calendar/u/0?cid=Y18wZTljMGRkZjRiM2IyNzdmMmFlZTMzZjI2NDljYzNlMDAzMGE2OTI1NmRiNjQyNTk0YTc3YmFkZDhjNjc4YzQ4QGdyb3VwLmNhbGVuZGFyLmdvb2dsZS5jb20" target="_blank" rel="noopener noreferrer">Wingnuts calendar</a>!
We'd love to see you at one or all of them :)</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" href="https://www.winglang.io/blog/2023/12/12/magazine-007#summary">​</a></h3>
<p>That's it for this edition!</p>
<p>If you're not already, stay updated on the latest changes in our
<a href="https://github.com/winglang/wing" target="_blank" rel="noopener noreferrer">repo</a>.</p>
<p>You'll find us regularly on <a href="https://t.winglang.io/discord" target="_blank" rel="noopener noreferrer">Discord</a>, so feel free to say hello! Give
<a href="https://winglang.io/" target="_blank" rel="noopener noreferrer">winglang.io</a> a visit and take Wing out for a spin.</p>
<p>Catch you in the next update!</p>]]></content:encoded>
            <author>eladb@wing.cloud (Elad Ben-Israel)</author>
            <author>revitalb@wing.cloud (Revital Barletz)</author>
            <author>urib@wing.cloud (Uri Bar)</author>
            <category>cloud-oriented programming</category>
            <category>winglang</category>
            <category>changelog</category>
            <category>newsletter</category>
        </item>
    </channel>
</rss>