<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Voltra</title>
    <description>The latest articles on DEV Community by Voltra (@voltra).</description>
    <link>https://dev.to/voltra</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F525240%2F302c0aef-7a5d-4216-ba16-531b0ef2b4f7.png</url>
      <title>DEV Community: Voltra</title>
      <link>https://dev.to/voltra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/voltra"/>
    <language>en</language>
    <item>
      <title>"Back-end as a Front-end" or How admin dashboards can drive your apps</title>
      <dc:creator>Voltra</dc:creator>
      <pubDate>Wed, 20 Dec 2023 11:31:28 +0000</pubDate>
      <link>https://dev.to/voltra/back-end-as-a-front-end-or-how-admin-dashboards-can-drive-your-apps-57</link>
      <guid>https://dev.to/voltra/back-end-as-a-front-end-or-how-admin-dashboards-can-drive-your-apps-57</guid>
      <description>&lt;h2&gt;
  
  
  A discovery
&lt;/h2&gt;

&lt;p&gt;I was writing a playlist manager app. I had an API server setup, my database setup, and I was working on making a front-end client for it.&lt;/p&gt;

&lt;p&gt;One source of my frustration was the back-and-forth I had to do with the API, the synchronization primitives that would be needed to make it a proper distributed system, and how complicated orchestrating everything could be.&lt;/p&gt;

&lt;p&gt;And then I remembered a piece of tech I stumbled upon a few months prior: &lt;a href="https://filamentphp.com/" rel="noopener noreferrer"&gt;Laravel Filament&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Laravel Filament
&lt;/h2&gt;

&lt;p&gt;Filament is a free admin dashboard (called panel in v3) toolkit/framework that sits on top of Laravel. You define your Laravel app as usual, and you have lots of tools to help build your back-office, including "auto"-generation of forms and tables.&lt;/p&gt;

&lt;p&gt;"Back-end as a Front-end" isn't limited to Filament, and this post isn't about Filament. It's just that I was using Laravel for my API, so I gave it a try.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is "Back-end as a Front-end"
&lt;/h2&gt;

&lt;p&gt;An architectural design pattern. It can also be named "back-office as a front-office".&lt;/p&gt;

&lt;p&gt;It's the idea that your user's space blends in with your admin's space. That the app is nothing more than the admin dashboard itself.&lt;/p&gt;

&lt;p&gt;It's the idea that you might not need a front-end beside the admin dashboard. It's the idea that sometimes, a separate front-end is just redundant.&lt;/p&gt;

&lt;p&gt;One pattern that emerges really quickly when you have this in mind: web apps can be built entirely relying on this principle.&lt;/p&gt;

&lt;p&gt;Why have a decoupled admin panel and user app when you can just have everything be in one place and managed in the same way?&lt;/p&gt;

&lt;h2&gt;
  
  
  What is this architectural pattern good at?
&lt;/h2&gt;

&lt;p&gt;It's really good at tying together every part of your application in one place: the back-end.&lt;/p&gt;

&lt;p&gt;Your user flow is extremely similar to your admin flow? Use this pattern.&lt;/p&gt;

&lt;p&gt;You need job queues? Easy. You need de-duplication? Easy. You need locks? Easy.&lt;/p&gt;

&lt;p&gt;You don't even have an API lying around: your area of attack has been reduced.&lt;/p&gt;

&lt;h2&gt;
  
  
  What can't this pattern do?
&lt;/h2&gt;

&lt;p&gt;Replace all the need for a separate front-end. Not everything can be architectured this way.&lt;/p&gt;

&lt;p&gt;Most SaaS can, but most client-facing apps cannot. Blogs, social media apps, etc. they cannot benefit from it.&lt;/p&gt;

&lt;p&gt;Admin panels are not the sexiest, most user-friendly and most usable pieces of software in the universe. They have one job, and they usually do it well: administering content.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>webdev</category>
    </item>
    <item>
      <title>My first major contribution: More rxjs in vue-use</title>
      <dc:creator>Voltra</dc:creator>
      <pubDate>Sat, 28 Oct 2023 16:31:41 +0000</pubDate>
      <link>https://dev.to/voltra/my-first-major-contribution-more-rxjs-in-vue-use-4neo</link>
      <guid>https://dev.to/voltra/my-first-major-contribution-more-rxjs-in-vue-use-4neo</guid>
      <description>&lt;p&gt;Let me tell you the story of my first (actually relevant) major contribution to an Open Source project: adding more &lt;a href="https://rxjs.dev/guide/overview" rel="noopener noreferrer"&gt;rxjs&lt;/a&gt; in &lt;a href="https://vueuse.org/guide/" rel="noopener noreferrer"&gt;vue-use&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  My approach to Computer Science
&lt;/h2&gt;

&lt;p&gt;I chose Computer Science because I like writing code, and I like solving problems. My approach to open source and Computer Science as a whole is the following:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solve a problem, don't create a problem just to solve it&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My problem
&lt;/h2&gt;

&lt;p&gt;I was rewriting &lt;a href="https://github.com/Voltra/vuelectron-music" rel="noopener noreferrer"&gt;my music player&lt;/a&gt; and had to migrate the existing code from Vue 2 to Vue 3. I also had to, you know, actually finish the damn thing this time.&lt;/p&gt;

&lt;p&gt;One thing I like to do when using Vue (or any other framework) is to completely decouple the business logic from the "application logic". I also like to completely decouple the "framework logic" from the business logic.&lt;/p&gt;

&lt;p&gt;As such, I had written an &lt;code&gt;AudioPlayer&lt;/code&gt; class. Trying to integrate the pieces together, I noticed something: I need an &lt;code&gt;HTMLAudioElement&lt;/code&gt; to construct my &lt;code&gt;AudioPlayer&lt;/code&gt;, but I can only ever get &lt;code&gt;Ref&amp;lt;HTMLAudioElement|null&amp;gt;&lt;/code&gt; if I don't want to use directives.&lt;/p&gt;

&lt;p&gt;That problem was easy enough to solve: make a &lt;code&gt;computed&lt;/code&gt; property and wrap it nicely into a &lt;code&gt;ReadonlyRef&amp;lt;AudioPlayer|null&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then the real issue came up: &lt;code&gt;useObservable&lt;/code&gt; only accepts &lt;code&gt;Observable&amp;lt;T&amp;gt;&lt;/code&gt; as input. I have a &lt;code&gt;ReadonlyRef&amp;lt;AudioPlayer|null&amp;gt;&lt;/code&gt; which can give me a &lt;code&gt;ReadonlyRef&amp;lt;Observable&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt;. I can't make that work with the existing composition functions, but I desperately want to!&lt;/p&gt;

&lt;p&gt;So what did I do? I rolled my own!&lt;/p&gt;

&lt;h2&gt;
  
  
  What's new?
&lt;/h2&gt;

&lt;p&gt;Introducing &lt;a href="https://vueuse.org/rxjs/useExtractedObservable/" rel="noopener noreferrer"&gt;&lt;code&gt;useExtractedObservable&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://vueuse.org/rxjs/watchExtractedObservable/" rel="noopener noreferrer"&gt;&lt;code&gt;watchExtractedObservable&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do they do?
&lt;/h2&gt;

&lt;p&gt;Precisely solve one problem (in two similar yet distinct ways): &lt;strong&gt;The lack of interoperability between Vue's &lt;a href="https://vuejs.org/guide/reusability/composables.html" rel="noopener noreferrer"&gt;composables&lt;/a&gt; and RxJS's &lt;a href="https://rxjs.dev/guide/observable" rel="noopener noreferrer"&gt;observables&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it went
&lt;/h2&gt;

&lt;p&gt;I had wrote a first draft of them for myself, and thought:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If I have that problem, others will.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And thus I forked &lt;code&gt;vue-use&lt;/code&gt;, looked at the implementation of &lt;code&gt;useObservable&lt;/code&gt; and &lt;a href="https://vuejs.org/api/reactivity-core.html#watch" rel="noopener noreferrer"&gt;&lt;code&gt;watch&lt;/code&gt;&lt;/a&gt;, and adapted them to make the new composables.&lt;/p&gt;

&lt;h2&gt;
  
  
  useExtractedObservable
&lt;/h2&gt;

&lt;p&gt;Is a fancier version of &lt;code&gt;useObservable&lt;/code&gt; that, as the name suggests, extracts the observable from something else (aka &lt;a href="https://vuejs.org/guide/essentials/watchers.html#watch-source-types" rel="noopener noreferrer"&gt;watch sources&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;You map your extracted data into an observable, and turn that observable as a &lt;a href="https://vuejs.org/api/reactivity-core.html#ref" rel="noopener noreferrer"&gt;&lt;code&gt;ref&lt;/code&gt;&lt;/a&gt; (well, technically really a &lt;a href="https://vuejs.org/api/reactivity-advanced.html#shallowref" rel="noopener noreferrer"&gt;&lt;code&gt;shallowRef&lt;/code&gt;&lt;/a&gt; for performance reasons).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useExtractedObservable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vueuse/rxjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mapTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startWith&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;takeWhile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs/operators&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;// setup()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useExtractedObservable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;mapTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nf"&gt;startWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nf"&gt;takeWhile&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;immediate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  watchExtractedObservable
&lt;/h2&gt;

&lt;p&gt;Is the love child of &lt;code&gt;watch&lt;/code&gt; and &lt;code&gt;useExtractedObservable&lt;/code&gt;. Instead of getting the new values in a &lt;code&gt;ref&lt;/code&gt;, you instead get to react to them via a callback.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;watchExtractedObservable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vueuse/rxjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AudioPlayer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../my/libs/AudioPlayer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;// setup()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLAudioElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AudioPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nf"&gt;watchExtractedObservable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;progress$&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;percentage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;percentage&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opensource</category>
      <category>vue</category>
      <category>vueuse</category>
      <category>rxjs</category>
    </item>
    <item>
      <title>cpp-as-is: A taste of the future of genericity, in the past</title>
      <dc:creator>Voltra</dc:creator>
      <pubDate>Sun, 10 Sep 2023 14:02:08 +0000</pubDate>
      <link>https://dev.to/voltra/cpp-as-is-a-taste-of-the-future-of-genericity-in-the-past-2k0o</link>
      <guid>https://dev.to/voltra/cpp-as-is-a-taste-of-the-future-of-genericity-in-the-past-2k0o</guid>
      <description>&lt;p&gt;At &lt;a href="https://www.youtube.com/watch?v=raB_289NxBk" rel="noopener noreferrer"&gt;CppCon 2021, Herb Sutter gave a talk&lt;/a&gt; about potential pattern matching in the C++ standard.&lt;/p&gt;

&lt;p&gt;One point in particular held my attention: there are many ways to extract or cast values in C++, but that makes it more difficult to write generic code (e.g. a single templated function).&lt;/p&gt;

&lt;p&gt;He talked about the &lt;a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2392r0.pdf" rel="noopener noreferrer"&gt;P2392 proposal&lt;/a&gt; that introduces two new operators: &lt;code&gt;is&lt;/code&gt; and &lt;code&gt;as&lt;/code&gt;. These features are currently implemented only in &lt;a href="https://www.circle-lang.org/" rel="noopener noreferrer"&gt;Circle&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Voltra/cpp-as-is/tree/dev" rel="noopener noreferrer"&gt;cpp-as-is&lt;/a&gt; &lt;strong&gt;&lt;em&gt;(WIP)&lt;/em&gt;&lt;/strong&gt; is a small library that aims to provide these features today (as long as you have C++17 support).&lt;/p&gt;

&lt;p&gt;The idea came to me from both re-watching that talk, but also deeply thinking about how I could port to C++ the conversion utilities of Rust and how it has both &lt;code&gt;std::convert::From&lt;/code&gt; and &lt;code&gt;std::convert::Into&lt;/code&gt; traits when it really only needs &lt;code&gt;std::convert::Into&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One of my favorite "feature" of C++ is how you can basically use the language to introduce new features and "extend the language", without having to change the language (think Michael Park's &lt;a href="https://github.com/mpark/patterns" rel="noopener noreferrer"&gt;patterns library&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This library sort of follows that principle. The basic idea is to be able to write the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;any&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;optional&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;variant&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;cpp_as_is/cpp_as_is.hpp&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;cpp_as_is&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;inspect_underlying_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;nothing&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;inspect_underlying_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;inspect_underlying_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="n"&gt;inspect_underlying_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;opt2&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;420&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="n"&gt;inspect_underlying_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opt2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/*
Output is:

42
&amp;lt;nothing&amp;gt;
23
420
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without &lt;code&gt;is&lt;/code&gt; and &lt;code&gt;as&lt;/code&gt; you have to write quite a few overloads if you want your one function to handle all cases properly. And the worst part is that you have to do it all over again with every single function.&lt;/p&gt;

&lt;p&gt;Here, you just use two extension points and you're good to go with using &lt;code&gt;is&lt;/code&gt; and &lt;code&gt;as&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;cpp_as_is&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;From&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;To&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;is_conversion_traits&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;arg_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="cm"&gt;/*From*/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/*constexpr*/&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/*arg_type*/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;noexcept&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;From&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;To&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;as_conversion_traits&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;arg_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="cm"&gt;/*From*/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;return_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="cm"&gt;/*To*/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/*constexpr*/&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="cm"&gt;/*return_type*/&lt;/span&gt; &lt;span class="n"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/*arg_type*/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;noexcept&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You also have concepts constraints on &lt;code&gt;is&lt;/code&gt; and &lt;code&gt;as&lt;/code&gt; to make them easier to use and have better error messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;cpp_as_is&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;From&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;To&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;concept&lt;/span&gt; &lt;span class="n"&gt;InspectableWithIs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;From&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;To&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;concept&lt;/span&gt; &lt;span class="n"&gt;IsConvertibleWithAs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's a list of supported conversions (as of now):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;T&lt;/code&gt; -&amp;gt; &lt;code&gt;T&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;T*&lt;/code&gt; -&amp;gt; &lt;code&gt;T&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;std::shared_ptr&amp;lt;T&amp;gt;&lt;/code&gt; -&amp;gt; &lt;code&gt;T&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;std::unique_ptr&amp;lt;T&amp;gt;&lt;/code&gt; -&amp;gt; &lt;code&gt;T&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;std::variant&amp;lt;V1..., T, V2...&amp;gt;&lt;/code&gt; -&amp;gt; &lt;code&gt;T&lt;/code&gt; (and boost alternatives)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;std::any&lt;/code&gt; -&amp;gt; &lt;code&gt;T&lt;/code&gt; (and boost alternatives)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;std::expected&amp;lt;T, E&amp;gt;&lt;/code&gt; -&amp;gt; &lt;code&gt;T&lt;/code&gt; (and boost alternatives)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;std::expected&amp;lt;T, E&amp;gt;&lt;/code&gt; -&amp;gt; &lt;code&gt;std::unexpected&amp;lt;E&amp;gt;&lt;/code&gt; (and boost alternatives)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;std::optional&amp;lt;T&amp;gt;&lt;/code&gt; (and boost alternatives)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;std::future&amp;lt;T&amp;gt;&lt;/code&gt; -&amp;gt; &lt;code&gt;T&lt;/code&gt; (and experimental, and boost alternatives)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cpp</category>
      <category>library</category>
      <category>cpp17</category>
    </item>
    <item>
      <title>IP Info was a mistake, and how digging for the source of the problem is tricky</title>
      <dc:creator>Voltra</dc:creator>
      <pubDate>Mon, 04 Sep 2023 10:03:50 +0000</pubDate>
      <link>https://dev.to/voltra/ip-info-was-a-mistake-and-how-digging-for-the-source-of-the-problem-is-tricky-4b94</link>
      <guid>https://dev.to/voltra/ip-info-was-a-mistake-and-how-digging-for-the-source-of-the-problem-is-tricky-4b94</guid>
      <description>&lt;p&gt;&lt;strong&gt;IP Info&lt;/strong&gt; is the list of information that is publicly available from just having your IP Address (whether that be IPv4 or IPv6).&lt;/p&gt;

&lt;p&gt;Some businesses even use that as their source of income (which I'm pretty sure is illegal).&lt;/p&gt;

&lt;p&gt;So what can you get from an IP Address? Well just about any of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hostname&lt;/li&gt;
&lt;li&gt;City&lt;/li&gt;
&lt;li&gt;Potentially inaccurate zipcode&lt;/li&gt;
&lt;li&gt;Region/State&lt;/li&gt;
&lt;li&gt;Country code&lt;/li&gt;
&lt;li&gt;(I hope inaccurate) latitude and longitude&lt;/li&gt;
&lt;li&gt;Timezone&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Autonomous_system_(Internet)" rel="noopener noreferrer"&gt;ASN&lt;/a&gt; info&lt;/li&gt;
&lt;li&gt;Internet Service Provider info&lt;/li&gt;
&lt;li&gt;Security info (such as whether you're using a VPN, Tor, a proxy, a relay, or if you're hosting a server)&lt;/li&gt;
&lt;li&gt;Abuse contact info&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you ask me, none of that should be available. Or at the very least, not freely available to literally anyone.&lt;/p&gt;

&lt;h2&gt;
  
  
  The question that naturally comes to mind is: &lt;strong&gt;Why the hell is this even available in the first place?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Well, it's a bit complicated. The &lt;a href="https://datatracker.ietf.org/doc/html/rfc791" rel="noopener noreferrer"&gt;RFC 791: IP Protocol&lt;/a&gt; doesn't mention any of it. Neither does &lt;a href="https://datatracker.ietf.org/doc/html/rfc997" rel="noopener noreferrer"&gt;RFC 997: Internet Numbers&lt;/a&gt;, nor &lt;a href="https://datatracker.ietf.org/doc/html/rfc1519" rel="noopener noreferrer"&gt;RFC 1519: CIDR&lt;/a&gt;, nor &lt;a href="https://datatracker.ietf.org/doc/html/rfc1531" rel="noopener noreferrer"&gt;RFC 1531: DCHP&lt;/a&gt;, nor &lt;a href="https://datatracker.ietf.org/doc/html/rfc903" rel="noopener noreferrer"&gt;RFC 903: RARP&lt;/a&gt;, nor &lt;a href="https://datatracker.ietf.org/doc/html/rfc2460" rel="noopener noreferrer"&gt;RFC 2460: IPv6&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Clearly, &lt;strong&gt;&lt;em&gt;it's absolutely not needed for the Internet Protocol (and related stuff) to be functional&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what's going on?
&lt;/h2&gt;

&lt;p&gt;I found &lt;a href="https://datatracker.ietf.org/doc/html/rfc8805" rel="noopener noreferrer"&gt;RFC 8805: A format for self-published geo-location feeds&lt;/a&gt; which explains that at least Google (sigh... not again) accepts such a format. Thus IP prefixes can have geolocation baked in those lists. But that's from 2020.&lt;/p&gt;

&lt;p&gt;There was an abandoned &lt;a href="https://datatracker.ietf.org/doc/html/rfc1876" rel="noopener noreferrer"&gt;RFC 1876: Location within DNS&lt;/a&gt; that the &lt;a href="https://link.springer.com/chapter/10.1007/978-3-540-71617-4_26" rel="noopener noreferrer"&gt;Investigating the Imprecision of IP Block-Based Geolocation&lt;/a&gt; research paper cites, and tells you that alternatives "had" to be used. So it's not in there.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's the need?
&lt;/h2&gt;

&lt;p&gt;The "need", at least as expressed in RFC 8805, is to be able to better serve content to end users. I mean sure, but that only requires one or max two pieces of info: the country and the region/state. &lt;strong&gt;Why the hell is the rest available? Why is it freely and openly available!?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A glimpse at the source?
&lt;/h2&gt;

&lt;p&gt;Turns out that the research paper cited above has one interesting reference: &lt;a href="https://dl.acm.org/doi/10.1145/964723.383073" rel="noopener noreferrer"&gt;An investigation of geographic mapping techniques for internet hosts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This 2001 paper doesn't talk about how things have been done, but how things could be done. And once again, &lt;strong&gt;it's a case of scientists asking themselves whether they could, before asking themselves whether they should.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You think this is bad? Well I'll give you &lt;a href="https://ieeexplore.ieee.org/document/10214926/" rel="noopener noreferrer"&gt;this treat&lt;/a&gt; for you to check out on your free time. The only thing I'll tell you is that it's from 2023...&lt;/p&gt;

&lt;h2&gt;
  
  
  What did we learn?
&lt;/h2&gt;

&lt;p&gt;The Internet Protocol has been plagued by a lack of security that even IPSec cannot help and fix. Scientists have been very eager to help anyone get more and more information about you from simply an IP Address. Why? I guess we'll never know (spoiler: it's greed or scientific stupidity).&lt;/p&gt;

&lt;p&gt;A simple number, used to help in information exchange, now allows people to passively get information about you. A 32 bit number, now gives you access to bytes upon bytes of data on someone.&lt;/p&gt;

&lt;p&gt;That there is a lot of unnecessary endangerment, that should have been trivially avoided. Could there be a legal case to be made? I'd like for that to be true. If even scientists are eager to give out your privacy for free, only that could potentially fix the issue (along with making it "more" illegal I guess).&lt;/p&gt;

&lt;h2&gt;
  
  
  My recommendations?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Never share your IP Address (duh)&lt;/li&gt;
&lt;li&gt;Never (accidentally) expose your IP Address (e.g. using any kind of P2P or direct connections)&lt;/li&gt;
&lt;li&gt;Use any masking tool at your disposal (e.g. VPN, Proxy, etc...)&lt;/li&gt;
&lt;li&gt;Tell your friends, family, etc.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>security</category>
      <category>ip</category>
    </item>
    <item>
      <title>Phone number centric apps are a Security Hazard</title>
      <dc:creator>Voltra</dc:creator>
      <pubDate>Mon, 04 Sep 2023 09:06:18 +0000</pubDate>
      <link>https://dev.to/voltra/phone-number-centric-apps-are-a-security-hazard-3i2d</link>
      <guid>https://dev.to/voltra/phone-number-centric-apps-are-a-security-hazard-3i2d</guid>
      <description>&lt;p&gt;Let's not beat around the bush, using phone numbers as part of the required information for a user simply tells to the world "Look! I make terrible choices when designing software".&lt;/p&gt;

&lt;p&gt;Most of the apps that use them as the primary login/info will also have the tendency of making it visible for the world to see (cc. WhatsApp).&lt;/p&gt;

&lt;p&gt;You also have a username on these apps? They don't care, they'll usually show your phone number before they show your username, or show them side-by-side for... reasons?&lt;/p&gt;

&lt;p&gt;Most of the time, if they have a desktop client, you can even extract a list of phone numbers from a group fairly easily.&lt;/p&gt;

&lt;p&gt;This is an obvious security hazard as, more often than not, the default visibility is "for everyone" instead of "my contacts" which is a baffling choice to say the least.&lt;/p&gt;

&lt;p&gt;Exposing your phone number, just like your IP address, can have... unintended side-effects (we'll dive more on that in a future post).&lt;/p&gt;

&lt;p&gt;Thus far the issues we have listed are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Getting your phone number&lt;/li&gt;
&lt;li&gt;Accessing information they probably shouldn't have&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hackers can even use your phone number as a means for reverse-lookups. Hell, even regular users can since most apps have a "add from my contacts" feature (which is extremely bad for security).&lt;/p&gt;

&lt;p&gt;The other funny thing is... unlike email addresses, phone numbers can usually be re-assigned! Only after your death or any phone number change, sure, but it can still happen.&lt;/p&gt;

&lt;p&gt;Therefore anything that uses phone numbers for let's say 2FA has a fundamental design flaw: too many assumptions.&lt;/p&gt;

&lt;p&gt;Does it prevent spam? Nope. Does it make sure no one can have multiple accounts? Nope. Does it make sure only the owner has access to their account? Not necessarily.&lt;/p&gt;

&lt;p&gt;There is no reason that justifies the use of a phone number beyond sending a verification code. It should never be used as a primary means for identification, authentication or authorization. It should only be used as a secondary one.&lt;/p&gt;

</description>
      <category>security</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Re-imagining Async/Await polyfills</title>
      <dc:creator>Voltra</dc:creator>
      <pubDate>Tue, 22 Aug 2023 12:24:11 +0000</pubDate>
      <link>https://dev.to/voltra/re-imagining-asyncawait-polyfills-1phi</link>
      <guid>https://dev.to/voltra/re-imagining-asyncawait-polyfills-1phi</guid>
      <description>&lt;p&gt;One thing I've always been curious about is: why use generators to polyfill async/await?&lt;/p&gt;

&lt;p&gt;Sure I can see how that can be convenient, taking into account how they work in JavaScript, but why use that approach when there's much better alternatives?&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution: Just write promises
&lt;/h2&gt;

&lt;p&gt;It's as simple as it can get. Async/await are syntactic sugar for promise chains, so why not just translate them to literally that: promise chains.&lt;/p&gt;

&lt;p&gt;Keep track of the results in a state object, that way you have access to them even in future continuation function.&lt;/p&gt;

&lt;p&gt;The only drawback is that you do not get variable shadowing, you get variable overriding. But that could be solved trivially by using a stack-like data structure with push'n'pop mechanisms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;Let me demonstrate my proposed alternative to things like &lt;code&gt;regenerator-runtime&lt;/code&gt;:&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple linear transformation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;KO&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Transforming it should give us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;KO&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's pretty much a line-by-line conversion to a simple promise-based solution.&lt;/p&gt;

&lt;p&gt;If we want to make the transformation uniform, then it could give us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;KO&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  In need of previous results
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;extractData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;extractData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extractedData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extractedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scope-dependent exception handling
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;extractData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApiError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;extractData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extractedData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extractedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApiError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll note that only in the case of error handling do we actually need to nest promises.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finally
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;extractData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApiError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;logStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;extractData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extractedData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extractedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApiError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;logStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, if we want to avoid using &lt;code&gt;Promise#finally&lt;/code&gt; and instead rely on the initial proposed API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;finallyFn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;logStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;extractData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extractedData&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extractedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;extractedData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;finallyFn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApiError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_$res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;finallyFn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_$res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>async</category>
      <category>promises</category>
    </item>
    <item>
      <title>Free Monads for smart optimized code</title>
      <dc:creator>Voltra</dc:creator>
      <pubDate>Sun, 13 Aug 2023 17:42:13 +0000</pubDate>
      <link>https://dev.to/voltra/free-monads-for-smart-optimized-code-onh</link>
      <guid>https://dev.to/voltra/free-monads-for-smart-optimized-code-onh</guid>
      <description>&lt;p&gt;One of the most annoying and complex problem to solve is database querying. When your request is not a simple read or write, it becomes quite complicated to be fully optimal.&lt;/p&gt;

&lt;p&gt;Most of the time, it's due to technical constraints (e.g. a library used makes multiple independent requests instead of batching them somehow).&lt;/p&gt;

&lt;p&gt;What if we could eliminate the problem altogether?&lt;/p&gt;

&lt;p&gt;My proposed solution? Turn your whole application logic into Free Monad program.&lt;/p&gt;

&lt;p&gt;Introducing Free Monads: cool monads that help building eDSL.&lt;/p&gt;

&lt;p&gt;The whole idea is that you make sort of "programs" that are really blueprints for an execution. What makes it extremely interesting is that you can evaluate the same program differently, it's the evaluator that dictates how things work, not the program. The program only has the "shape" of the instructions.&lt;/p&gt;

&lt;p&gt;How is that different from interfaces in OOP you might ask? It's simple, with interfaces you're still operating at a value level. With Free Monad, you're operating at an operation level.&lt;/p&gt;

&lt;p&gt;In a way, you can think of Free Monad programs as a sort of weird AST, and evaluators as visitors.&lt;/p&gt;

&lt;p&gt;Here's the proposed pseudo code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;$program&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AppProgram&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$dbEvaluator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DbAppEvaluator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$queryData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$dbEvaluator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$program&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$responseEvaluator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ResponseEvaluator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$queryData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$responseEvaluator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$program&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$errorHandlerEvaluator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ErrorHandlerEvaluator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$errorHandlerEvaluator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$program&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How cool would that be?&lt;/p&gt;

&lt;p&gt;Things like &lt;code&gt;Database::connect()&lt;/code&gt; wouldn't actually give you a connection object back, but a handle to an operation that has been added to the sequence of the program.&lt;/p&gt;

&lt;p&gt;Thing like &lt;code&gt;Query::table("x")-&amp;gt;select("*")-&amp;gt;where($cond)&lt;/code&gt; wouldn't immediately query to the database, but be an handler. Then the database evaluator would get all the queries, optimize them, and do as little work as possible.&lt;/p&gt;

&lt;p&gt;A whole framework designed like that would eliminate a lot of poor design choices or bad coding practices that lead to poor performances.&lt;/p&gt;

</description>
      <category>functional</category>
      <category>webdev</category>
      <category>database</category>
    </item>
    <item>
      <title>Web Environment Integrity: Google strikes again</title>
      <dc:creator>Voltra</dc:creator>
      <pubDate>Sun, 06 Aug 2023 06:51:11 +0000</pubDate>
      <link>https://dev.to/voltra/web-environment-integrity-google-strikes-again-j4a</link>
      <guid>https://dev.to/voltra/web-environment-integrity-google-strikes-again-j4a</guid>
      <description>&lt;p&gt;The &lt;a href="https://github.com/RupertBenWiser/Web-Environment-Integrity" rel="noopener noreferrer"&gt;Web Environment Integrity&lt;/a&gt; is yet another Google proposal for making the web worse for everyone but them.&lt;/p&gt;

&lt;p&gt;Links of interest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/RupertBenWiser/Web-Environment-Integrity/blob/main/explainer.md" rel="noopener noreferrer"&gt;The explainer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rupertbenwiser.github.io/Web-Environment-Integrity/" rel="noopener noreferrer"&gt;The RFC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/RupertBenWiser/Web-Environment-Integrity" rel="noopener noreferrer"&gt;The Github repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Issues with the RFC
&lt;/h2&gt;

&lt;p&gt;Request For Comments, a nice way to make proposals and ask for comments and feedback. Well, usually when one comes out it's at least polished enough to feel like a complete unit.&lt;/p&gt;

&lt;p&gt;As of today, very crucial and important parts of the RFC are marked as "TODO". Things like, you know, definitions of "web environment" and "content binding", nothing that important /s.&lt;/p&gt;

&lt;p&gt;Hell, even whole sections are missing like "Browser Acceptance Criteria" and &lt;strong&gt;&lt;em&gt;"Privacy considerations"&lt;/em&gt;&lt;/strong&gt; which gives off strong &lt;a href="https://www.youtube.com/watch?v=xNjI03CGkb4&amp;amp;t=40s" rel="noopener noreferrer"&gt;"I'll leave the morality of it out of the talk"&lt;/a&gt; vibes (no that is not a parody, it's an actual serious talk, you should definitely check it out).&lt;/p&gt;

&lt;p&gt;The biggest issue with the RFC is, if you're like me, the first time you read this and looked at the API you certainly thought: "wow... that's actually useless":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Craft a token and... encode it in base64? No asymmetrical encryption? Just Base64? Wth!?&lt;/li&gt;
&lt;li&gt;Cool, but how can it be verified?&lt;/li&gt;
&lt;li&gt;The token is crafted on the user's device and verified on another?&lt;/li&gt;
&lt;li&gt;What is the use exactly?&lt;/li&gt;
&lt;li&gt;What prevents it from being spoofed or polyfilled?&lt;/li&gt;
&lt;li&gt;This is to fight against fingerprinting? But that introduces a wayyyy better way of fingerprinting users, on a literal MAC address/machine level&lt;/li&gt;
&lt;li&gt;You can't remove the need for an anti-virus software on each machine&lt;/li&gt;
&lt;li&gt;Making a "web anti-virus solution" is the single dumbest and most useless idea ever! Sure let's give any website a way to inspect (the integrity of) your memory, that sounds like a great idea!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And of course, these questions are absolutely not addressed in the RFC. All you can read is something that feels like someone's draft of an RFC (that needs to be finalized before being published), not an actual RFC. Which probably means that whoever was behind this idea thought of it last minute and pushed it way too hard to have it go out ASAP.&lt;/p&gt;

&lt;h2&gt;
  
  
  And with the explainer, all the evil is unveiled
&lt;/h2&gt;

&lt;p&gt;You see, before reading the explainer (which is dumb, why external explanation for an RFC) you were already thinking about how this is terrible, a DRM-ization of the web, etc.&lt;/p&gt;

&lt;p&gt;But within the first few lines of the explainer, you actually understand that one of the main goals of this is absolutely not to protect users in any way, but to make sure ads are shown to real users and never bots.&lt;/p&gt;

&lt;p&gt;It's pretty much a Comic book Villain (or politician) tactic: pretend to do things for others' interest, but in reality you do them for your own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Goals
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Allow web servers to evaluate the authenticity of the device and honest representation of the software stack and the traffic from the device.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's a mouthful way of saying "we want website to be able to very accurately fingerprint your device". How's the EU doing btw?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Offer an adversarially robust and long-term sustainable anti-abuse solution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that's just absurd and wishful thinking at best. There's a reason anti-virus and anti-cheat software run at system startup and in a different "context" than other programs... You can't do that from inside a web browser.&lt;/p&gt;

&lt;p&gt;Plus, that would only cover mid-execution corruption. You couldn't detect prior-to-execution corruption like, let's say, a computer full of malware?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don't enable new cross-site user tracking capabilities through attestation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sure, try to act like you won't use that in GA or GTM at all. How's the EU doing btw?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Continue to allow web browsers to browse the Web without attestation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Oh thank god, you actually admit yourself that your proposal is a waste and totally useless since you can just skip it...&lt;/p&gt;

&lt;h3&gt;
  
  
  "Non-goals"
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Enforce or interfere with browser functionality, including plugins and extensions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Oh I'm sure it won't interfere...&lt;/p&gt;

&lt;p&gt;In addition to Manifest V3, you'd also like to further kill extension/plugin users and developers? Wow. You really hate adblockers huh? Despite them being a minority in the vast user base? Are you looking for pennies under the couch Google? I have 4 bucks in my pocket if you want.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Enable reliable client-side validation of verdicts&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes, "reliable client-side" the famous oxymoron. Thank you for "clarifying" that. I hope Google doesn't connect to their production databases directly from the browser...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Access to this functionality from non-Secure Contexts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What do you not get about "non-Secure"? Are you serious?&lt;/p&gt;

&lt;h3&gt;
  
  
  Use cases
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Detect social media manipulation and fake engagement.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So it's not about users. Got it. And how do you plan on doing that exactly?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Detect non-human traffic in advertising to improve user experience and access to web content&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So it's not about users. Got it. And how do you plan on doing that exactly? I'm pretty sure I can make &lt;a href="https://www.selenium.dev/" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt; do things and it'd go through your wide net.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Detect phishing campaigns (e.g. webviews in malicious apps)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How exactly?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Detect bulk hijacking attempts and bulk account creation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How? Oooooh, by fingerprinting of course!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Detect large scale cheating in web based games with fake clients&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See the above about execution contexts of anti-cheat and anti-virus software...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Detect compromised devices where user data would be at risk&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There's no reason a malware-infested system couldn't spoof that. It's not an anti-virus...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Detect account takeover attempts by identifying password guessing&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Literally how? Do you have any idea of the intrinsic unsolvability of the problem you claim this would solve? Why do you think 2FA/MFA exist? Google literally has one of the strictest ones out there, how do you fain ignorance like that?&lt;/p&gt;

&lt;h2&gt;
  
  
  Does the explainer, explain or address anything?
&lt;/h2&gt;

&lt;p&gt;No lmfao. Read it for yourself, it's pretty funny how it makes everything worse than the RFC already did.&lt;/p&gt;

&lt;h2&gt;
  
  
  The final words
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You cannot circumvent the Blind Trust Issue.&lt;/strong&gt; (i.e. the fact that any trust is always blindly given, otherwise it'd be knowledge)&lt;/p&gt;

&lt;p&gt;Hell, the whole thing relies on a 3rd-party attester which is an even bigger joke in and of itself.&lt;/p&gt;

&lt;p&gt;It's not even like HTTPS, DNS Sec, or whatever intelligent and well thought out security thing. That one is just useless junk if you're not Google Ads.&lt;/p&gt;

&lt;p&gt;The only way to circumvent the Blind Trust Issue is to turn trust into knowledge, that much is obvious. The only issue is that you can't have knowledge about a site being compromised (e.g. downloading a renowned browser), that your IP packets are not being intercepted (network layer), that your TCP packets are not being logged or intercepted (ISP), that your machine doesn't have spyware built into the OS, that the software you use is what it's advertised as (that's why we need reproducible builds), etc...&lt;/p&gt;

&lt;p&gt;It's the same thing with "Decentralized Web". You don't eliminate the need for trust at all, you just move it elsewhere.&lt;/p&gt;

</description>
      <category>google</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>A novel idea for (more) deterministic recommendation engines</title>
      <dc:creator>Voltra</dc:creator>
      <pubDate>Wed, 17 May 2023 11:20:59 +0000</pubDate>
      <link>https://dev.to/voltra/an-novel-idea-for-more-deterministic-recommendation-engines-45jk</link>
      <guid>https://dev.to/voltra/an-novel-idea-for-more-deterministic-recommendation-engines-45jk</guid>
      <description>&lt;p&gt;The idea comes from the fact that the search engine of YouTube is pretty decent, but the recommendation one isn't.&lt;/p&gt;

&lt;p&gt;If only we could used that search engine for recommendations...&lt;/p&gt;

&lt;p&gt;That's where Algorithmic Reduction comes in. If we can express our recommendation problem as a search problem, then we can just use the search engine to get our recommendations.&lt;/p&gt;

&lt;p&gt;What's a recommendation engine anyway? Basically (or mathematically), it's a function that takes a &lt;code&gt;User&lt;/code&gt; and returns an ordered list of &lt;code&gt;Item&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What's a search engine? Basically (or mathematically), it's a function that takes a &lt;code&gt;SearchQuery&lt;/code&gt; and returns an ordered list of &lt;code&gt;Item&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What if we could turn a &lt;code&gt;User&lt;/code&gt; into a &lt;code&gt;SearchQuery&lt;/code&gt;? Then the recommendation engine would simply be the composition of the transformer function and the search engine.&lt;/p&gt;

&lt;p&gt;Given that most website collect statistics about their users, this shouldn't be such a daunting task. And given how search engines are usually more deterministic than recommendation engines, then even if that transformer function is a heuristic, this approach should give extremely satisfactory results.&lt;/p&gt;

&lt;p&gt;Potential pitfalls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recommendation engines nowadays have a very strong bias towards how recently an item has been visited by the user (you get more recommendations on the latest 15 videos you've watched). You might want to stray away from that tendency&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>recommendation</category>
      <category>search</category>
      <category>research</category>
    </item>
    <item>
      <title>The misery of Hacktoberfest's reward merch</title>
      <dc:creator>Voltra</dc:creator>
      <pubDate>Wed, 08 Feb 2023 17:52:42 +0000</pubDate>
      <link>https://dev.to/voltra/the-misery-of-hacktoberfests-reward-merch-29ja</link>
      <guid>https://dev.to/voltra/the-misery-of-hacktoberfests-reward-merch-29ja</guid>
      <description>&lt;p&gt;As you may know, one of the rewards you can choose from for participating in Hacktoberfest is the merch.&lt;/p&gt;

&lt;p&gt;As some of you may also know, in the EU (or at least in France), there's a customs' tax for products coming from the US (and a few other countries).&lt;/p&gt;

&lt;p&gt;And instead of ticking the "Gift" box (which makes sense, as that's what this essentially is), they always tick the "Others" box, which forces you to pay Customs Taxes for something you got for free, which is annoying af.&lt;/p&gt;

&lt;p&gt;That's two years in a row, who knows if I'll want to keep this going.&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
    </item>
    <item>
      <title>What is e.defaultPrevented and why library authors MUST use it</title>
      <dc:creator>Voltra</dc:creator>
      <pubDate>Fri, 06 Jan 2023 12:58:00 +0000</pubDate>
      <link>https://dev.to/voltra/what-is-edefaultprevented-and-why-library-authors-must-use-it-2n8m</link>
      <guid>https://dev.to/voltra/what-is-edefaultprevented-and-why-library-authors-must-use-it-2n8m</guid>
      <description>&lt;p&gt;&lt;code&gt;Event#defaultPrevented&lt;/code&gt; is, as per &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Event/defaultPrevented" rel="noopener noreferrer"&gt;MDN&lt;/a&gt;, a flag available on an event to know whether its default action was prevented (regardless of whether &lt;code&gt;Event#preventDefault&lt;/code&gt; was called, but calling it will set the flag to &lt;code&gt;true&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Why do library authors need to use it? Because a listener added by the user calling &lt;code&gt;e.preventDefault()&lt;/code&gt; will not prevent your listeners from being called.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Dogstudio/highway" rel="noopener noreferrer"&gt;&lt;code&gt;@dogstudio/highway&lt;/code&gt;&lt;/a&gt; is one such library that doesn't check for that, and thus preventing the default behavior of an anchor will not prevent further navigation.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;e.defaultPrevented&lt;/code&gt; is here to ensure everyone can safely add listeners and execute them only if they should.&lt;/p&gt;

&lt;p&gt;Should browsers make the check for you? Maybe, but it might get freedom away for some use cases. In the meantime, please check for the flag.&lt;/p&gt;

</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>Dear "developers" who insist they don't need HTTPS, or SSL certificates</title>
      <dc:creator>Voltra</dc:creator>
      <pubDate>Sat, 29 Oct 2022 11:29:26 +0000</pubDate>
      <link>https://dev.to/voltra/dear-developers-who-insist-they-dont-need-https-or-ssl-certificates-2oll</link>
      <guid>https://dev.to/voltra/dear-developers-who-insist-they-dont-need-https-or-ssl-certificates-2oll</guid>
      <description>&lt;p&gt;Please invite me somewhere we can share the same network, you know, so you can showcase your brilliance and websites that don't use HTTPS while I steal every piece of personal data I can.&lt;/p&gt;

&lt;p&gt;Seriously, security is not a fucking joke, stop dicking around...&lt;/p&gt;

</description>
      <category>security</category>
      <category>https</category>
      <category>webdev</category>
      <category>rant</category>
    </item>
  </channel>
</rss>
